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.provisioning.java.data;
20  
21  import java.lang.reflect.Modifier;
22  import java.util.Optional;
23  import org.apache.commons.lang3.StringUtils;
24  import org.apache.syncope.common.lib.SyncopeClientException;
25  import org.apache.syncope.common.lib.policy.RuleConf;
26  import org.apache.syncope.common.lib.report.ReportConf;
27  import org.apache.syncope.common.lib.to.ImplementationTO;
28  import org.apache.syncope.common.lib.types.ClientExceptionType;
29  import org.apache.syncope.common.lib.types.IdMImplementationType;
30  import org.apache.syncope.common.lib.types.IdRepoImplementationType;
31  import org.apache.syncope.common.lib.types.ImplementationEngine;
32  import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
33  import org.apache.syncope.core.persistence.api.entity.EntityFactory;
34  import org.apache.syncope.core.persistence.api.entity.Implementation;
35  import org.apache.syncope.core.provisioning.api.data.ImplementationDataBinder;
36  import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  public class ImplementationDataBinderImpl implements ImplementationDataBinder {
41  
42      protected static final Logger LOG = LoggerFactory.getLogger(ImplementationDataBinder.class);
43  
44      protected final EntityFactory entityFactory;
45  
46      public ImplementationDataBinderImpl(final EntityFactory entityFactory) {
47          this.entityFactory = entityFactory;
48      }
49  
50      @Override
51      public Implementation create(final ImplementationTO implementationTO) {
52          Implementation implementation = entityFactory.newEntity(Implementation.class);
53          update(implementation, implementationTO);
54          return implementation;
55      }
56  
57      @Override
58      public void update(final Implementation implementation, final ImplementationTO implementationTO) {
59          SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidImplementation);
60  
61          if (implementation.getType() != null && !implementation.getType().equals(implementationTO.getType())) {
62              sce.getElements().add("ImplementationType cannot be changed");
63              throw sce;
64          }
65  
66          if (StringUtils.isBlank(implementationTO.getBody())) {
67              sce.getElements().add("No actual implementation provided");
68              throw sce;
69          }
70  
71          implementation.setKey(implementationTO.getKey());
72          implementation.setEngine(implementationTO.getEngine());
73          implementation.setType(implementationTO.getType());
74          implementation.setBody(implementationTO.getBody());
75  
76          if (implementation.getEngine() == ImplementationEngine.JAVA) {
77              Class<?> baseClazz = Optional.ofNullable(
78                      ImplementationTypesHolder.getInstance().getValues().get(implementation.getType())).
79                      map(intf -> {
80                          try {
81                              return Class.forName(intf);
82                          } catch (ClassNotFoundException e) {
83                              LOG.error("While resolving interface {} for implementation type {}",
84                                      intf, implementation.getType());
85                              return null;
86                          }
87                      }).
88                      orElse(null);
89  
90              if (baseClazz == null) {
91                  sce.getElements().add("No Java interface found for " + implementation.getType());
92                  throw sce;
93              }
94  
95              switch (implementation.getType()) {
96                  case IdRepoImplementationType.REPORT_DELEGATE:
97                      ReportConf conf = POJOHelper.deserialize(implementation.getBody(), ReportConf.class);
98                      if (conf == null) {
99                          sce.getElements().add("Could not deserialize as " + ReportConf.class.getName());
100                         throw sce;
101                     }
102                     break;
103 
104                 case IdRepoImplementationType.ACCOUNT_RULE:
105                 case IdRepoImplementationType.PASSWORD_RULE:
106                 case IdMImplementationType.PULL_CORRELATION_RULE:
107                 case IdMImplementationType.PUSH_CORRELATION_RULE:
108                     RuleConf rule = POJOHelper.deserialize(implementation.getBody(), RuleConf.class);
109                     if (rule == null) {
110                         sce.getElements().add("Could not deserialize as neither "
111                                 + "Account, Password, Pull nor Push Correlation RuleConf");
112                         throw sce;
113                     }
114                     break;
115 
116                 default:
117                     Class<?> clazz = null;
118                     try {
119                         clazz = Class.forName(implementation.getBody());
120                     } catch (Exception e) {
121                         LOG.error("Class '{}' not found", implementation.getBody(), e);
122                         sce.getElements().add("No Java class found: " + implementation.getBody());
123                         throw sce;
124                     }
125                     if (!baseClazz.isAssignableFrom(clazz)) {
126                         sce.getElements().add(
127                                 "Java class " + implementation.getBody() + " must comply with " + baseClazz.getName());
128                         throw sce;
129                     }
130                     if (Modifier.isAbstract(clazz.getModifiers())) {
131                         sce.getElements().add("Java class " + implementation.getBody() + " is abstract");
132                         throw sce;
133                     }
134                     break;
135             }
136         }
137     }
138 
139     @Override
140     public ImplementationTO getImplementationTO(final Implementation implementation) {
141         ImplementationTO implementationTO = new ImplementationTO();
142         implementationTO.setKey(implementation.getKey());
143         implementationTO.setEngine(implementation.getEngine());
144         implementationTO.setType(implementation.getType());
145         implementationTO.setBody(implementation.getBody());
146 
147         return implementationTO;
148     }
149 }