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/05 14:34:09 UTC

[04/53] [abbrv] syncope git commit: Initial running version, in order to fix #1

Initial running version, in order to fix #1


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

Branch: refs/heads/master
Commit: 5b3b124a0c4254e39f0caf5b0daabb5b7d571a56
Parents: bac25e1
Author: giacomolm <gi...@hotmail.it>
Authored: Mon Dec 15 16:37:58 2014 +0100
Committer: giacomolm <gi...@hotmail.it>
Committed: Mon Dec 15 16:37:58 2014 +0100

----------------------------------------------------------------------
 .../syncope/common/services/RouteService.java   |  49 ++
 .../common/services/WorkflowService.java        |   9 +
 .../org/apache/syncope/common/to/RouteTO.java   |  60 +++
 .../syncope/console/pages/Configuration.java    | 120 +++++
 .../syncope/console/pages/RouteModalPage.java   |  90 ++++
 .../syncope/console/rest/RouteRestClient.java   |  47 ++
 console/src/main/resources/authorizations.xml   |  13 +
 .../syncope/console/pages/Configuration.html    | 403 ++++++++--------
 .../console/pages/Configuration.properties      |   1 +
 .../syncope/console/pages/RouteModalPage.html   |  49 ++
 .../console/pages/RouteModalPage.properties     |  18 +
 .../console/pages/RouteModalPage_it.properties  |  18 +
 .../pages/RouteModalPage_pt_BR.properties       |  18 +
 core/pom.xml                                    |  19 +
 .../syncope/core/init/CamelRouteLoader.java     | 106 +++++
 .../core/init/SpringContextInitializer.java     |   5 +
 .../core/persistence/beans/CamelRoute.java      |  63 +++
 .../syncope/core/persistence/dao/RouteDAO.java  |  34 ++
 .../core/persistence/dao/impl/RouteDAOImpl.java |  58 +++
 .../DefaultRoleProvisioningManager.java         | 231 ++++++++++
 .../DefaultUserProvisioningManager.java         | 347 ++++++++++++++
 .../provisioning/RoleProvisioningManager.java   |  35 ++
 .../provisioning/UserProvisioningManager.java   |  50 ++
 .../camel/CamelRoleProvisioningManager.java     | 307 +++++++++++++
 .../camel/CamelUserProvisioningManager.java     | 456 +++++++++++++++++++
 .../provisioning/camel/SyncopeCamelContext.java | 137 ++++++
 .../DefaultRoleCreatePropagation.java           |  76 ++++
 .../DefaultRoleCreateSyncPropagation.java       |  79 ++++
 .../DefaultRoleDeletePropagation.java           | 100 ++++
 .../DefaultRoleDeprovisionPropagation.java      |  74 +++
 .../DefaultRoleUpdatePropagation.java           |  75 +++
 .../DefaultUserCreatePropagation.java           |  76 ++++
 .../DefaultUserDeletePropagation.java           |  72 +++
 .../DefaultUserDeprovisionPropagation.java      |  74 +++
 .../DefaultUserStatusPropagation.java           |  76 ++++
 .../DefaultUserUpdateInSyncPropagation.java     |  78 ++++
 .../DefaultUserUpdatePropagation.java           | 120 +++++
 .../DefaultUserWFSuspendPropagation.java        |  64 +++
 .../camel/processors/UserStatusOnSync.java      |  72 +++
 .../provisioning/ProvisioningManager.java       |  42 ++
 .../core/rest/controller/RoleController.java    | 113 +----
 .../core/rest/controller/RouteController.java   |  92 ++++
 .../core/rest/controller/UserController.java    | 146 +++---
 .../syncope/core/rest/data/RouteDataBinder.java |  40 ++
 .../syncope/core/services/RouteServiceImpl.java |  52 +++
 .../core/services/WorkflowServiceImpl.java      |  10 +
 .../sync/impl/AbstractSyncopeResultHandler.java |   9 +
 .../core/sync/impl/RoleSyncResultHandler.java   |  37 +-
 .../core/sync/impl/UserSyncResultHandler.java   |  33 +-
 .../apache/syncope/core/util/RouteManager.java  |  39 ++
 .../core/workflow/WorkflowUserSuspender.java    |  29 +-
 .../user/AbstractUserWorkflowAdapter.java       |   9 -
 .../workflow/user/NoOpUserWorkflowAdapter.java  |   5 +
 .../activiti/ActivitiUserWorkflowAdapter.java   |   5 +
 core/src/main/resources/camelRoute.xml          | 430 +++++++++++++++++
 core/src/main/resources/content.xml             |   3 +
 core/src/main/resources/coreContext.xml         |  26 +-
 core/src/main/resources/roleRoute.xml           | 174 +++++++
 core/src/main/resources/userRoute.xml           | 263 +++++++++++
 .../core/persistence/dao/EntitlementTest.java   |   2 +-
 core/src/test/resources/content.xml             |   3 +
 pom.xml                                         |  19 +-
 62 files changed, 4906 insertions(+), 454 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/common/src/main/java/org/apache/syncope/common/services/RouteService.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/syncope/common/services/RouteService.java b/common/src/main/java/org/apache/syncope/common/services/RouteService.java
