1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.apache.syncope.core.spring.implementation.ImplementationManager;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class ImplementationDataBinderImpl implements ImplementationDataBinder {
42
43 protected static final Logger LOG = LoggerFactory.getLogger(ImplementationDataBinder.class);
44
45 protected final EntityFactory entityFactory;
46
47 public ImplementationDataBinderImpl(final EntityFactory entityFactory) {
48 this.entityFactory = entityFactory;
49 }
50
51 @Override
52 public Implementation create(final ImplementationTO implementationTO) {
53 Implementation implementation = entityFactory.newEntity(Implementation.class);
54 update(implementation, implementationTO);
55 return implementation;
56 }
57
58 @Override
59 public void update(final Implementation implementation, final ImplementationTO implementationTO) {
60 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidImplementation);
61
62 if (implementation.getType() != null && !implementation.getType().equals(implementationTO.getType())) {
63 sce.getElements().add("ImplementationType cannot be changed");
64 throw sce;
65 }
66
67 if (StringUtils.isBlank(implementationTO.getBody())) {
68 sce.getElements().add("No actual implementation provided");
69 throw sce;
70 }
71
72 implementation.setKey(implementationTO.getKey());
73 implementation.setEngine(implementationTO.getEngine());
74 implementation.setType(implementationTO.getType());
75 implementation.setBody(implementationTO.getBody());
76
77 if (implementation.getEngine() == ImplementationEngine.JAVA) {
78 Class<?> baseClazz = Optional.ofNullable(
79 ImplementationTypesHolder.getInstance().getValues().get(implementation.getType())).
80 map(intf -> {
81 try {
82 return Class.forName(intf);
83 } catch (ClassNotFoundException e) {
84 LOG.error("While resolving interface {} for implementation type {}",
85 intf, implementation.getType());
86 return null;
87 }
88 }).
89 orElse(null);
90
91 if (baseClazz == null) {
92 sce.getElements().add("No Java interface found for " + implementation.getType());
93 throw sce;
94 }
95
96 switch (implementation.getType()) {
97 case IdRepoImplementationType.REPORT_DELEGATE:
98 ReportConf conf = POJOHelper.deserialize(implementation.getBody(), ReportConf.class);
99 if (conf == null) {
100 sce.getElements().add("Could not deserialize as " + ReportConf.class.getName());
101 throw sce;
102 }
103 break;
104
105 case IdRepoImplementationType.ACCOUNT_RULE:
106 case IdRepoImplementationType.PASSWORD_RULE:
107 case IdMImplementationType.PULL_CORRELATION_RULE:
108 case IdMImplementationType.PUSH_CORRELATION_RULE:
109 RuleConf rule = POJOHelper.deserialize(implementation.getBody(), RuleConf.class);
110 if (rule == null) {
111 sce.getElements().add("Could not deserialize as neither "
112 + "Account, Password, Pull nor Push Correlation RuleConf");
113 throw sce;
114 }
115 break;
116
117 default:
118 Class<?> clazz = null;
119 try {
120 clazz = Class.forName(implementation.getBody());
121 } catch (Exception e) {
122 LOG.error("Class '{}' not found", implementation.getBody(), e);
123 sce.getElements().add("No Java class found: " + implementation.getBody());
124 throw sce;
125 }
126 if (!baseClazz.isAssignableFrom(clazz)) {
127 sce.getElements().add(
128 "Java class " + implementation.getBody() + " must comply with " + baseClazz.getName());
129 throw sce;
130 }
131 if (Modifier.isAbstract(clazz.getModifiers())) {
132 sce.getElements().add("Java class " + implementation.getBody() + " is abstract");
133 throw sce;
134 }
135 break;
136 }
137 } else if (implementation.getEngine() == ImplementationEngine.GROOVY) {
138 try {
139 ImplementationManager.build(implementation);
140 } catch (Exception e) {
141 LOG.error("While building Groovy class {}", implementation.getKey(), e);
142
143 sce.getElements().add(e.getMessage());
144 throw sce;
145 }
146 }
147 }
148
149 @Override
150 public ImplementationTO getImplementationTO(final Implementation implementation) {
151 ImplementationTO implementationTO = new ImplementationTO();
152 implementationTO.setKey(implementation.getKey());
153 implementationTO.setEngine(implementation.getEngine());
154 implementationTO.setType(implementation.getType());
155 implementationTO.setBody(implementation.getBody());
156
157 return implementationTO;
158 }
159 }