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 2015/01/08 14:17:25 UTC
[05/13] syncope git commit: [SYNCOPE-620] server logic in,
tests missing
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/AbstractReportlet.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/AbstractReportlet.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/AbstractReportlet.java
new file mode 100644
index 0000000..8c8661b
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/AbstractReportlet.java
@@ -0,0 +1,66 @@
+/*
+ * 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.report;
+
+import org.apache.syncope.common.lib.report.AbstractReportletConf;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.transaction.annotation.Transactional;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+public abstract class AbstractReportlet<T extends AbstractReportletConf> implements Reportlet<T> {
+
+ /**
+ * Logger.
+ */
+ protected static final Logger LOG = LoggerFactory.getLogger(AbstractReportlet.class);
+
+ protected T conf;
+
+ public T getConf() {
+ return conf;
+ }
+
+ @Override
+ public void setConf(final T conf) {
+ this.conf = conf;
+ }
+
+ protected abstract void doExtract(ContentHandler handler) throws SAXException, ReportException;
+
+ @Override
+ @Transactional(readOnly = true)
+ public void extract(final ContentHandler handler) throws SAXException, ReportException {
+
+ if (conf == null) {
+ throw new ReportException(new IllegalArgumentException("No configuration provided"));
+ }
+
+ AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, conf.getName());
+ atts.addAttribute("", "", ReportXMLConst.ATTR_CLASS, ReportXMLConst.XSD_STRING, getClass().getName());
+ handler.startElement("", "", ReportXMLConst.ELEMENT_REPORTLET, atts);
+
+ doExtract(handler);
+
+ handler.endElement("", "", ReportXMLConst.ELEMENT_REPORTLET);
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportException.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportException.java
new file mode 100644
index 0000000..b8d311b
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportException.java
@@ -0,0 +1,32 @@
+/*
+ * 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.report;
+
+public class ReportException extends RuntimeException {
+
+ private static final long serialVersionUID = 6719507778589395283L;
+
+ public ReportException(final Throwable cause) {
+ super(cause);
+ }
+
+ public ReportException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportJob.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportJob.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportJob.java
new file mode 100644
index 0000000..ca59705
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportJob.java
@@ -0,0 +1,206 @@
+/*
+ * 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.report;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.commons.io.IOUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.report.ReportletConf;
+import org.apache.syncope.common.lib.types.ReportExecStatus;
+import org.apache.syncope.persistence.api.dao.ReportDAO;
+import org.apache.syncope.persistence.api.dao.ReportExecDAO;
+import org.apache.syncope.persistence.api.entity.EntityFactory;
+import org.apache.syncope.persistence.api.entity.Report;
+import org.apache.syncope.persistence.api.entity.ReportExec;
+import org.apache.syncope.server.logic.data.ReportDataBinder;
+import org.apache.syncope.server.spring.ApplicationContextProvider;
+import org.apache.syncope.server.utils.ExceptionUtil;
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Quartz job for executing a given report.
+ */
+@SuppressWarnings("unchecked")
+@DisallowConcurrentExecution
+public class ReportJob implements Job {
+
+ /**
+ * Logger.
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(ReportJob.class);
+
+ /**
+ * Report DAO.
+ */
+ @Autowired
+ private ReportDAO reportDAO;
+
+ /**
+ * Report execution DAO.
+ */
+ @Autowired
+ private ReportExecDAO reportExecDAO;
+
+ /**
+ * Report data binder.
+ */
+ @Autowired
+ private ReportDataBinder dataBinder;
+
+ @Autowired
+ private EntityFactory entityFactory;
+
+ /**
+ * Key, set by the caller, for identifying the report to be executed.
+ */
+ private Long reportKey;
+
+ /**
+ * Report id setter.
+ *
+ * @param reportKey to be set
+ */
+ public void setReportKey(final Long reportKey) {
+ this.reportKey = reportKey;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public void execute(final JobExecutionContext context) throws JobExecutionException {
+ Report report = reportDAO.find(reportKey);
+ if (report == null) {
+ throw new JobExecutionException("Report " + reportKey + " not found");
+ }
+
+ // 1. create execution
+ ReportExec execution = entityFactory.newEntity(ReportExec.class);
+ execution.setStatus(ReportExecStatus.STARTED);
+ execution.setStartDate(new Date());
+ execution.setReport(report);
+ execution = reportExecDAO.save(execution);
+
+ report.addExec(execution);
+ report = reportDAO.save(report);
+
+ // 2. define a SAX handler for generating result as XML
+ TransformerHandler handler;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ZipOutputStream zos = new ZipOutputStream(baos);
+ zos.setLevel(Deflater.BEST_COMPRESSION);
+ try {
+ SAXTransformerFactory tFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+ handler = tFactory.newTransformerHandler();
+ Transformer serializer = handler.getTransformer();
+ serializer.setOutputProperty(OutputKeys.ENCODING, SyncopeConstants.DEFAULT_ENCODING);
+ serializer.setOutputProperty(OutputKeys.INDENT, "yes");
+
+ // a single ZipEntry in the ZipOutputStream
+ zos.putNextEntry(new ZipEntry(report.getName()));
+
+ // streaming SAX handler in a compressed byte array stream
+ handler.setResult(new StreamResult(zos));
+ } catch (Exception e) {
+ throw new JobExecutionException("While configuring for SAX generation", e, true);
+ }
+
+ execution.setStatus(ReportExecStatus.RUNNING);
+ execution = reportExecDAO.save(execution);
+
+ // 3. actual report execution
+ StringBuilder reportExecutionMessage = new StringBuilder();
+ try {
+ // report header
+ handler.startDocument();
+ AttributesImpl atts = new AttributesImpl();
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, report.getName());
+ handler.startElement("", "", ReportXMLConst.ELEMENT_REPORT, atts);
+
+ // iterate over reportlet instances defined for this report
+ for (ReportletConf reportletConf : report.getReportletConfs()) {
+ Class<Reportlet> reportletClass =
+ dataBinder.findReportletClassHavingConfClass(reportletConf.getClass());
+ if (reportletClass != null) {
+ Reportlet<ReportletConf> autowired =
+ (Reportlet<ReportletConf>) ApplicationContextProvider.getBeanFactory().
+ createBean(reportletClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+ autowired.setConf(reportletConf);
+
+ // invoke reportlet
+ try {
+ autowired.extract(handler);
+ } catch (Exception e) {
+ execution.setStatus(ReportExecStatus.FAILURE);
+
+ Throwable t = e instanceof ReportException
+ ? e.getCause()
+ : e;
+ reportExecutionMessage.
+ append(ExceptionUtil.getFullStackTrace(t)).
+ append("\n==================\n");
+ }
+ }
+ }
+
+ // report footer
+ handler.endElement("", "", ReportXMLConst.ELEMENT_REPORT);
+ handler.endDocument();
+
+ if (!ReportExecStatus.FAILURE.name().equals(execution.getStatus())) {
+ execution.setStatus(ReportExecStatus.SUCCESS);
+ }
+ } catch (Exception e) {
+ execution.setStatus(ReportExecStatus.FAILURE);
+ reportExecutionMessage.append(ExceptionUtil.getFullStackTrace(e));
+
+ throw new JobExecutionException(e, true);
+ } finally {
+ try {
+ zos.closeEntry();
+ IOUtils.closeQuietly(zos);
+ IOUtils.closeQuietly(baos);
+ } catch (IOException e) {
+ LOG.error("While closing StreamResult's backend", e);
+ }
+
+ execution.setExecResult(baos.toByteArray());
+ execution.setMessage(reportExecutionMessage.toString());
+ execution.setEndDate(new Date());
+ reportExecDAO.save(execution);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportXMLConst.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportXMLConst.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportXMLConst.java
new file mode 100644
index 0000000..3cd22cd
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportXMLConst.java
@@ -0,0 +1,44 @@
+/*
+ * 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.report;
+
+public final class ReportXMLConst {
+
+ public static final String XSD_STRING = "xsd:string";
+
+ public static final String XSD_INT = "xsd:integer";
+
+ public static final String XSD_LONG = "xsd:long";
+
+ public static final String XSD_BOOLEAN = "xsd:boolean";
+
+ public static final String XSD_DATETIME = "xsd:dateTime";
+
+ public static final String ELEMENT_REPORT = "report";
+
+ public static final String ATTR_NAME = "name";
+
+ public static final String ATTR_CLASS = "class";
+
+ public static final String ELEMENT_REPORTLET = "reportlet";
+
+ private ReportXMLConst() {
+ // empty private constructor for static utility class
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/Reportlet.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/Reportlet.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/Reportlet.java
new file mode 100644
index 0000000..49438bc
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/Reportlet.java
@@ -0,0 +1,47 @@
+/*
+ * 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.report;
+
+import org.apache.syncope.common.lib.report.ReportletConf;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Interface for all elements that can be embedded in a report.
+ *
+ * @see org.apache.syncope.core.persistence.beans.Report
+ */
+public interface Reportlet<T extends ReportletConf> {
+
+ /**
+ * Set this reportlet configuration.
+ *
+ * @param conf configuration
+ */
+ void setConf(T conf);
+
+ /**
+ * Actual data extraction for reporting.
+ *
+ * @param handler SAX content handler for streaming result
+ * @throws SAXException if there is any problem in SAX handling
+ * @throws ReportException if anything goes wrong
+ */
+ void extract(ContentHandler handler) throws SAXException, ReportException;
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportletConfClass.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportletConfClass.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportletConfClass.java
new file mode 100644
index 0000000..48896cc
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/ReportletConfClass.java
@@ -0,0 +1,32 @@
+/*
+ * 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.report;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import org.apache.syncope.common.lib.report.ReportletConf;
+
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ReportletConfClass {
+
+ Class<? extends ReportletConf> value();
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/RoleReportlet.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/RoleReportlet.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/RoleReportlet.java
new file mode 100644
index 0000000..3ffbdfb
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/RoleReportlet.java
@@ -0,0 +1,327 @@
+/*
+ * 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.report;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.report.RoleReportletConf;
+import org.apache.syncope.common.lib.report.RoleReportletConf.Feature;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.RoleDAO;
+import org.apache.syncope.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.role.Role;
+import org.apache.syncope.server.logic.data.RoleDataBinder;
+import org.apache.syncope.server.logic.search.SearchCondConverter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+@ReportletConfClass(RoleReportletConf.class)
+public class RoleReportlet extends AbstractReportlet<RoleReportletConf> {
+
+ private static final int PAGE_SIZE = 10;
+
+ @Autowired
+ private EntitlementDAO entitlementDAO;
+
+ @Autowired
+ private RoleDAO roleDAO;
+
+ @Autowired
+ private SubjectSearchDAO searchDAO;
+
+ @Autowired
+ private RoleDataBinder roleDataBinder;
+
+ private List<Role> getPagedRoles(final int page) {
+ final Set<Long> adminRoleIds = RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
+ final List<Role> result;
+ if (StringUtils.isBlank(conf.getMatchingCond())) {
+ result = roleDAO.findAll();
+ } else {
+ result = searchDAO.search(adminRoleIds, SearchCondConverter.convert(conf.getMatchingCond()),
+ page, PAGE_SIZE, Collections.<OrderByClause>emptyList(), SubjectType.ROLE);
+ }
+
+ return result;
+ }
+
+ private int count() {
+ Set<Long> adminRoleIds = RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
+
+ return StringUtils.isBlank(conf.getMatchingCond())
+ ? roleDAO.findAll().size()
+ : searchDAO.count(adminRoleIds, SearchCondConverter.convert(conf.getMatchingCond()), SubjectType.ROLE);
+ }
+
+ private void doExtractResources(final ContentHandler handler, final AbstractSubjectTO subjectTO)
+ throws SAXException {
+
+ if (subjectTO.getResources().isEmpty()) {
+ LOG.debug("No resources found for {}[{}]", subjectTO.getClass().getSimpleName(), subjectTO.getKey());
+ } else {
+ AttributesImpl atts = new AttributesImpl();
+ handler.startElement("", "", "resources", null);
+
+ for (String resourceName : subjectTO.getResources()) {
+ atts.clear();
+
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, resourceName);
+ handler.startElement("", "", "resource", atts);
+ handler.endElement("", "", "resource");
+ }
+
+ handler.endElement("", "", "resources");
+ }
+ }
+
+ private void doExtractAttributes(final ContentHandler handler, final AbstractAttributableTO attributableTO,
+ final Collection<String> attrs, final Collection<String> derAttrs, final Collection<String> virAttrs)
+ throws SAXException {
+
+ AttributesImpl atts = new AttributesImpl();
+ if (!attrs.isEmpty()) {
+ Map<String, AttrTO> attrMap = attributableTO.getAttrMap();
+
+ handler.startElement("", "", "attributes", null);
+ for (String attrName : attrs) {
+ atts.clear();
+
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
+ handler.startElement("", "", "attribute", atts);
+
+ if (attrMap.containsKey(attrName)) {
+ for (String value : attrMap.get(attrName).getValues()) {
+ handler.startElement("", "", "value", null);
+ handler.characters(value.toCharArray(), 0, value.length());
+ handler.endElement("", "", "value");
+ }
+ } else {
+ LOG.debug("{} not found for {}[{}]", attrName,
+ attributableTO.getClass().getSimpleName(), attributableTO.getKey());
+ }
+
+ handler.endElement("", "", "attribute");
+ }
+ handler.endElement("", "", "attributes");
+ }
+
+ if (!derAttrs.isEmpty()) {
+ Map<String, AttrTO> derAttrMap = attributableTO.getDerAttrMap();
+
+ handler.startElement("", "", "derivedAttributes", null);
+ for (String attrName : derAttrs) {
+ atts.clear();
+
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
+ handler.startElement("", "", "derivedAttribute", atts);
+
+ if (derAttrMap.containsKey(attrName)) {
+ for (String value : derAttrMap.get(attrName).getValues()) {
+ handler.startElement("", "", "value", null);
+ handler.characters(value.toCharArray(), 0, value.length());
+ handler.endElement("", "", "value");
+ }
+ } else {
+ LOG.debug("{} not found for {}[{}]", attrName,
+ attributableTO.getClass().getSimpleName(), attributableTO.getKey());
+ }
+
+ handler.endElement("", "", "derivedAttribute");
+ }
+ handler.endElement("", "", "derivedAttributes");
+ }
+
+ if (!virAttrs.isEmpty()) {
+ Map<String, AttrTO> virAttrMap = attributableTO.getVirAttrMap();
+
+ handler.startElement("", "", "virtualAttributes", null);
+ for (String attrName : virAttrs) {
+ atts.clear();
+
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
+ handler.startElement("", "", "virtualAttribute", atts);
+
+ if (virAttrMap.containsKey(attrName)) {
+ for (String value : virAttrMap.get(attrName).getValues()) {
+ handler.startElement("", "", "value", null);
+ handler.characters(value.toCharArray(), 0, value.length());
+ handler.endElement("", "", "value");
+ }
+ } else {
+ LOG.debug("{} not found for {}[{}]", attrName,
+ attributableTO.getClass().getSimpleName(), attributableTO.getKey());
+ }
+
+ handler.endElement("", "", "virtualAttribute");
+ }
+ handler.endElement("", "", "virtualAttributes");
+ }
+ }
+
+ private void doExtract(final ContentHandler handler, final List<Role> roles)
+ throws SAXException, ReportException {
+
+ AttributesImpl atts = new AttributesImpl();
+ for (Role role : roles) {
+ atts.clear();
+
+ for (Feature feature : conf.getFeatures()) {
+ String type = null;
+ String value = null;
+ switch (feature) {
+ case key:
+ type = ReportXMLConst.XSD_LONG;
+ value = String.valueOf(role.getKey());
+ break;
+
+ case name:
+ type = ReportXMLConst.XSD_STRING;
+ value = String.valueOf(role.getName());
+ break;
+
+ case roleOwner:
+ type = ReportXMLConst.XSD_LONG;
+ value = String.valueOf(role.getRoleOwner());
+ break;
+
+ case userOwner:
+ type = ReportXMLConst.XSD_LONG;
+ value = String.valueOf(role.getUserOwner());
+ break;
+
+ default:
+ }
+
+ if (type != null && value != null) {
+ atts.addAttribute("", "", feature.name(), type, value);
+ }
+ }
+
+ handler.startElement("", "", "role", atts);
+
+ // Using RoleTO for attribute values, since the conversion logic of
+ // values to String is already encapsulated there
+ RoleTO roleTO = roleDataBinder.getRoleTO(role);
+
+ doExtractAttributes(handler, roleTO, conf.getAttrs(), conf.getDerAttrs(), conf.getVirAttrs());
+
+ if (conf.getFeatures().contains(Feature.entitlements)) {
+ handler.startElement("", "", "entitlements", null);
+
+ for (String ent : roleTO.getEntitlements()) {
+ atts.clear();
+
+ atts.addAttribute("", "", "id", ReportXMLConst.XSD_STRING, String.valueOf(ent));
+
+ handler.startElement("", "", "entitlement", atts);
+ handler.endElement("", "", "entitlement");
+ }
+
+ handler.endElement("", "", "entitlements");
+ }
+ // to get resources associated to a role
+ if (conf.getFeatures().contains(Feature.resources)) {
+ doExtractResources(handler, roleTO);
+ }
+ //to get users asscoiated to a role is preferred RoleDAO to RoleTO
+ if (conf.getFeatures().contains(Feature.users)) {
+ handler.startElement("", "", "users", null);
+
+ for (Membership memb : roleDAO.findMemberships(role)) {
+ atts.clear();
+
+ atts.addAttribute("", "", "key", ReportXMLConst.XSD_LONG,
+ String.valueOf(memb.getUser().getKey()));
+ atts.addAttribute("", "", "username", ReportXMLConst.XSD_STRING,
+ String.valueOf(memb.getUser().getUsername()));
+
+ handler.startElement("", "", "user", atts);
+ handler.endElement("", "", "user");
+ }
+
+ handler.endElement("", "", "users");
+ }
+
+ handler.endElement("", "", "role");
+ }
+ }
+
+ private void doExtractConf(final ContentHandler handler) throws SAXException {
+ if (conf == null) {
+ LOG.debug("Report configuration is not present");
+ }
+
+ AttributesImpl atts = new AttributesImpl();
+ handler.startElement("", "", "configurations", null);
+ handler.startElement("", "", "roleAttributes", atts);
+
+ for (Feature feature : conf.getFeatures()) {
+ atts.clear();
+ handler.startElement("", "", "feature", atts);
+ handler.characters(feature.name().toCharArray(), 0, feature.name().length());
+ handler.endElement("", "", "feature");
+ }
+
+ for (String attr : conf.getAttrs()) {
+ atts.clear();
+ handler.startElement("", "", "attribute", atts);
+ handler.characters(attr.toCharArray(), 0, attr.length());
+ handler.endElement("", "", "attribute");
+ }
+
+ for (String derAttr : conf.getDerAttrs()) {
+ atts.clear();
+ handler.startElement("", "", "derAttribute", atts);
+ handler.characters(derAttr.toCharArray(), 0, derAttr.length());
+ handler.endElement("", "", "derAttribute");
+ }
+
+ for (String virAttr : conf.getVirAttrs()) {
+ atts.clear();
+ handler.startElement("", "", "virAttribute", atts);
+ handler.characters(virAttr.toCharArray(), 0, virAttr.length());
+ handler.endElement("", "", "virAttribute");
+ }
+
+ handler.endElement("", "", "roleAttributes");
+ handler.endElement("", "", "configurations");
+ }
+
+ @Override
+ protected void doExtract(final ContentHandler handler) throws SAXException, ReportException {
+ doExtractConf(handler);
+ for (int i = 1; i <= (count() / PAGE_SIZE) + 1; i++) {
+ doExtract(handler, getPagedRoles(i));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/StaticReportlet.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/StaticReportlet.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/StaticReportlet.java
new file mode 100644
index 0000000..bdc76f8
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/StaticReportlet.java
@@ -0,0 +1,120 @@
+/*
+ * 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.report;
+
+import org.apache.syncope.common.lib.report.StaticReportletConf;
+import org.apache.syncope.server.utils.DataFormat;
+import org.springframework.util.StringUtils;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+@ReportletConfClass(StaticReportletConf.class)
+public class StaticReportlet extends AbstractReportlet<StaticReportletConf> {
+
+ private void doExtractConf(final ContentHandler handler) throws SAXException {
+
+ AttributesImpl atts = new AttributesImpl();
+ handler.startElement("", "", "configurations", null);
+ handler.startElement("", "", "staticAttributes", atts);
+
+ handler.startElement("", "", "string", atts);
+ handler.characters("string".toCharArray(), 0, "string".length());
+ handler.endElement("", "", "string");
+
+ handler.startElement("", "", "long", atts);
+ handler.characters("long".toCharArray(), 0, "long".length());
+ handler.endElement("", "", "long");
+
+ handler.startElement("", "", "double", atts);
+ handler.characters("double".toCharArray(), 0, "double".length());
+ handler.endElement("", "", "double");
+
+ handler.startElement("", "", "date", atts);
+ handler.characters("date".toCharArray(), 0, "date".length());
+ handler.endElement("", "", "date");
+
+ handler.startElement("", "", "double", atts);
+ handler.characters("double".toCharArray(), 0, "double".length());
+ handler.endElement("", "", "double");
+
+ handler.startElement("", "", "enum", atts);
+ handler.characters("enum".toCharArray(), 0, "enum".length());
+ handler.endElement("", "", "enum");
+
+ handler.startElement("", "", "list", atts);
+ handler.characters("list".toCharArray(), 0, "list".length());
+ handler.endElement("", "", "list");
+
+ handler.endElement("", "", "staticAttributes");
+ handler.endElement("", "", "configurations");
+ }
+
+ @Override
+ public void doExtract(final ContentHandler handler) throws SAXException, ReportException {
+
+ doExtractConf(handler);
+
+ if (StringUtils.hasText(conf.getStringField())) {
+ handler.startElement("", "", "string", null);
+ handler.characters(conf.getStringField().toCharArray(), 0, conf.getStringField().length());
+ handler.endElement("", "", "string");
+ }
+
+ if (conf.getLongField() != null) {
+ handler.startElement("", "", "long", null);
+ String printed = String.valueOf(conf.getLongField());
+ handler.characters(printed.toCharArray(), 0, printed.length());
+ handler.endElement("", "", "long");
+ }
+
+ if (conf.getDoubleField() != null) {
+ handler.startElement("", "", "double", null);
+ String printed = String.valueOf(conf.getDoubleField());
+ handler.characters(printed.toCharArray(), 0, printed.length());
+ handler.endElement("", "", "double");
+ }
+
+ if (conf.getDateField() != null) {
+ handler.startElement("", "", "date", null);
+ String printed = DataFormat.format(conf.getDateField());
+ handler.characters(printed.toCharArray(), 0, printed.length());
+ handler.endElement("", "", "date");
+ }
+
+ if (conf.getTraceLevel() != null) {
+ handler.startElement("", "", "enum", null);
+ String printed = conf.getTraceLevel().name();
+ handler.characters(printed.toCharArray(), 0, printed.length());
+ handler.endElement("", "", "enum");
+ }
+
+ if (conf.getListField() != null && !conf.getListField().isEmpty()) {
+ handler.startElement("", "", "list", null);
+ for (String item : conf.getListField()) {
+ if (StringUtils.hasText(item)) {
+ handler.startElement("", "", "string", null);
+ handler.characters(item.toCharArray(), 0, item.length());
+ handler.endElement("", "", "string");
+ }
+ }
+ handler.endElement("", "", "list");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/TextSerializer.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/TextSerializer.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/TextSerializer.java
new file mode 100644
index 0000000..8ad63fc
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/TextSerializer.java
@@ -0,0 +1,101 @@
+/*
+ * 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.report;
+
+import org.apache.cocoon.sax.component.XMLSerializer;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * Converts XML into plain text. It omits all XML tags and writes only character events to the output. Input document
+ * must have at least one element - root element - which should wrap all the text inside it.
+ *
+ */
+public class TextSerializer extends XMLSerializer {
+
+ private static final String UTF_8 = "UTF-8";
+
+ private static final String TXT = "text";
+
+ public TextSerializer() {
+ super();
+ super.setOmitXmlDeclaration(true);
+ }
+
+ @Override
+ public void setDocumentLocator(final Locator locator) {
+ // nothing
+ }
+
+ @Override
+ public void processingInstruction(final String target, final String data)
+ throws SAXException {
+ // nothing
+ }
+
+ @Override
+ public void startDTD(final String name, final String publicId, final String systemId)
+ throws SAXException {
+ // nothing
+ }
+
+ @Override
+ public void endDTD() throws SAXException {
+ // nothing
+ }
+
+ @Override
+ public void startElement(final String uri, final String loc, final String raw, final Attributes atts)
+ throws SAXException {
+ // nothing
+ }
+
+ @Override
+ public void endElement(final String uri, final String name, final String raw)
+ throws SAXException {
+ // nothing
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ super.endDocument();
+ }
+
+ /**
+ * @throws SAXException if text is encountered before root element.
+ */
+ @Override
+ public void characters(final char buffer[], final int start, final int len) throws SAXException {
+ super.characters(buffer, start, len);
+ }
+
+ @Override
+ public void recycle() {
+ super.recycle();
+ }
+
+ public static TextSerializer createPlainSerializer() {
+ final TextSerializer serializer = new TextSerializer();
+ serializer.setContentType("text/plain; charset=" + UTF_8);
+ serializer.setEncoding(UTF_8);
+ serializer.setMethod(TXT);
+ return serializer;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/UserReportlet.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/UserReportlet.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/UserReportlet.java
new file mode 100644
index 0000000..ecae604
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/report/UserReportlet.java
@@ -0,0 +1,359 @@
+/*
+ * 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.report;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.report.UserReportletConf;
+import org.apache.syncope.common.lib.report.UserReportletConf.Feature;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.persistence.api.RoleEntitlementUtil;
+import org.apache.syncope.persistence.api.dao.EntitlementDAO;
+import org.apache.syncope.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.persistence.api.dao.UserDAO;
+import org.apache.syncope.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.persistence.api.entity.membership.Membership;
+import org.apache.syncope.persistence.api.entity.user.User;
+import org.apache.syncope.server.logic.data.RoleDataBinder;
+import org.apache.syncope.server.logic.data.UserDataBinder;
+import org.apache.syncope.server.logic.search.SearchCondConverter;
+import org.apache.syncope.server.utils.DataFormat;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+@ReportletConfClass(UserReportletConf.class)
+public class UserReportlet extends AbstractReportlet<UserReportletConf> {
+
+ private static final int PAGE_SIZE = 10;
+
+ @Autowired
+ private EntitlementDAO entitlementDAO;
+
+ @Autowired
+ private UserDAO userDAO;
+
+ @Autowired
+ private SubjectSearchDAO searchDAO;
+
+ @Autowired
+ private UserDataBinder userDataBinder;
+
+ @Autowired
+ private RoleDataBinder roleDataBinder;
+
+ private List<User> getPagedUsers(final int page) {
+ final Set<Long> adminRoleIds = RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
+
+ final List<User> result;
+ if (StringUtils.isBlank(conf.getMatchingCond())) {
+ result = userDAO.findAll(adminRoleIds, page, PAGE_SIZE);
+ } else {
+ result = searchDAO.search(adminRoleIds, SearchCondConverter.convert(conf.getMatchingCond()),
+ page, PAGE_SIZE, Collections.<OrderByClause>emptyList(), SubjectType.USER);
+ }
+
+ return result;
+ }
+
+ private int count() {
+ Set<Long> adminRoleIds = RoleEntitlementUtil.getRoleKeys(entitlementDAO.findAll());
+
+ return StringUtils.isBlank(conf.getMatchingCond())
+ ? userDAO.count(adminRoleIds)
+ : searchDAO.count(adminRoleIds, SearchCondConverter.convert(conf.getMatchingCond()), SubjectType.USER);
+ }
+
+ private void doExtractResources(final ContentHandler handler, final AbstractSubjectTO subjectTO)
+ throws SAXException {
+
+ if (subjectTO.getResources().isEmpty()) {
+ LOG.debug("No resources found for {}[{}]", subjectTO.getClass().getSimpleName(), subjectTO.getKey());
+ } else {
+ AttributesImpl atts = new AttributesImpl();
+ handler.startElement("", "", "resources", null);
+
+ for (String resourceName : subjectTO.getResources()) {
+ atts.clear();
+
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, resourceName);
+ handler.startElement("", "", "resource", atts);
+ handler.endElement("", "", "resource");
+ }
+
+ handler.endElement("", "", "resources");
+ }
+ }
+
+ private void doExtractAttributes(final ContentHandler handler, final AbstractAttributableTO attributableTO,
+ final Collection<String> attrs, final Collection<String> derAttrs, final Collection<String> virAttrs)
+ throws SAXException {
+
+ AttributesImpl atts = new AttributesImpl();
+ if (!attrs.isEmpty()) {
+ Map<String, AttrTO> attrMap = attributableTO.getAttrMap();
+
+ handler.startElement("", "", "attributes", null);
+ for (String attrName : attrs) {
+ atts.clear();
+
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
+ handler.startElement("", "", "attribute", atts);
+
+ if (attrMap.containsKey(attrName)) {
+ for (String value : attrMap.get(attrName).getValues()) {
+ handler.startElement("", "", "value", null);
+ handler.characters(value.toCharArray(), 0, value.length());
+ handler.endElement("", "", "value");
+ }
+ } else {
+ LOG.debug("{} not found for {}[{}]", attrName,
+ attributableTO.getClass().getSimpleName(), attributableTO.getKey());
+ }
+
+ handler.endElement("", "", "attribute");
+ }
+ handler.endElement("", "", "attributes");
+ }
+
+ if (!derAttrs.isEmpty()) {
+ Map<String, AttrTO> derAttrMap = attributableTO.getDerAttrMap();
+
+ handler.startElement("", "", "derivedAttributes", null);
+ for (String attrName : derAttrs) {
+ atts.clear();
+
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
+ handler.startElement("", "", "derivedAttribute", atts);
+
+ if (derAttrMap.containsKey(attrName)) {
+ for (String value : derAttrMap.get(attrName).getValues()) {
+ handler.startElement("", "", "value", null);
+ handler.characters(value.toCharArray(), 0, value.length());
+ handler.endElement("", "", "value");
+ }
+ } else {
+ LOG.debug("{} not found for {}[{}]", attrName,
+ attributableTO.getClass().getSimpleName(), attributableTO.getKey());
+ }
+
+ handler.endElement("", "", "derivedAttribute");
+ }
+ handler.endElement("", "", "derivedAttributes");
+ }
+
+ if (!virAttrs.isEmpty()) {
+ Map<String, AttrTO> virAttrMap = attributableTO.getVirAttrMap();
+
+ handler.startElement("", "", "virtualAttributes", null);
+ for (String attrName : virAttrs) {
+ atts.clear();
+
+ atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
+ handler.startElement("", "", "virtualAttribute", atts);
+
+ if (virAttrMap.containsKey(attrName)) {
+ for (String value : virAttrMap.get(attrName).getValues()) {
+ handler.startElement("", "", "value", null);
+ handler.characters(value.toCharArray(), 0, value.length());
+ handler.endElement("", "", "value");
+ }
+ } else {
+ LOG.debug("{} not found for {}[{}]", attrName,
+ attributableTO.getClass().getSimpleName(), attributableTO.getKey());
+ }
+
+ handler.endElement("", "", "virtualAttribute");
+ }
+ handler.endElement("", "", "virtualAttributes");
+ }
+ }
+
+ private void doExtract(final ContentHandler handler, final List<User> users)
+ throws SAXException, ReportException {
+
+ AttributesImpl atts = new AttributesImpl();
+ for (User user : users) {
+ atts.clear();
+
+ for (Feature feature : conf.getFeatures()) {
+ String type = null;
+ String value = null;
+ switch (feature) {
+ case key:
+ type = ReportXMLConst.XSD_LONG;
+ value = String.valueOf(user.getKey());
+ break;
+
+ case username:
+ type = ReportXMLConst.XSD_STRING;
+ value = user.getUsername();
+ break;
+
+ case workflowId:
+ type = ReportXMLConst.XSD_LONG;
+ value = String.valueOf(user.getWorkflowId());
+ break;
+
+ case status:
+ type = ReportXMLConst.XSD_STRING;
+ value = user.getStatus();
+ break;
+
+ case creationDate:
+ type = ReportXMLConst.XSD_DATETIME;
+ value = user.getCreationDate() == null
+ ? ""
+ : DataFormat.format(user.getCreationDate());
+ break;
+
+ case lastLoginDate:
+ type = ReportXMLConst.XSD_DATETIME;
+ value = user.getLastLoginDate() == null
+ ? ""
+ : DataFormat.format(user.getLastLoginDate());
+ break;
+
+ case changePwdDate:
+ type = ReportXMLConst.XSD_DATETIME;
+ value = user.getChangePwdDate() == null
+ ? ""
+ : DataFormat.format(user.getChangePwdDate());
+ break;
+
+ case passwordHistorySize:
+ type = ReportXMLConst.XSD_INT;
+ value = String.valueOf(user.getPasswordHistory().size());
+ break;
+
+ case failedLoginCount:
+ type = ReportXMLConst.XSD_INT;
+ value = String.valueOf(user.getFailedLogins());
+ break;
+
+ default:
+ }
+
+ if (type != null && value != null) {
+ atts.addAttribute("", "", feature.name(), type, value);
+ }
+ }
+
+ handler.startElement("", "", "user", atts);
+
+ // Using UserTO for attribute values, since the conversion logic of
+ // values to String is already encapsulated there
+ UserTO userTO = userDataBinder.getUserTO(user);
+
+ doExtractAttributes(handler, userTO, conf.getAttrs(), conf.getDerAttrs(), conf.getVirAttrs());
+
+ if (conf.getFeatures().contains(Feature.memberships)) {
+ handler.startElement("", "", "memberships", null);
+
+ for (MembershipTO memb : userTO.getMemberships()) {
+ atts.clear();
+
+ atts.addAttribute("", "", "id", ReportXMLConst.XSD_LONG, String.valueOf(memb.getKey()));
+ atts.addAttribute("", "", "roleId", ReportXMLConst.XSD_LONG, String.valueOf(memb.getRoleId()));
+ atts.addAttribute("", "", "roleName", ReportXMLConst.XSD_STRING, String.valueOf(memb.getRoleName()));
+ handler.startElement("", "", "membership", atts);
+
+ doExtractAttributes(handler, memb, memb.getAttrMap().keySet(), memb.getDerAttrMap()
+ .keySet(), memb.getVirAttrMap().keySet());
+
+ if (conf.getFeatures().contains(Feature.resources)) {
+ Membership actualMemb = user.getMembership(memb.getRoleId());
+ if (actualMemb == null) {
+ LOG.warn("Unexpected: cannot find membership for role {} for user {}", memb.getRoleId(),
+ user);
+ } else {
+ doExtractResources(handler, roleDataBinder.getRoleTO(actualMemb.getRole()));
+ }
+ }
+
+ handler.endElement("", "", "membership");
+ }
+
+ handler.endElement("", "", "memberships");
+ }
+
+ if (conf.getFeatures().contains(Feature.resources)) {
+ doExtractResources(handler, userTO);
+ }
+
+ handler.endElement("", "", "user");
+ }
+ }
+
+ private void doExtractConf(final ContentHandler handler) throws SAXException {
+
+ AttributesImpl atts = new AttributesImpl();
+ handler.startElement("", "", "configurations", null);
+ handler.startElement("", "", "userAttributes", atts);
+
+ for (Feature feature : conf.getFeatures()) {
+ atts.clear();
+ handler.startElement("", "", "feature", atts);
+ handler.characters(feature.name().toCharArray(), 0, feature.name().length());
+ handler.endElement("", "", "feature");
+ }
+
+ for (String attr : conf.getAttrs()) {
+ atts.clear();
+ handler.startElement("", "", "attribute", atts);
+ handler.characters(attr.toCharArray(), 0, attr.length());
+ handler.endElement("", "", "attribute");
+ }
+
+ for (String derAttr : conf.getDerAttrs()) {
+ atts.clear();
+ handler.startElement("", "", "derAttribute", atts);
+ handler.characters(derAttr.toCharArray(), 0, derAttr.length());
+ handler.endElement("", "", "derAttribute");
+ }
+
+ for (String virAttr : conf.getVirAttrs()) {
+ atts.clear();
+ handler.startElement("", "", "virAttribute", atts);
+ handler.characters(virAttr.toCharArray(), 0, virAttr.length());
+ handler.endElement("", "", "virAttribute");
+ }
+
+ handler.endElement("", "", "userAttributes");
+ handler.endElement("", "", "configurations");
+ }
+
+ @Override
+ protected void doExtract(final ContentHandler handler) throws SAXException, ReportException {
+ doExtractConf(handler);
+ for (int i = 1; i <= (count() / PAGE_SIZE) + 1; i++) {
+ doExtract(handler, getPagedUsers(i));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/search/SearchCondConverter.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/search/SearchCondConverter.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/search/SearchCondConverter.java
new file mode 100644
index 0000000..662cd46
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/search/SearchCondConverter.java
@@ -0,0 +1,50 @@
+/*
+ * 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.search;
+
+import org.apache.cxf.jaxrs.ext.search.SearchBean;
+import org.apache.cxf.jaxrs.ext.search.fiql.FiqlParser;
+import org.apache.syncope.common.lib.search.SyncopeFiqlSearchConditionBuilder;
+import org.apache.syncope.persistence.api.dao.search.SearchCond;
+
+/**
+ * Converts FIQL expressions to Syncope's <tt>SearchCond</tt>.
+ */
+public final class SearchCondConverter {
+
+ /**
+ * Parses a FIQL expression into Syncope's <tt>SearchCond</tt>, using CXF's <tt>FiqlParser</tt>.
+ *
+ * @param fiqlExpression FIQL string
+ * @return <tt>SearchCond</tt> instance for given FIQL expression
+ * @see FiqlParser
+ */
+ public static SearchCond convert(final String fiqlExpression) {
+ FiqlParser<SearchBean> fiqlParser = new FiqlParser<SearchBean>(
+ SearchBean.class, SyncopeFiqlSearchConditionBuilder.CONTEXTUAL_PROPERTIES);
+ SearchCondVisitor searchCondVisitor = new SearchCondVisitor();
+
+ searchCondVisitor.visit(fiqlParser.parse(fiqlExpression));
+ return searchCondVisitor.getQuery();
+ }
+
+ private SearchCondConverter() {
+ // empty constructor for static utility class
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/search/SearchCondVisitor.java
----------------------------------------------------------------------
diff --git a/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/search/SearchCondVisitor.java b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/search/SearchCondVisitor.java
new file mode 100644
index 0000000..5c9acdb
--- /dev/null
+++ b/syncope620/server/logic/src/main/java/org/apache/syncope/server/logic/search/SearchCondVisitor.java
@@ -0,0 +1,203 @@
+/*
+ * 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.search;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.cxf.jaxrs.ext.search.ConditionType;
+import org.apache.cxf.jaxrs.ext.search.SearchBean;
+import org.apache.cxf.jaxrs.ext.search.SearchCondition;
+import org.apache.cxf.jaxrs.ext.search.SearchUtils;
+import org.apache.cxf.jaxrs.ext.search.visitor.AbstractSearchConditionVisitor;
+import org.apache.syncope.common.lib.search.SearchableFields;
+import org.apache.syncope.common.lib.search.SpecialAttr;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.persistence.api.dao.search.EntitlementCond;
+import org.apache.syncope.persistence.api.dao.search.MembershipCond;
+import org.apache.syncope.persistence.api.dao.search.ResourceCond;
+import org.apache.syncope.persistence.api.dao.search.SearchCond;
+import org.apache.syncope.persistence.api.dao.search.SubjectCond;
+
+/**
+ * Converts CXF's <tt>SearchCondition</tt> into internal <tt>SearchCond</tt>.
+ */
+public class SearchCondVisitor extends AbstractSearchConditionVisitor<SearchBean, SearchCond> {
+
+ private static final List<String> ATTRIBUTABLE_FIELDS;
+
+ static {
+ ATTRIBUTABLE_FIELDS = new ArrayList<String>();
+ ATTRIBUTABLE_FIELDS.addAll(SearchableFields.get(UserTO.class));
+ ATTRIBUTABLE_FIELDS.addAll(SearchableFields.get(RoleTO.class));
+ }
+
+ private SearchCond searchCond;
+
+ public SearchCondVisitor() {
+ super(null);
+ }
+
+ public SearchCondVisitor(final Map<String, String> fieldMap) {
+ super(fieldMap);
+ }
+
+ private AttributeCond createAttributeCond(final String schema) {
+ AttributeCond attributeCond = ATTRIBUTABLE_FIELDS.contains(schema)
+ ? new SubjectCond()
+ : new AttributeCond();
+ attributeCond.setSchema(schema);
+ return attributeCond;
+ }
+
+ private SearchCond visitPrimitive(final SearchCondition<SearchBean> sc) {
+ String name = getRealPropertyName(sc.getStatement().getProperty());
+ SpecialAttr specialAttrName = SpecialAttr.fromString(name);
+
+ String value = SearchUtils.toSqlWildcardString(sc.getStatement().getValue().toString(), false).
+ replaceAll("\\\\_", "_");
+ SpecialAttr specialAttrValue = SpecialAttr.fromString(value);
+
+ AttributeCond attributeCond = createAttributeCond(name);
+ attributeCond.setExpression(value);
+
+ SearchCond leaf;
+ switch (sc.getConditionType()) {
+ case EQUALS:
+ case NOT_EQUALS:
+ if (specialAttrName == null) {
+ if (specialAttrValue != null && specialAttrValue == SpecialAttr.NULL) {
+ attributeCond.setType(AttributeCond.Type.ISNULL);
+ attributeCond.setExpression(null);
+ } else if (value.indexOf('%') == -1) {
+ attributeCond.setType(AttributeCond.Type.EQ);
+ } else {
+ attributeCond.setType(AttributeCond.Type.LIKE);
+ }
+
+ leaf = SearchCond.getLeafCond(attributeCond);
+ } else {
+ switch (specialAttrName) {
+ case ROLES:
+ MembershipCond membershipCond = new MembershipCond();
+ membershipCond.setRoleId(Long.valueOf(value));
+ leaf = SearchCond.getLeafCond(membershipCond);
+ break;
+
+ case RESOURCES:
+ ResourceCond resourceCond = new ResourceCond();
+ resourceCond.setResourceName(value);
+ leaf = SearchCond.getLeafCond(resourceCond);
+ break;
+
+ case ENTITLEMENTS:
+ EntitlementCond entitlementCond = new EntitlementCond();
+ entitlementCond.setExpression(value);
+ leaf = SearchCond.getLeafCond(entitlementCond);
+ break;
+
+ default:
+ throw new IllegalArgumentException(
+ String.format("Special attr name %s is not supported", specialAttrName));
+ }
+ }
+ if (sc.getConditionType() == ConditionType.NOT_EQUALS) {
+ if (leaf.getAttributeCond() != null
+ && leaf.getAttributeCond().getType() == AttributeCond.Type.ISNULL) {
+
+ leaf.getAttributeCond().setType(AttributeCond.Type.ISNOTNULL);
+ } else if (leaf.getSubjectCond() != null
+ && leaf.getSubjectCond().getType() == SubjectCond.Type.ISNULL) {
+
+ leaf.getSubjectCond().setType(AttributeCond.Type.ISNOTNULL);
+ } else {
+ leaf = SearchCond.getNotLeafCond(leaf);
+ }
+ }
+ break;
+
+ case GREATER_OR_EQUALS:
+ attributeCond.setType(AttributeCond.Type.GE);
+ leaf = SearchCond.getLeafCond(attributeCond);
+ break;
+
+ case GREATER_THAN:
+ attributeCond.setType(AttributeCond.Type.GT);
+ leaf = SearchCond.getLeafCond(attributeCond);
+ break;
+
+ case LESS_OR_EQUALS:
+ attributeCond.setType(AttributeCond.Type.LE);
+ leaf = SearchCond.getLeafCond(attributeCond);
+ break;
+
+ case LESS_THAN:
+ attributeCond.setType(AttributeCond.Type.LT);
+ leaf = SearchCond.getLeafCond(attributeCond);
+ break;
+
+ default:
+ throw new IllegalArgumentException(
+ String.format("Condition type %s is not supported", sc.getConditionType().name()));
+ }
+
+ return leaf;
+ }
+
+ private SearchCond visitCompount(final SearchCondition<SearchBean> sc) {
+ List<SearchCond> searchConds = new ArrayList<SearchCond>();
+ for (SearchCondition<SearchBean> searchCondition : sc.getSearchConditions()) {
+ searchConds.add(searchCondition.getStatement() == null
+ ? visitCompount(searchCondition)
+ : visitPrimitive(searchCondition));
+ }
+
+ SearchCond compound;
+ switch (sc.getConditionType()) {
+ case AND:
+ compound = SearchCond.getAndCond(searchConds);
+ break;
+
+ case OR:
+ compound = SearchCond.getOrCond(searchConds);
+ break;
+
+ default:
+ throw new IllegalArgumentException(
+ String.format("Condition type %s is not supported", sc.getConditionType().name()));
+ }
+
+ return compound;
+ }
+
+ @Override
+ public void visit(final SearchCondition<SearchBean> sc) {
+ searchCond = sc.getStatement() == null
+ ? visitCompount(sc)
+ : visitPrimitive(sc);
+ }
+
+ @Override
+ public SearchCond getQuery() {
+ return searchCond;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DuplicateException.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DuplicateException.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DuplicateException.java
new file mode 100644
index 0000000..517d64d
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/DuplicateException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.persistence.api.dao;
+
+/**
+ * Thrown when something is not found.
+ */
+public class DuplicateException extends RuntimeException {
+
+ private static final long serialVersionUID = -8200698688516957508L;
+
+ public DuplicateException(final String msg) {
+ super(msg);
+ }
+
+ public DuplicateException(final String msg, final Exception cause) {
+ super(msg, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java
index b2d7dd3..d26615d 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/RoleDAO.java
@@ -77,4 +77,6 @@ public interface RoleDAO extends SubjectDAO<RPlainAttr, RDerAttr, RVirAttr> {
void delete(Role role);
void delete(Long key);
+
+ Role authFetchRole(Long key);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java
index 42ea10a..0f359c3 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/dao/UserDAO.java
@@ -62,4 +62,7 @@ public interface UserDAO extends SubjectDAO<UPlainAttr, UDerAttr, UVirAttr> {
void delete(User user);
+ User authFecthUser(Long key);
+
+ User authFecthUser(String username);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java
index ff1679c..3d12ec9 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtil.java
@@ -19,6 +19,8 @@
package org.apache.syncope.persistence.api.entity;
import java.util.List;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
import org.apache.syncope.common.lib.types.AttributableType;
import org.apache.syncope.common.lib.types.IntMappingType;
import org.apache.syncope.common.lib.types.MappingPurpose;
@@ -83,4 +85,7 @@ public interface AttributableUtil {
<T extends MappingItem> Class<T> mappingItemClass();
+ <T extends AbstractAttributableTO> T newAttributableTO();
+
+ <T extends AbstractSubjectTO> T newSubjectTO();
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtilFactory.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtilFactory.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtilFactory.java
new file mode 100644
index 0000000..1f42c17
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/AttributableUtilFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.persistence.api.entity;
+
+import org.apache.syncope.common.lib.types.AttributableType;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+
+public interface AttributableUtilFactory {
+
+ AttributableUtil getInstance(AttributableType type);
+
+ AttributableUtil getInstance(String attributableType);
+
+ AttributableUtil getInstance(ObjectClass objectClass);
+
+ AttributableUtil getInstance(Attributable<?, ?, ?> attributable);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Entity.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Entity.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Entity.java
index b1b4e00..6c8afbd 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Entity.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/Entity.java
@@ -18,7 +18,9 @@
*/
package org.apache.syncope.persistence.api.entity;
-public interface Entity<KEY> {
+import java.io.Serializable;
+
+public interface Entity<KEY> extends Serializable {
KEY getKey();
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/EntityFactory.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/EntityFactory.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/EntityFactory.java
index 58af4f8..c36030b 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/EntityFactory.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/EntityFactory.java
@@ -23,4 +23,6 @@ public interface EntityFactory {
<KEY, T extends Entity<KEY>> T newEntity(Class<T> reference);
<T extends Policy> T newPolicy(Class<T> reference, boolean global);
+
+ ConnPoolConf newConnPoolConf();
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java
index 965c1a5..8e55c26 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/ExternalResource.java
@@ -27,7 +27,7 @@ import org.apache.syncope.common.lib.types.PropagationMode;
import org.apache.syncope.common.lib.types.TraceLevel;
import org.identityconnectors.framework.common.objects.SyncToken;
-public interface ExternalResource extends Entity<String> {
+public interface ExternalResource extends AnnotatedEntity<String> {
AccountPolicy getAccountPolicy();
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java
index 0c3ac50..b61afdc 100644
--- a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/role/Role.java
@@ -92,7 +92,7 @@ public interface Role extends Subject<RPlainAttr, RDerAttr, RVirAttr> {
boolean isInheritAccountPolicy();
- boolean isInheritAttrs();
+ boolean isInheritPlainAttrs();
boolean isInheritDerAttrs();
@@ -108,7 +108,7 @@ public interface Role extends Subject<RPlainAttr, RDerAttr, RVirAttr> {
void setInheritAccountPolicy(boolean condition);
- void setInheritAttrs(boolean inheritAttrs);
+ void setInheritPlainAttrs(boolean inheritAttrs);
void setInheritDerAttrs(boolean inheritDerAttrs);
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/TaskUtil.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/TaskUtil.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/TaskUtil.java
new file mode 100644
index 0000000..661c645
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/TaskUtil.java
@@ -0,0 +1,36 @@
+/*
+ * 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.persistence.api.entity.task;
+
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.types.TaskType;
+
+public interface TaskUtil {
+
+ TaskType getType();
+
+ <T extends Task> T newTask();
+
+ <T extends AbstractTaskTO> T newTaskTO();
+
+ <T extends Task> Class<T> taskClass();
+
+ <T extends AbstractTaskTO> Class<T> taskTOClass();
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/TaskUtilFactory.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/TaskUtilFactory.java b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/TaskUtilFactory.java
new file mode 100644
index 0000000..b2b24e6
--- /dev/null
+++ b/syncope620/server/persistence-api/src/main/java/org/apache/syncope/persistence/api/entity/task/TaskUtilFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.persistence.api.entity.task;
+
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.types.TaskType;
+
+public interface TaskUtilFactory {
+
+ TaskUtil getInstance(TaskType type);
+
+ TaskUtil getInstance(Task task);
+
+ TaskUtil getInstance(Class<? extends AbstractTaskTO> taskClass);
+
+ TaskUtil getInstance(AbstractTaskTO taskTO);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/pom.xml b/syncope620/server/persistence-jpa/pom.xml
index 17b6a92..b5f0bbe 100644
--- a/syncope620/server/persistence-jpa/pom.xml
+++ b/syncope620/server/persistence-jpa/pom.xml
@@ -91,7 +91,7 @@ under the License.
<dependency>
<groupId>org.apache.syncope.server</groupId>
- <artifactId>syncope-provisioning-api</artifactId>
+ <artifactId>syncope-provisioning-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/syncope/blob/99369c31/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
----------------------------------------------------------------------
diff --git a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
index ac6ab68..64712c8 100644
--- a/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
+++ b/syncope620/server/persistence-jpa/src/main/java/org/apache/syncope/persistence/jpa/dao/AbstractSubjectDAO.java
@@ -89,10 +89,10 @@ abstract class AbstractSubjectDAO<P extends PlainAttr, D extends DerAttr, V exte
final Parser parser = new Parser(new StringReader(expression));
// Schema names
- final List<String> identifiers = new ArrayList<String>();
+ final List<String> identifiers = new ArrayList<>();
// Literals
- final List<String> literals = new ArrayList<String>();
+ final List<String> literals = new ArrayList<>();
// Get schema names and literals
Token token;
@@ -131,18 +131,18 @@ abstract class AbstractSubjectDAO<P extends PlainAttr, D extends DerAttr, V exte
final List<String> attrValues = split(value, literals);
if (attrValues.size() != identifiers.size()) {
- LOG.error("Ambiguous jexl expression resolution.");
+ LOG.error("Ambiguous JEXL expression resolution.");
throw new IllegalArgumentException("literals and values have different size");
}
// clauses to be used with INTERSECTed queries
- final Set<String> clauses = new HashSet<String>();
+ final Set<String> clauses = new HashSet<>();
// builder to build the clauses
final StringBuilder bld = new StringBuilder();
// Contains used identifiers in order to avoid replications
- final Set<String> used = new HashSet<String>();
+ final Set<String> used = new HashSet<>();
// Create several clauses: one for eanch identifiers
for (int i = 0; i < identifiers.size(); i++) {