View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.core.persistence.jpa.openjpa;
20  
21  import java.io.Serializable;
22  import java.util.Collection;
23  import java.util.List;
24  import org.apache.openjpa.event.RemoteCommitEvent;
25  import org.apache.openjpa.event.RemoteCommitListener;
26  import org.apache.openjpa.util.StringId;
27  import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
28  import org.apache.syncope.core.persistence.api.entity.ExternalResource;
29  import org.apache.syncope.core.persistence.jpa.entity.JPAConnInstance;
30  import org.apache.syncope.core.persistence.jpa.entity.JPAExternalResource;
31  import org.apache.syncope.core.provisioning.api.ConnectorManager;
32  import org.apache.syncope.core.spring.ApplicationContextProvider;
33  import org.apache.syncope.core.spring.security.AuthContextUtils;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  /**
38   * Takes care of connectors' Spring beans (un)registration in case HA is set up and the actual change is performed by
39   * another node in the OpenJPA cluster.
40   */
41  public class ConnectorManagerRemoteCommitListener implements RemoteCommitListener, Serializable {
42  
43      private static final long serialVersionUID = 5260753255454140460L;
44  
45      protected static final Logger LOG = LoggerFactory.getLogger(ConnectorManagerRemoteCommitListener.class);
46  
47      protected final String domain;
48  
49      public ConnectorManagerRemoteCommitListener(final String domain) {
50          this.domain = domain;
51      }
52  
53      protected void registerForExternalResource(final String resourceKey) {
54          AuthContextUtils.callAsAdmin(domain, () -> {
55              ExternalResource resource = ApplicationContextProvider.getApplicationContext().
56                      getBean(ExternalResourceDAO.class).find(resourceKey);
57              if (resource == null) {
58                  LOG.debug("No resource found for '{}', ignoring", resourceKey);
59              }
60  
61              try {
62                  ApplicationContextProvider.getApplicationContext().
63                          getBean(ConnectorManager.class).registerConnector(resource);
64              } catch (Exception e) {
65                  LOG.error("While registering connector for resource {}", resourceKey, e);
66              }
67  
68              return null;
69          });
70      }
71  
72      protected void registerForConnInstance(final String connInstanceKey) {
73          AuthContextUtils.callAsAdmin(domain, () -> {
74              List<ExternalResource> resources = ApplicationContextProvider.getApplicationContext().
75                      getBean(ExternalResourceDAO.class).findByConnInstance(connInstanceKey);
76              if (resources.isEmpty()) {
77                  LOG.debug("No resources found for connInstance '{}', ignoring", connInstanceKey);
78              }
79  
80              resources.forEach(resource -> {
81                  try {
82                      ApplicationContextProvider.getApplicationContext().
83                              getBean(ConnectorManager.class).registerConnector(resource);
84                  } catch (Exception e) {
85                      LOG.error("While registering connector {} for resource {}", connInstanceKey, resource, e);
86                  }
87              });
88  
89              return null;
90          });
91      }
92  
93      protected void unregister(final String resourceKey) {
94          AuthContextUtils.callAsAdmin(domain, () -> {
95              ExternalResource resource = ApplicationContextProvider.getApplicationContext().
96                      getBean(ExternalResourceDAO.class).find(resourceKey);
97              if (resource == null) {
98                  LOG.debug("No resource found for '{}', ignoring", resourceKey);
99              }
100 
101             try {
102                 ApplicationContextProvider.getApplicationContext().
103                         getBean(ConnectorManager.class).unregisterConnector(resource);
104             } catch (Exception e) {
105                 LOG.error("While unregistering connector for resource {}", resourceKey, e);
106             }
107 
108             return null;
109         });
110     }
111 
112     @SuppressWarnings("unchecked")
113     @Override
114     public void afterCommit(final RemoteCommitEvent event) {
115         if (event.getPayloadType() == RemoteCommitEvent.PAYLOAD_OIDS_WITH_ADDS) {
116             ((Collection<Object>) event.getPersistedObjectIds()).stream().
117                     filter(StringId.class::isInstance).
118                     map(StringId.class::cast).
119                     forEach(id -> {
120                         if (JPAExternalResource.class.isAssignableFrom(id.getType())) {
121                             registerForExternalResource(id.getId());
122                         } else if (JPAConnInstance.class.isAssignableFrom(id.getType())) {
123                             registerForConnInstance(id.getId());
124                         }
125                     });
126         }
127 
128         if (event.getPayloadType() != RemoteCommitEvent.PAYLOAD_EXTENTS) {
129             ((Collection<Object>) event.getUpdatedObjectIds()).stream().
130                     filter(StringId.class::isInstance).
131                     map(StringId.class::cast).
132                     forEach(id -> {
133                         if (JPAExternalResource.class.isAssignableFrom(id.getType())) {
134                             registerForExternalResource(id.getId());
135                         } else if (JPAConnInstance.class.isAssignableFrom(id.getType())) {
136                             registerForConnInstance(id.getId());
137                         }
138                     });
139 
140             ((Collection<Object>) event.getDeletedObjectIds()).stream().
141                     filter(StringId.class::isInstance).
142                     map(StringId.class::cast).
143                     forEach(id -> {
144                         if (JPAExternalResource.class.isAssignableFrom(id.getType())) {
145                             unregister(id.getId());
146                         }
147                     });
148         }
149     }
150 
151     @Override
152     public void close() {
153         // nothing to do
154     }
155 }