new file mode 100644
index 0000000..feb7db7
--- /dev/null
+++ b/common/src/main/java/org/apache/syncope/common/services/RouteService.java
@@ -0,0 +1,49 @@
+/*
+ * 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.services;
+
+import java.util.List;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.apache.syncope.common.to.RouteTO;
+
+@Path("routes")
+public interface RouteService extends JAXRSService{
+    
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    List<RouteTO> getRoutes();
+    
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @Path("{id}")
+    public RouteTO getRoute(@PathParam("id") Long Id);
+    
+    @PUT
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    @Path("{id}")
+    void importRoute(@PathParam("id") Long id, RouteTO route);
+    
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/common/src/main/java/org/apache/syncope/common/services/WorkflowService.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/syncope/common/services/WorkflowService.java b/common/src/main/java/org/apache/syncope/common/services/WorkflowService.java
index 2a291e0..da70043 100644
--- a/common/src/main/java/org/apache/syncope/common/services/WorkflowService.java
+++ b/common/src/main/java/org/apache/syncope/common/services/WorkflowService.java
@@ -86,4 +86,13 @@ public interface WorkflowService extends JAXRSService {
     @PUT
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     void importDefinition(@NotNull @PathParam("kind") SubjectType kind, @NotNull String definition);
+    
+    @GET
+    @Path("{id}")
+    @Produces({ MediaType.APPLICATION_XML })
+    Response getRoute(@PathParam("id") Long id);
+    
+    @GET
+    @Produces({ MediaType.APPLICATION_XML })
+    Response getRoutes();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/common/src/main/java/org/apache/syncope/common/to/RouteTO.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/syncope/common/to/RouteTO.java b/common/src/main/java/org/apache/syncope/common/to/RouteTO.java
new file mode 100644
index 0000000..d9fe833
--- /dev/null
+++ b/common/src/main/java/org/apache/syncope/common/to/RouteTO.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.syncope.common.to;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.AbstractBaseBean;
+
+@XmlRootElement(name = "route")
+@XmlType
+public class RouteTO extends AbstractBaseBean{
+    
+    private Long id;
+
+    private String name;
+
+    private String routeContent;
+    
+    public void setId(Long id){
+        this.id = id;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getRouteContent() {
+        return routeContent;
+    }
+
+    public void setRouteContent(String routeContent) {
+        this.routeContent = routeContent;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/java/org/apache/syncope/console/pages/Configuration.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/Configuration.java b/console/src/main/java/org/apache/syncope/console/pages/Configuration.java
index b2e5c07..10dcfc7 100644
--- a/console/src/main/java/org/apache/syncope/console/pages/Configuration.java
+++ b/console/src/main/java/org/apache/syncope/console/pages/Configuration.java
@@ -32,6 +32,7 @@ import org.apache.syncope.common.SyncopeClientException;
 import org.apache.syncope.common.SyncopeConstants;
 import org.apache.syncope.common.to.LoggerTO;
 import org.apache.syncope.common.to.NotificationTO;
+import org.apache.syncope.common.to.RouteTO;
 import org.apache.syncope.common.to.SecurityQuestionTO;
 import org.apache.syncope.console.commons.AttrLayoutType;
 import org.apache.syncope.common.types.LoggerLevel;
@@ -44,6 +45,7 @@ import org.apache.syncope.console.pages.panels.LayoutsPanel;
 import org.apache.syncope.console.pages.panels.PoliciesPanel;
 import org.apache.syncope.console.rest.LoggerRestClient;
 import org.apache.syncope.console.rest.NotificationRestClient;
+import org.apache.syncope.console.rest.RouteRestClient;
 import org.apache.syncope.console.rest.SecurityQuestionRestClient;
 import org.apache.syncope.console.rest.WorkflowRestClient;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.CollectionPropertyColumn;
@@ -117,6 +119,9 @@ public class Configuration extends BasePage {
 
     @SpringBean
     private WorkflowRestClient wfRestClient;
+    
+    @SpringBean
+    private RouteRestClient routeRestClient;
 
     @SpringBean
     private PreferenceManager prefMan;
@@ -130,12 +135,16 @@ public class Configuration extends BasePage {
     private final ModalWindow createSecurityQuestionWin;
 
     private final ModalWindow editSecurityQuestionWin;
+    
+    private final ModalWindow editRouteWin;
 
     private WebMarkupContainer notificationContainer;
 
     private WebMarkupContainer securityQuestionContainer;
 
     private int notificationPaginatorRows;
+    
+    private int routePaginatorRows;
 
     public Configuration() {
         super();
@@ -267,6 +276,10 @@ public class Configuration extends BasePage {
         add(new LayoutsPanel("selfRoleLayoutPanel", AttrLayoutType.SELF_ROLE, feedbackPanel));
         add(new LayoutsPanel("adminMembershipLayoutPanel", AttrLayoutType.ADMIN_MEMBERSHIP, feedbackPanel));
         add(new LayoutsPanel("selfMembershipLayoutPanel", AttrLayoutType.SELF_MEMBERSHIP, feedbackPanel));
+        
+        //Route Management
+        add(editRouteWin = new ModalWindow("editRouteWin"));
+        setupRoutes();
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
@@ -754,4 +767,111 @@ public class Configuration extends BasePage {
             ctx.updateLoggers();
         }
     }
+    
+    private void setupRoutes() {
+
+        routePaginatorRows = prefMan.getPaginatorRows(getRequest(), "route.paginator.rows");
+
+        final List<IColumn<RouteTO, String>> routeCols = new ArrayList<IColumn<RouteTO, String>>();
+        routeCols.add(new PropertyColumn<RouteTO, String>(
+                new ResourceModel("id"), "id", "id"));
+
+        routeCols.add(new PropertyColumn<RouteTO, String>(
+                new ResourceModel("name"), "name", "name"));
+
+        routeCols.add(new AbstractColumn<RouteTO, String>(new ResourceModel("actions", "")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public String getCssClass() {
+                return "action";
+            }
+
+            @Override
+            public void populateItem(final Item<ICellPopulator<RouteTO>> cellItem, final String componentId,
+                    final IModel<RouteTO> model) {
+
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference());
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+
+                        editRouteWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new RouteModalPage(Configuration.this.getPageReference(), editRouteWin, routeRestClient.readRoute(model.getObject().getId()), false);
+                                //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+                            }
+
+                        });
+
+                        editRouteWin.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, "Routes");
+
+                cellItem.add(panel);
+            }
+        });
+
+        final AjaxFallbackDefaultDataTable<RouteTO, String> routeTable
+                = new AjaxFallbackDefaultDataTable<RouteTO, String>(
+                        "routeTable", routeCols, new RouteProvider(), routePaginatorRows);
+
+        WebMarkupContainer routeContainer = new WebMarkupContainer("routesContainer");
+        routeContainer.add(routeTable);
+        routeContainer.setOutputMarkupId(true);
+
+        add(routeContainer);
+
+        editRouteWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        editRouteWin.setInitialHeight(NOTIFICATION_WIN_HEIGHT);
+        editRouteWin.setInitialWidth(NOTIFICATION_WIN_WIDTH);
+    }
+    
+    private class RouteProvider extends SortableDataProvider<RouteTO, String> {
+
+        private SortableDataProviderComparator<RouteTO> comparator;
+       
+        public RouteProvider() {
+            setSort("id", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<RouteTO>(this);   
+        }
+
+        @Override
+        public Iterator<? extends RouteTO> iterator(long first, long count) {
+            List<RouteTO> list =  routeRestClient.readRoutes();
+
+            Collections.sort(list, comparator);
+
+            return list.subList((int) first, (int) first + (int) count).iterator();
+        }
+
+        @Override
+        public long size() {
+            return routeRestClient.readRoutes().size();
+        }
+
+        @Override
+        public IModel<RouteTO> model(final RouteTO route) {
+            return new AbstractReadOnlyModel<RouteTO>() {
+
+                private static final long serialVersionUID = 774694801558497248L;
+
+                @Override
+                public RouteTO getObject() {
+                    return route;
+                }
+            };
+        }
+       
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/java/org/apache/syncope/console/pages/RouteModalPage.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/RouteModalPage.java b/console/src/main/java/org/apache/syncope/console/pages/RouteModalPage.java
new file mode 100644
index 0000000..bba8aa4
--- /dev/null
+++ b/console/src/main/java/org/apache/syncope/console/pages/RouteModalPage.java
@@ -0,0 +1,90 @@
+/*
+ * 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.console.pages;
+
+import org.apache.syncope.common.SyncopeClientException;
+import org.apache.syncope.common.to.RouteTO;
+import org.apache.syncope.console.commons.Constants;
+import org.apache.syncope.console.rest.RouteRestClient;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.TextArea;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+
+public class RouteModalPage extends BaseModalPage{
+    
+    @SpringBean
+    private RouteRestClient restClient;
+    
+     public RouteModalPage(final PageReference pageRef, final ModalWindow window,
+            final RouteTO routeTO, final boolean createFlag){
+         
+        Form routeForm = new Form("routeDefForm");            
+        
+        final TextArea<String> routeDefArea = new TextArea<String>("routeContent", new PropertyModel<String>(routeTO, "routeContent"));       
+        //routeDefArea.setOutputMarkupId(true);      
+        
+        routeForm.add(routeDefArea);
+        routeForm.setModel(new CompoundPropertyModel<RouteTO>(routeTO));
+        
+        //routeDefArea.setMarkupId("routeContent");
+
+        AjaxButton submit =
+                new IndicatingAjaxButton(APPLY, new Model<String>(getString(SUBMIT)), routeForm) {
+
+                    private static final long serialVersionUID = -958724007591692537L;
+
+                    @Override
+                    protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                        try {
+                            restClient.updateRoute(routeTO.getId(), ((RouteTO)form.getModelObject()).getRouteContent());
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                            
+                            Configuration callerPage = (Configuration) pageRef.getPage();
+                            callerPage.setModalResult(true);                            
+                            window.close(target);
+                        } catch (SyncopeClientException scee) {
+                            error(getString(Constants.ERROR) + ": " + scee.getMessage());
+                        }
+                        target.add(feedbackPanel);
+                    }
+
+                    @Override
+                    protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                        target.add(feedbackPanel);
+                    }
+
+                };
+
+        MetaDataRoleAuthorizationStrategy.authorize(submit, ENABLE,
+                xmlRolesReader.getEntitlement("Routes", "update"));
+        routeForm.add(submit);
+
+        this.add(routeForm);
+     }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/java/org/apache/syncope/console/rest/RouteRestClient.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/rest/RouteRestClient.java b/console/src/main/java/org/apache/syncope/console/rest/RouteRestClient.java
new file mode 100644
index 0000000..673652a
--- /dev/null
+++ b/console/src/main/java/org/apache/syncope/console/rest/RouteRestClient.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.console.rest;
+
+import java.util.List;
+import org.apache.syncope.common.services.RouteService;
+import org.apache.syncope.common.to.RouteTO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RouteRestClient extends BaseRestClient{
+    
+    protected static final Logger LOG = LoggerFactory.getLogger(RouteRestClient.class);
+    
+    public List<RouteTO> readRoutes(){
+        return getService(RouteService.class).getRoutes();
+    }
+    
+    public RouteTO readRoute(Long id){
+        return getService(RouteService.class).getRoute(id);
+    }
+    
+    public void updateRoute(Long id, String definition){
+        RouteTO routeTO = readRoute(id);        
+        routeTO.setRouteContent(definition);     
+        getService(RouteService.class).importRoute(routeTO.getId(), routeTO);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/resources/authorizations.xml
----------------------------------------------------------------------
diff --git a/console/src/main/resources/authorizations.xml b/console/src/main/resources/authorizations.xml
index 69e9b0c..d5914f8 100644
--- a/console/src/main/resources/authorizations.xml
+++ b/console/src/main/resources/authorizations.xml
@@ -317,4 +317,17 @@ under the License.
       <entitlement>POLICY_UPDATE</entitlement>
     </action>
   </page>
+  <page id="Routes">
+    <action id="list">
+      <entitlement>ROUTE_LIST</entitlement>
+    </action>
+
+    <action id="read">
+      <entitlement>ROUTE_READ</entitlement>
+    </action>
+
+    <action id="update">
+      <entitlement>ROUTE_UPDATE</entitlement>
+    </action>
+  </page>
 </auth>

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/resources/org/apache/syncope/console/pages/Configuration.html
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/Configuration.html b/console/src/main/resources/org/apache/syncope/console/pages/Configuration.html
index f3699b8..62f97a8 100644
--- a/console/src/main/resources/org/apache/syncope/console/pages/Configuration.html
+++ b/console/src/main/resources/org/apache/syncope/console/pages/Configuration.html
@@ -17,211 +17,220 @@ specific language governing permissions and limitations
 under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
-  <wicket:head>
-    <script type="text/javascript">
-      $(document).ready(function () {
-        $("#policies").tabs();
-        $("#logs").tabs();
-        $("#layouts").tabs();
-      });
-    </script>
-  </wicket:head>
+    <wicket:head>
+        <script type="text/javascript">
+            $(document).ready(function () {
+                $("#policies").tabs();
+                $("#logs").tabs();
+                $("#layouts").tabs();
+            });
+        </script>
+    </wicket:head>
 
-  <wicket:extend>
+    <wicket:extend>
 
-    <div id="tabs">
-      <ul>
-        <li class="tabs-selected">
-          <a href="#layouts"><span><wicket:message key="layouts"/></span></a>
-        </li>
-        <li><a href="#policies"><span><wicket:message key="policies"/></span></a></li>
-        <li><a href="#notifications"><span><wicket:message key="notifications"/></span></a></li>
-        <li><a href="#securityQuestions"><span><wicket:message key="securityQuestions"/></span></a></li>
-        <li><a href="#workflow"><span><wicket:message key="workflow"/></span></a></li>
-        <li><a href="#logs"><span><wicket:message key="logs"/></span></a></li>
-      </ul>
-      <div id="layouts">
-        <ul>
-          <li class="tabs-selected">
-            <a href="#adminUser"><span><wicket:message key="adminUser"/></span></a>
-          </li>
-          <li><a href="#selfUser"><span><wicket:message key="selfUser"/></span></a></li>
-          <li><a href="#adminRole"><span><wicket:message key="adminRole"/></span></a></li>
-          <li><a href="#selfRole"><span><wicket:message key="selfRole"/></span></a></li>
-          <li><a href="#adminMembership"><span><wicket:message key="adminMembership"/></span></a></li>
-          <li><a href="#selfMembership"><span><wicket:message key="selfMembership"/></span></a></li>
-        </ul>
-        <div id="adminUser" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="adminUserLayoutPanel">[admin user layout panel]</span>
-        </div>
-        <div id="selfUser" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="selfUserLayoutPanel">[self user layout panel]</span>
-        </div>
-        <div id="adminRole" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="adminRoleLayoutPanel">[admin role layout panel]</span>
-        </div>
-        <div id="selfRole" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="selfRoleLayoutPanel">[self role layout panel]</span>
-        </div>
-        <div id="adminMembership" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="adminMembershipLayoutPanel">[admin membership layout panel]</span>
-        </div>
-        <div id="selfMembership" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="selfMembershipLayoutPanel">[self membership layout panel]</span>
-        </div>
-      </div>      
-      <div id="policies">
-        <ul>
-          <li class="tabs-selected">
-            <a href="#account"><span><wicket:message key="account"/></span></a>
-          </li>
-          <li><a href="#password"><span><wicket:message key="password"/></span></a></li>
-          <li><a href="#sync"><span><wicket:message key="sync"/></span></a></li>
-        </ul>
-        <div id="account" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="accountPoliciesPanel">[account policies]</span>
-        </div>
-        <div id="password" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="passwordPoliciesPanel">[password policies]</span>
-        </div>
-        <div id="sync" style="border-width: 1px;border-top-width: 0px;">
-          <span wicket:id="syncPoliciesPanel">[sync policies]</span>
-        </div>
-      </div>
-      <div id="notifications">
-        <div id="users-contain" class="ui-widget" style="width:inherit">
-          <span wicket:id="notificationContainer">
-            <table class="ui-widget ui-widget-content table-hover"
-                   wicket:id="notificationTable"/>
-          </span>
+        <div id="tabs">
+            <ul>
+                <li class="tabs-selected">
+                    <a href="#layouts"><span><wicket:message key="layouts"/></span></a>
+                </li>
+                <li><a href="#policies"><span><wicket:message key="policies"/></span></a></li>
+                <li><a href="#notifications"><span><wicket:message key="notifications"/></span></a></li>
+                <li><a href="#securityQuestions"><span><wicket:message key="securityQuestions"/></span></a></li>
+                <li><a href="#workflow"><span><wicket:message key="workflow"/></span></a></li>
+                <li><a href="#routes"><span><wicket:message key="routes"/></span></a></li>
+                <li><a href="#logs"><span><wicket:message key="logs"/></span></a></li>
+            </ul>
+            <div id="layouts">
+                <ul>
+                    <li class="tabs-selected">
+                        <a href="#adminUser"><span><wicket:message key="adminUser"/></span></a>
+                    </li>
+                    <li><a href="#selfUser"><span><wicket:message key="selfUser"/></span></a></li>
+                    <li><a href="#adminRole"><span><wicket:message key="adminRole"/></span></a></li>
+                    <li><a href="#selfRole"><span><wicket:message key="selfRole"/></span></a></li>
+                    <li><a href="#adminMembership"><span><wicket:message key="adminMembership"/></span></a></li>
+                    <li><a href="#selfMembership"><span><wicket:message key="selfMembership"/></span></a></li>
+                </ul>
+                <div id="adminUser" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="adminUserLayoutPanel">[admin user layout panel]</span>
+                </div>
+                <div id="selfUser" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="selfUserLayoutPanel">[self user layout panel]</span>
+                </div>
+                <div id="adminRole" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="adminRoleLayoutPanel">[admin role layout panel]</span>
+                </div>
+                <div id="selfRole" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="selfRoleLayoutPanel">[self role layout panel]</span>
+                </div>
+                <div id="adminMembership" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="adminMembershipLayoutPanel">[admin membership layout panel]</span>
+                </div>
+                <div id="selfMembership" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="selfMembershipLayoutPanel">[self membership layout panel]</span>
+                </div>
+            </div>      
+            <div id="policies">
+                <ul>
+                    <li class="tabs-selected">
+                        <a href="#account"><span><wicket:message key="account"/></span></a>
+                    </li>
+                    <li><a href="#password"><span><wicket:message key="password"/></span></a></li>
+                    <li><a href="#sync"><span><wicket:message key="sync"/></span></a></li>
+                </ul>
+                <div id="account" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="accountPoliciesPanel">[account policies]</span>
+                </div>
+                <div id="password" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="passwordPoliciesPanel">[password policies]</span>
+                </div>
+                <div id="sync" style="border-width: 1px;border-top-width: 0px;">
+                    <span wicket:id="syncPoliciesPanel">[sync policies]</span>
+                </div>
+            </div>
+            <div id="notifications">
+                <div id="users-contain" class="ui-widget" style="width:inherit">
+                    <span wicket:id="notificationContainer">
+                        <table class="ui-widget ui-widget-content table-hover"
+                               wicket:id="notificationTable"/>
+                    </span>
 
-          <span style="float:right">
-            <form wicket:id="notificationPaginatorForm" style="display:inline">
-              <label><wicket:message key="displayRows"/></label>
-              <select class="text ui-widget-content ui-corner-all"
-                      wicket:id="rowsChooser"/>
-            </form>
-          </span>
-        </div>
+                    <span style="float:right">
+                        <form wicket:id="notificationPaginatorForm" style="display:inline">
+                            <label><wicket:message key="displayRows"/></label>
+                            <select class="text ui-widget-content ui-corner-all"
+                                    wicket:id="rowsChooser"/>
+                        </form>
+                    </span>
+                </div>
 
-        <div wicket:id="createNotificationWin">[Show modal window for creating notification]</div>
-        <div wicket:id="editNotificationWin">[Show modal window for editing notification]</div>
+                <div wicket:id="createNotificationWin">[Show modal window for creating notification]</div>
+                <div wicket:id="editNotificationWin">[Show modal window for editing notification]</div>
 
-        <a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
-           wicket:id="createNotificationLink">
-          <wicket:message key="create"/>
-        </a>
-      </div>
-      <div id="securityQuestions">
-        <div id="users-contain" class="ui-widget" style="width:inherit">
-          <span wicket:id="securityQuestionContainer">
-            <table class="ui-widget ui-widget-content table-hover"
-                   wicket:id="securityQuestionTable"/>
-          </span>
-        </div>
+                <a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
+                   wicket:id="createNotificationLink">
+                    <wicket:message key="create"/>
+                </a>
+            </div>
+            <div id="securityQuestions">
+                <div id="users-contain" class="ui-widget" style="width:inherit">
+                    <span wicket:id="securityQuestionContainer">
+                        <table class="ui-widget ui-widget-content table-hover"
+                               wicket:id="securityQuestionTable"/>
+                    </span>
+                </div>
 
-        <div wicket:id="createSecurityQuestionWin">[Show modal window for creating security questions]</div>
-        <div wicket:id="editSecurityQuestionWin">[Show modal window for editing security questions]</div>
+                <div wicket:id="createSecurityQuestionWin">[Show modal window for creating security questions]</div>
+                <div wicket:id="editSecurityQuestionWin">[Show modal window for editing security questions]</div>
 
-        <a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
-           wicket:id="createSecurityQuestionLink">
-          <wicket:message key="create"/>
-        </a>
-      </div>
-      <div id="workflow">
-        <div id="users-contain" class="ui-widget" style="width:inherit">
-          <span wicket:id="noActivitiEnabledForUsers"><i><wicket:message key="noActivitiEnabledForUsers"/></i></span>
-          <span wicket:id="workflowDefContainer">
-            <div style="float: left;">
-              <button wicket:id="activitiModeler" style="width: 122px">
-                <div style="display: table-row;">
-                  <div style="display: table-cell">
-                    <img src="img/modeler.png" alt="Activiti Modeler" title="Activiti Modeler"/>
-                  </div>
-                  <div style="display: table-cell;vertical-align:middle;font-size:62.5%;">
-                    Activiti Modeler
-                  </div>
-                </div>
-              </button>
+                <a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
+                   wicket:id="createSecurityQuestionLink">
+                    <wicket:message key="create"/>
+                </a>
             </div>
-            <div>
-              <button wicket:id="xmlEditor" style="width: 122px">
-                <div style="display: table-row;">
-                  <div style="display: table-cell">
-                    <img src="img/xml.png" alt="XML editor" title="XML editor"/>
-                  </div>
-                  <div style="display: table-cell;vertical-align:middle;font-size:62.5%;">                  
-                    XML editor
-                  </div>
-                </div>
-              </button>
+            <div id="workflow">
+                <div id="users-contain" class="ui-widget" style="width:inherit">
+                    <span wicket:id="noActivitiEnabledForUsers"><i><wicket:message key="noActivitiEnabledForUsers"/></i></span>
+                    <span wicket:id="workflowDefContainer">
+                        <div style="float: left;">
+                            <button wicket:id="activitiModeler" style="width: 122px">
+                                <div style="display: table-row;">
+                                    <div style="display: table-cell">
+                                        <img src="img/modeler.png" alt="Activiti Modeler" title="Activiti Modeler"/>
+                                    </div>
+                                    <div style="display: table-cell;vertical-align:middle;font-size:62.5%;">
+                                        Activiti Modeler
+                                    </div>
+                                </div>
+                            </button>
+                        </div>
+                        <div>
+                            <button wicket:id="xmlEditor" style="width: 122px">
+                                <div style="display: table-row;">
+                                    <div style="display: table-cell">
+                                        <img src="img/xml.png" alt="XML editor" title="XML editor"/>
+                                    </div>
+                                    <div style="display: table-cell;vertical-align:middle;font-size:62.5%;">                  
+                                        XML editor
+                                    </div>
+                                </div>
+                            </button>
+                        </div>
+                        <img wicket:id="workflowDefDiagram" style="width: 100%;"/>
+                    </span>
+                </div>
             </div>
-            <img wicket:id="workflowDefDiagram" style="width: 100%;"/>
-          </span>
-        </div>
-      </div>
-      <div id="logs">
-        <ul>
-          <li class="tabs-selected">
-            <a href="#core"><span>Core</span></a>
-          </li>
-          <li><a href="#console"><span>Console</span></a></li>
-        </ul>
-        <div id="core" style="border-width: 1px;border-top-width: 0px;">
-          <div id="users-contain" class="ui-widget" style="width:inherit">
-            <span wicket:id="coreLoggerContainer">
-              <table class="ui-widget ui-widget-content table-hover">
-                <thead class="ui-widget-header">
-                  <tr class="heaaders">
-                    <th><wicket:message key="logger"/></th>
-                    <th><wicket:message key="level"/></th>
-                  </tr>
-                </thead>
-                <tbody>
-                  <tr wicket:id="corelogger">
-                    <td><span wicket:id="name"/></td>
-                    <td id="level"><select wicket:id="level"/></td>
-                  </tr>
-                </tbody>
-              </table>
-            </span>
-          </div>
-        </div>
-        <div id="console" style="border-width: 1px;border-top-width: 0px;">
-          <div id="users-contain" class="ui-widget" style="width:inherit">
-            <span wicket:id="consoleLoggerContainer">
-              <table class="ui-widget ui-widget-content table-hover">
-                <thead class="ui-widget-header">
-                  <tr class="heaaders">
-                    <th><wicket:message key="logger"/></th>
-                    <th><wicket:message key="level"/></th>
-                  </tr>
-                </thead>
-                <tbody>
-                  <tr wicket:id="consolelogger">
-                    <td><span wicket:id="name"/></td>
-                    <td id="level"><select wicket:id="level"/></td>
-                  </tr>
-                </tbody>
-              </table>
-            </span>
-          </div>
-        </div>
-      </div>
-      <div>
-        <div wicket:id="parameters">
-          <a style="position: absolute; top: 2px; right:50px;" wicket:id="confLink">
-            <img src="img/actions/settings-icon.png" width="30" height="30"
-                 alt="Parameters" title="title" wicket:message="title:parameters"/>
-          </a>
-        </div>
-        <div wicket:id="syncopeConfWin">[Show modal window for conf parameters]</div>        
+            <div id="routes">
+                <div id="users-contain" class="ui-widget" style="width:inherit">
+                    <span wicket:id="routesContainer">
+                        <table class="ui-widget ui-widget-content table-hover" wicket:id="routeTable"/>
+                    </span>
+                </div>
+                <div wicket:id="editRouteWin">[Show modal window for editing route]</div>
+            </div>
+            <div id="logs">
+                <ul>
+                    <li class="tabs-selected">
+                        <a href="#core"><span>Core</span></a>
+                    </li>
+                    <li><a href="#console"><span>Console</span></a></li>
+                </ul>
+                <div id="core" style="border-width: 1px;border-top-width: 0px;">
+                    <div id="users-contain" class="ui-widget" style="width:inherit">
+                        <span wicket:id="coreLoggerContainer">
+                            <table class="ui-widget ui-widget-content table-hover">
+                                <thead class="ui-widget-header">
+                                    <tr class="heaaders">
+                                        <th><wicket:message key="logger"/></th>
+                                        <th><wicket:message key="level"/></th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr wicket:id="corelogger">
+                                        <td><span wicket:id="name"/></td>
+                                        <td id="level"><select wicket:id="level"/></td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </span>
+                    </div>
+                </div>
+                <div id="console" style="border-width: 1px;border-top-width: 0px;">
+                    <div id="users-contain" class="ui-widget" style="width:inherit">
+                        <span wicket:id="consoleLoggerContainer">
+                            <table class="ui-widget ui-widget-content table-hover">
+                                <thead class="ui-widget-header">
+                                    <tr class="heaaders">
+                                        <th><wicket:message key="logger"/></th>
+                                        <th><wicket:message key="level"/></th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr wicket:id="consolelogger">
+                                        <td><span wicket:id="name"/></td>
+                                        <td id="level"><select wicket:id="level"/></td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </span>
+                    </div>
+                </div>
+            </div>
+            <div>
+                <div wicket:id="parameters">
+                    <a style="position: absolute; top: 2px; right:50px;" wicket:id="confLink">
+                        <img src="img/actions/settings-icon.png" width="30" height="30"
+                             alt="Parameters" title="title" wicket:message="title:parameters"/>
+                    </a>
+                </div>
+                <div wicket:id="syncopeConfWin">[Show modal window for conf parameters]</div>        
 
-        <a style="position: absolute; top: 2px; right:20px;" wicket:id="dbExportLink">
-          <img src="img/db_export.png" width="30" height="30"
-               alt="DB export" title="title" wicket:message="title:db_export"/>
-        </a>
-      </div>    
-    </div>
-  </wicket:extend>
+                <a style="position: absolute; top: 2px; right:20px;" wicket:id="dbExportLink">
+                    <img src="img/db_export.png" width="30" height="30"
+                         alt="DB export" title="title" wicket:message="title:db_export"/>
+                </a>
+            </div>    
+        </div>
+    </wicket:extend>
 </html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/resources/org/apache/syncope/console/pages/Configuration.properties
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/Configuration.properties b/console/src/main/resources/org/apache/syncope/console/pages/Configuration.properties
index 1b6bcc7..f59b50f 100644
--- a/console/src/main/resources/org/apache/syncope/console/pages/Configuration.properties
+++ b/console/src/main/resources/org/apache/syncope/console/pages/Configuration.properties
@@ -45,3 +45,4 @@ adminRole=Administrator Role Form
 selfRole=Self Role Form
 adminMembership=Administrator Membership Form
 selfMembership=Self Membership Form
+routes=Routes
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage.html
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage.html b/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage.html
new file mode 100644
index 0000000..a237c27
--- /dev/null
+++ b/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage.html
@@ -0,0 +1,49 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:head>
+    <link rel="stylesheet" type="text/css" href="webjars/codemirror/${codemirror.version}/lib/codemirror.css"/>
+
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/lib/codemirror.js"></script>
+    <script type="text/javascript" src="webjars/codemirror/${codemirror.version}/mode/xml/xml.js"></script>
+    <script type="text/javascript">
+      function updateTextArea(editor) {         
+        document.getElementById("routeDefForm").elements["routeContent"].value = editor.getValue();
+      }
+    </script>
+  </wicket:head>
+  <wicket:extend>
+    <form wicket:id="routeDefForm" id="routeDefForm">
+      <textarea wicket:id="routeContent" id="routeContent" name="routeContent" style="width: 100%; height: 350px;">
+      </textarea>
+      <div style="margin: 10px;">
+        <input type="submit"
+               class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
+               wicket:id="apply"
+               onclick=""/>
+      </div>
+    </form>
+    <script>
+      window.onload = function(){
+              var editor = CodeMirror.fromTextArea(document.getElementById("routeContent"),{lineNumbers: true});
+              editor.on("change", updateTextArea);
+      }    
+    </script>
+  </wicket:extend>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage.properties
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage.properties b/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage.properties
new file mode 100644
index 0000000..8ac2655
--- /dev/null
+++ b/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage.properties
@@ -0,0 +1,18 @@
+# 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.
+title=Edit route
+id=id

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage_it.properties
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage_it.properties b/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage_it.properties
new file mode 100644
index 0000000..44663f7
--- /dev/null
+++ b/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage_it.properties
@@ -0,0 +1,18 @@
+# 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.
+title=Modifica le rotte
+id=id

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage_pt_BR.properties
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage_pt_BR.properties b/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage_pt_BR.properties
new file mode 100644
index 0000000..a6395a0
--- /dev/null
+++ b/console/src/main/resources/org/apache/syncope/console/pages/RouteModalPage_pt_BR.properties
@@ -0,0 +1,18 @@
+# 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.
+title=Editar rotas
+id=id

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index d9ab5a6..66b5a22 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -117,6 +117,25 @@ under the License.
       <groupId>org.apache.cxf</groupId>
       <artifactId>cxf-rt-rs-client</artifactId>
     </dependency>  
+       
+     <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-spring</artifactId>
+    </dependency>
+    <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+            <version>2.2.7</version>
+    </dependency>
+    <dependency>
+       <groupId>com.sun.xml.bind</groupId>
+       <artifactId>jaxb-impl</artifactId>
+       <version>2.2.7</version>
+    </dependency>
 
     <dependency>
       <groupId>org.springframework</groupId>

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/core/src/main/java/org/apache/syncope/core/init/CamelRouteLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/init/CamelRouteLoader.java b/core/src/main/java/org/apache/syncope/core/init/CamelRouteLoader.java
new file mode 100644
index 0000000..aa6da28
--- /dev/null
+++ b/core/src/main/java/org/apache/syncope/core/init/CamelRouteLoader.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.syncope.core.init;
+
+import java.io.File;
+import java.io.StringWriter;
+import java.net.URL;
+import javax.sql.DataSource;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.syncope.core.persistence.beans.CamelRoute;
+import org.apache.syncope.core.persistence.dao.RouteDAO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+@Component
+public class CamelRouteLoader {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(CamelRouteLoader.class);
+    
+    @Autowired
+    private RouteDAO routeDAO;
+    
+    @Autowired
+    private DataSource dataSource;
+    
+    @Transactional
+    public void load(){
+        
+        //if(routeDAO.findAll().isEmpty()){
+            URL url = getClass().getResource("/camelRoute.xml");                                   
+
+            File file = new File(url.getPath());
+            String query= "INSERT INTO CamelRoute(ID, NAME, ROUTECONTENT) VALUES (?, ?, ?)";
+            try{
+                
+                DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+                Document doc = dBuilder.parse(file);
+                doc.getDocumentElement().normalize();
+
+                JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
+
+                NodeList listOfRoutes = doc.getElementsByTagName("route");
+                for(int s=0; s<listOfRoutes.getLength(); s++){
+                    //getting the route node element
+                    Node routeEl = listOfRoutes.item(s);
+                    //crate an instance of CamelRoute Entity
+                    CamelRoute route = new CamelRoute();                                 
+                    route.setName(((Element)routeEl).getAttribute("id"));        
+                    route.setRouteContent(nodeToString(listOfRoutes.item(s)));
+                    
+                    jdbcTemplate.update(query, new Object[]{s+1,((Element)routeEl).getAttribute("id"),  nodeToString(listOfRoutes.item(s))});
+                    LOG.info("Route Registration Successed");
+                }
+            } catch (DataAccessException e) {
+                LOG.error("While trying to perform {}", query, e);
+            } catch (Exception e) {
+                LOG.error("Route Registration failed {}",e.getMessage());
+            }
+        //}
+    }
+    
+  private String nodeToString(Node node) {
+        StringWriter sw = new StringWriter();
+        try{
+            Transformer t = TransformerFactory.newInstance().newTransformer();
+            t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+            t.transform(new DOMSource(node), new StreamResult(sw));
+        }catch (TransformerException te) {
+            System.out.println("nodeToString Transformer Exception");
+        }
+        return sw.toString();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/core/src/main/java/org/apache/syncope/core/init/SpringContextInitializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/init/SpringContextInitializer.java b/core/src/main/java/org/apache/syncope/core/init/SpringContextInitializer.java
index 403fe96..115587d 100644
--- a/core/src/main/java/org/apache/syncope/core/init/SpringContextInitializer.java
+++ b/core/src/main/java/org/apache/syncope/core/init/SpringContextInitializer.java
@@ -49,6 +49,9 @@ public class SpringContextInitializer implements InitializingBean {
 
     @Autowired
     private WorkflowAdapterLoader workflowAdapterLoader;
+    
+    @Autowired
+    private CamelRouteLoader routeLoader;
 
     @Override
     public void afterPropertiesSet() throws Exception {
@@ -59,6 +62,8 @@ public class SpringContextInitializer implements InitializingBean {
         loggerLoader.load();
         classNamesLoader.load();
 
+        routeLoader.load();
+        
         workflowAdapterLoader.init();
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/core/src/main/java/org/apache/syncope/core/persistence/beans/CamelRoute.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/persistence/beans/CamelRoute.java b/core/src/main/java/org/apache/syncope/core/persistence/beans/CamelRoute.java
new file mode 100644
index 0000000..ad05f27
--- /dev/null
+++ b/core/src/main/java/org/apache/syncope/core/persistence/beans/CamelRoute.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.syncope.core.persistence.beans;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.GenerationType;
+import javax.persistence.Column;
+
+
+@Entity
+public class CamelRoute {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    @Column(name="id")
+    private Long id;
+
+    private String name;
+
+    @Lob
+    private String routeContent;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getRouteContent() {
+        return routeContent;
+    }
+
+    public void setRouteContent(String routeContent) {
+        this.routeContent = routeContent;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/core/src/main/java/org/apache/syncope/core/persistence/dao/RouteDAO.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/persistence/dao/RouteDAO.java b/core/src/main/java/org/apache/syncope/core/persistence/dao/RouteDAO.java
new file mode 100644
index 0000000..aa7f4f6
--- /dev/null
+++ b/core/src/main/java/org/apache/syncope/core/persistence/dao/RouteDAO.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.dao;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.validation.entity.InvalidEntityException;
+import org.apache.syncope.core.persistence.beans.CamelRoute;
+
+public interface RouteDAO {
+
+    CamelRoute find(Long id);
+
+    List<CamelRoute> findAll();
+
+    CamelRoute save(CamelRoute route) throws InvalidEntityException;
+
+    void delete(Long id);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/RouteDAOImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/RouteDAOImpl.java b/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/RouteDAOImpl.java
new file mode 100644
index 0000000..aaa0026
--- /dev/null
+++ b/core/src/main/java/org/apache/syncope/core/persistence/dao/impl/RouteDAOImpl.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.core.persistence.dao.impl;
+
+import java.util.List;
+import javax.persistence.TypedQuery;
+import org.apache.syncope.core.persistence.beans.CamelRoute;
+import org.apache.syncope.core.persistence.dao.RouteDAO;
+import org.apache.syncope.core.persistence.validation.entity.InvalidEntityException;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class RouteDAOImpl extends AbstractDAOImpl implements RouteDAO {
+
+    @Override
+    public CamelRoute find(final Long id) {
+        return entityManager.find(CamelRoute.class, id);
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public List<CamelRoute> findAll() {
+        TypedQuery<CamelRoute> query = entityManager.createQuery("SELECT e FROM " + CamelRoute.class.getSimpleName() + " e", CamelRoute.class);
+        return query.getResultList();
+    }
+
+    @Override
+    public CamelRoute save(final CamelRoute route) throws InvalidEntityException {
+        return entityManager.merge(route);
+    }
+
+    @Override
+    public void delete(Long id) {
+        CamelRoute route = find(id);
+        if (route != null) {
+            entityManager.remove(route);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/5b3b124a/core/src/main/java/org/apache/syncope/core/provisioning/DefaultRoleProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/provisioning/DefaultRoleProvisioningManager.java b/core/src/main/java/org/apache/syncope/core/provisioning/DefaultRoleProvisioningManager.java
new file mode 100644
index 0000000..de9e1fc
--- /dev/null
+++ b/core/src/main/java/org/apache/syncope/core/provisioning/DefaultRoleProvisioningManager.java
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.syncope.core.provisioning;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.syncope.common.mod.RoleMod;
+import org.apache.syncope.common.to.AttributeTO;
+import org.apache.syncope.common.to.PropagationStatus;
+import org.apache.syncope.common.to.RoleTO;
+import org.apache.syncope.core.persistence.beans.PropagationTask;
+import org.apache.syncope.core.persistence.beans.role.SyncopeRole;
+import org.apache.syncope.core.persistence.dao.RoleDAO;
+import org.apache.syncope.core.propagation.PropagationException;
+import org.apache.syncope.core.propagation.PropagationReporter;
+import org.apache.syncope.core.propagation.PropagationTaskExecutor;
+import org.apache.syncope.core.propagation.impl.PropagationManager;
+import org.apache.syncope.core.rest.data.RoleDataBinder;
+import org.apache.syncope.core.util.ApplicationContextProvider;
+import org.apache.syncope.core.util.EntitlementUtil;
+import org.apache.syncope.core.workflow.WorkflowResult;
+import org.apache.syncope.core.workflow.role.RoleWorkflowAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.apache.commons.lang3.StringUtils;
+
+public class DefaultRoleProvisioningManager implements RoleProvisioningManager{
+
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultRoleProvisioningManager.class);
+    @Autowired
+    protected RoleWorkflowAdapter rwfAdapter;
+    @Autowired
+    protected PropagationManager propagationManager;
+    @Autowired
+    protected PropagationTaskExecutor taskExecutor;    
+    @Autowired
+    protected RoleDAO roleDAO;
+    @Autowired
+    protected RoleDataBinder binder;
+    
+    @Override
+    public Map.Entry<Long, List<PropagationStatus>> create(RoleTO subject) {
+        return create(subject, Collections.<String>emptySet());
+    }
+
+    @Override
+    public Map.Entry<Long, List<PropagationStatus>> create(RoleTO subject, Set<String> excludedResources) {
+        
+        WorkflowResult<Long> created;
+        try{
+            created = rwfAdapter.create(subject);
+        }
+        catch(RuntimeException e){
+            throw e;
+        }
+
+        EntitlementUtil.extendAuthContext(created.getResult());
+
+        List<PropagationTask> tasks = propagationManager.getRoleCreateTaskIds(created, subject.getVirAttrs());
+        PropagationReporter propagationReporter = ApplicationContextProvider.getApplicationContext().getBean(
+                PropagationReporter.class);
+        try {
+            taskExecutor.execute(tasks, propagationReporter);
+        } catch (PropagationException e) {
+            LOG.error("Error propagation primary resource", e);
+            propagationReporter.onPrimaryResourceFailure(tasks);
+        }
+        
+        Map.Entry<Long, List<PropagationStatus>> result = new AbstractMap.SimpleEntry<Long, List<PropagationStatus>>(
+                created.getResult(), propagationReporter.getStatuses());
+        return result;
+    }
+    
+    @Override
+    public Map.Entry<Long, List<PropagationStatus>> createInSync(RoleTO roleTO, Map<Long, String> roleOwnerMap,Set<String> excludedResources) throws PropagationException{
+        
+        WorkflowResult<Long> created = rwfAdapter.create((RoleTO) roleTO);
+        AttributeTO roleOwner = roleTO.getAttrMap().get(StringUtils.EMPTY);
+        if (roleOwner != null) {
+            roleOwnerMap.put(created.getResult(), roleOwner.getValues().iterator().next());
+        }
+
+        EntitlementUtil.extendAuthContext(created.getResult());
+
+        List<PropagationTask> tasks = propagationManager.getRoleCreateTaskIds(created,
+                roleTO.getVirAttrs(), excludedResources);
+
+        taskExecutor.execute(tasks);
+        
+        Map.Entry<Long, List<PropagationStatus>> result = new AbstractMap.SimpleEntry<Long, List<PropagationStatus>>(
+                created.getResult(), null);
+        return result;
+    }
+    
+    @Override
+    public Map.Entry<Long, List<PropagationStatus>> update(RoleMod subjectMod) {
+        
+        return update(subjectMod, Collections.<String>emptySet());
+    }
+    
+    @Override
+    public Map.Entry<Long, List<PropagationStatus>> update(RoleMod subjectMod, Set<String> excludedResources) {
+                
+        WorkflowResult<Long> updated;
+        
+        try{
+            updated = rwfAdapter.update(subjectMod);
+        }
+        catch(RuntimeException e){
+            throw e;
+        }
+
+        List<PropagationTask> tasks = propagationManager.getRoleUpdateTaskIds(updated,
+                subjectMod.getVirAttrsToRemove(), subjectMod.getVirAttrsToUpdate(),excludedResources);
+        PropagationReporter propagationReporter = ApplicationContextProvider.getApplicationContext().getBean(
+                PropagationReporter.class);
+        try {
+            taskExecutor.execute(tasks, propagationReporter);
+        } catch (PropagationException e) {
+            LOG.error("Error propagation primary resource", e);
+            propagationReporter.onPrimaryResourceFailure(tasks);
+        }
+        
+        Map.Entry<Long, List<PropagationStatus>> result = new AbstractMap.SimpleEntry<Long, List<PropagationStatus>>(
+                updated.getResult(), propagationReporter.getStatuses());
+        return result;
+    }
+
+    @Override
+    public List<PropagationStatus> delete(Long subjectId) {
+
+        final List<SyncopeRole> toBeDeprovisioned = new ArrayList<SyncopeRole>();
+
+        final SyncopeRole syncopeRole = roleDAO.find(subjectId);
+
+        if (syncopeRole != null) {
+            toBeDeprovisioned.add(syncopeRole);
+
+            final List<SyncopeRole> descendants = roleDAO.findDescendants(toBeDeprovisioned.get(0));
+            if (descendants != null) {
+                toBeDeprovisioned.addAll(descendants);
+            }
+        }
+
+        final List<PropagationTask> tasks = new ArrayList<PropagationTask>();
+
+        for (SyncopeRole role : toBeDeprovisioned) {
+            // Generate propagation tasks for deleting users from role resources, if they are on those resources only
+            // because of the reason being deleted (see SYNCOPE-357)
+            for (WorkflowResult<Long> wfResult : binder.getUsersOnResourcesOnlyBecauseOfRole(role.getId())) {
+                tasks.addAll(propagationManager.getUserDeleteTaskIds(wfResult));
+            }
+
+            // Generate propagation tasks for deleting this role from resources
+            tasks.addAll(propagationManager.getRoleDeleteTaskIds(role.getId()));
+        }
+
+        PropagationReporter propagationReporter = ApplicationContextProvider.getApplicationContext().getBean(
+                PropagationReporter.class);
+        try {
+            taskExecutor.execute(tasks, propagationReporter);
+        } catch (PropagationException e) {
+            LOG.error("Error propagation primary resource", e);
+            propagationReporter.onPrimaryResourceFailure(tasks);
+        }
+
+        try{
+            rwfAdapter.delete(subjectId);
+        }
+        catch(RuntimeException e){
+            throw  e;
+        }
+        
+        return propagationReporter.getStatuses();
+    }
+
+    @Override
+    public Long unlink(RoleMod subjectMod) {
+        WorkflowResult<Long> updated = rwfAdapter.update(subjectMod);
+        return updated.getResult();
+    }
+    
+    @Override
+    public List<PropagationStatus> deprovision(final Long roleId, final Collection<String> resources){
+        final SyncopeRole role = binder.getRoleFromId(roleId);
+        
+        final Set<String> noPropResourceName = role.getResourceNames();
+        noPropResourceName.removeAll(resources);
+        
+        final List<PropagationTask> tasks = propagationManager.getRoleDeleteTaskIds(roleId, new HashSet<String>(resources), noPropResourceName);
+        PropagationReporter propagationReporter = ApplicationContextProvider.getApplicationContext().getBean(
+                PropagationReporter.class);
+        try {
+            taskExecutor.execute(tasks, propagationReporter);
+        } catch (PropagationException e) {
+            LOG.error("Error propagation primary resource", e);
+            propagationReporter.onPrimaryResourceFailure(tasks);
+        }
+        return propagationReporter.getStatuses();
+    }
+
+    @Override
+    public Long link(RoleMod subjectMod) {
+        return rwfAdapter.update(subjectMod).getResult();
+    }
+    
+}