2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2019 Nordix Foundation.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.rest.jpa;
24 import com.att.research.xacml.api.pip.PIPException;
25 import com.att.research.xacml.std.pip.engines.StdConfigurableEngine;
26 import com.att.research.xacml.util.XACMLProperties;
27 import com.google.common.base.Joiner;
28 import com.google.common.base.Splitter;
30 import java.io.Serializable;
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.Date;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.Iterator;
37 import java.util.List;
39 import java.util.Properties;
42 import javax.persistence.CascadeType;
43 import javax.persistence.Column;
44 import javax.persistence.Entity;
45 import javax.persistence.GeneratedValue;
46 import javax.persistence.GenerationType;
47 import javax.persistence.Id;
48 import javax.persistence.JoinColumn;
49 import javax.persistence.ManyToOne;
50 import javax.persistence.NamedQuery;
51 import javax.persistence.OneToMany;
52 import javax.persistence.PrePersist;
53 import javax.persistence.PreUpdate;
54 import javax.persistence.Table;
55 import javax.persistence.Temporal;
56 import javax.persistence.TemporalType;
57 import javax.persistence.Transient;
60 import lombok.NoArgsConstructor;
62 import lombok.ToString;
64 import org.apache.commons.logging.Log;
65 import org.apache.commons.logging.LogFactory;
66 import org.onap.policy.common.logging.eelf.MessageCodes;
67 import org.onap.policy.common.logging.eelf.PolicyLogger;
68 import org.onap.policy.xacml.api.XACMLErrorConstants;
71 * The persistent class for the PipConfiguration database table.
75 @Table(name = "PipConfiguration")
76 @NamedQuery(name = "PipConfiguration.findAll", query = "SELECT p FROM PipConfiguration p")
81 public class PipConfiguration implements Serializable {
82 private static final long serialVersionUID = 1L;
83 private static final Log logger = LogFactory.getLog(PipConfiguration.class);
86 @GeneratedValue(strategy = GenerationType.AUTO)
90 @Column(name = "DESCRIPTION", nullable = true, length = 2048)
91 private String description;
93 @Column(name = "NAME", nullable = false, length = 255)
96 @Column(name = "CLASSNAME", nullable = false, length = 2048)
97 private String classname;
99 @Column(name = "ISSUER", nullable = true, length = 1024)
100 private String issuer;
102 @Column(name = "READ_ONLY", nullable = false)
103 private char readOnly = '0';
105 @Column(name = "REQUIRES_RESOLVER", nullable = false)
106 private char requiresResolvers;
108 @Column(name = "CREATED_BY", nullable = false, length = 255)
109 private String createdBy = "guest";
111 @Temporal(TemporalType.TIMESTAMP)
112 @Column(name = "CREATED_DATE", nullable = false, updatable = false)
113 private Date createdDate;
115 @Column(name = "MODIFIED_BY", nullable = false, length = 255)
116 private String modifiedBy = "guest";
118 @Temporal(TemporalType.TIMESTAMP)
119 @Column(name = "MODIFIED_DATE", nullable = false)
120 private Date modifiedDate;
122 // bi-directional many-to-one association to PipConfigParam
123 @OneToMany(mappedBy = "pipconfiguration", orphanRemoval = true, cascade = CascadeType.REMOVE)
124 private Set<PipConfigParam> pipconfigParams = new HashSet<>();
126 // bi-directional many-to-one association to PipType
128 @JoinColumn(name = "TYPE")
129 private PipType piptype;
131 // bi-directional many-to-one association to PipResolver
132 @OneToMany(mappedBy = "pipconfiguration", orphanRemoval = true, cascade = CascadeType.REMOVE)
133 private Set<PipResolver> pipresolvers = new HashSet<>();
136 * Instantiates a new PIP configuration.
138 * @param config the config
139 * @param user the user
141 public PipConfiguration(PipConfiguration config, String user) {
142 this.description = config.description;
143 this.name = config.name;
144 this.classname = config.classname;
145 this.issuer = config.issuer;
146 this.requiresResolvers = config.requiresResolvers;
147 this.readOnly = config.readOnly;
148 this.piptype = config.piptype;
149 for (PipConfigParam param : config.pipconfigParams) {
150 this.addPipconfigParam(new PipConfigParam(param));
152 for (PipResolver resolver : config.pipresolvers) {
153 this.addPipresolver(new PipResolver(resolver));
158 * Instantiates a new PIP configuration.
161 * @param properties the properties
162 * @throws PIPException the PIP exception
164 public PipConfiguration(String id, Properties properties) throws PIPException {
165 this.readProperties(id, properties);
169 * Instantiates a new PIP configuration.
172 * @param properties the properties
173 * @param user the user
174 * @throws PIPException the PIP exception
176 public PipConfiguration(String id, Properties properties, String user) throws PIPException {
177 this.createdBy = user;
178 this.modifiedBy = user;
179 this.readProperties(id, properties);
186 public void prePersist() {
187 Date date = new Date();
188 this.createdDate = date;
189 this.modifiedDate = date;
196 public void preUpdate() {
197 this.modifiedDate = new Date();
201 * Adds the pipconfig param.
203 * @param pipconfigParam the pipconfig param
204 * @return the PIP config param
206 public PipConfigParam addPipconfigParam(PipConfigParam pipconfigParam) {
207 getPipconfigParams().add(pipconfigParam);
208 pipconfigParam.setPipconfiguration(this);
210 return pipconfigParam;
214 * Removes the pipconfig param.
216 * @param pipconfigParam the pipconfig param
217 * @return the PIP config param
219 public PipConfigParam removePipconfigParam(PipConfigParam pipconfigParam) {
220 if (pipconfigParam == null) {
221 return pipconfigParam;
223 getPipconfigParams().remove(pipconfigParam);
224 pipconfigParam.setPipconfiguration(null);
226 return pipconfigParam;
230 * Clear config params.
233 public void clearConfigParams() {
234 while (!this.pipconfigParams.isEmpty()) {
235 this.removePipconfigParam(this.pipconfigParams.iterator().next());
240 * Adds the pipresolver.
242 * @param pipresolver the pipresolver
243 * @return the PIP resolver
245 public PipResolver addPipresolver(PipResolver pipresolver) {
246 getPipresolvers().add(pipresolver);
247 pipresolver.setPipconfiguration(this);
253 * Removes the pipresolver.
255 * @param pipresolver the pipresolver
256 * @return the PIP resolver
258 public PipResolver removePipresolver(PipResolver pipresolver) {
259 getPipresolvers().remove(pipresolver);
260 pipresolver.setPipconfiguration(null);
266 * Checks if is read only.
268 * @return true, if is read only
271 public boolean isReadOnly() {
272 return this.readOnly == '1';
276 * Sets the read only flag.
278 * @param readOnly the new read only flag
281 public void setReadOnlyFlag(boolean readOnly) {
290 * Requires resolvers.
292 * @return true, if successful
295 public boolean requiresResolvers() {
296 return this.requiresResolvers == '1';
300 * Sets the requires resolvers flag.
302 * @param requires the new requires resolvers flag
305 public void setRequiresResolversFlag(boolean requires) {
307 this.requiresResolvers = '1';
309 this.requiresResolvers = '0';
314 * Import PIP configurations.
316 * @param properties the properties
317 * @return the collection
320 public static Collection<PipConfiguration> importPipConfigurations(Properties properties) {
321 Collection<PipConfiguration> configurations = new ArrayList<>();
322 String engines = properties.getProperty(XACMLProperties.PROP_PIP_ENGINES);
323 if (engines == null || engines.isEmpty()) {
324 return configurations;
326 for (String id : Splitter.on(',').trimResults().omitEmptyStrings().split(engines)) {
327 PipConfiguration configuration;
329 String user = "super-admin";
330 configuration = new PipConfiguration(id, properties, user);
331 configuration.setCreatedBy(user);
332 configuration.setModifiedBy(user);
333 configurations.add(configuration);
334 } catch (PIPException e) {
335 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Import failed: " + e.getLocalizedMessage());
336 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "PipConfiguration", "Import failed");
340 return configurations;
347 * @param properties the properties
348 * @throws PIPException the PIP exception
351 protected void readProperties(String id, Properties properties) throws PIPException {
353 // Save the id if we don't have one already
358 this.id = Integer.parseInt(id);
359 } catch (NumberFormatException e) {
360 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Convert id to integer failed: " + id);
361 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "PipConfiguration", "Convert id to integer failed");
365 // Get its classname, this MUST exist.
367 this.classname = properties.getProperty(id + ".classname");
368 if (this.classname == null) {
369 throw new PIPException("PIP Engine defined without a classname");
372 // Go through each property
374 for (Object propertyKey : properties.keySet()) {
375 readProperty(id, properties, propertyKey);
378 // Make sure we have a name at least
380 if (this.name == null) {
386 * Read a property into the PIP configuration.
388 * @param id the ID of the property
389 * @param properties the properties object to read from
390 * @param key the key of the property being checked
391 * @throws PIPException on exceptions thrown on reading the property
393 private void readProperty(String id, Properties properties, Object key) throws PIPException {
394 if (!key.toString().startsWith(id)) {
397 if (key.equals(id + ".classname")) {
399 // We already saved this
401 } else if (key.equals(id + "." + StdConfigurableEngine.PROP_NAME)) {
402 this.name = properties.getProperty(key.toString());
403 } else if (key.equals(id + "." + StdConfigurableEngine.PROP_DESCRIPTION)) {
404 this.description = properties.getProperty(key.toString());
405 } else if (key.equals(id + "." + StdConfigurableEngine.PROP_ISSUER)) {
406 this.issuer = properties.getProperty(key.toString());
407 } else if (key.equals(id + ".resolvers")) {
409 // It has resolvers, make sure this is set to true if
410 // it has been already.
412 this.setRequiresResolversFlag(true);
414 // Parse the resolvers
416 Collection<PipResolver> resolvers = PipResolver.importResolvers(id + ".resolver",
417 properties.getProperty(key.toString()), properties, "super-admin");
418 for (PipResolver resolver : resolvers) {
419 this.addPipresolver(resolver);
421 } else if (key.toString().startsWith(id + ".resolver")) {
423 // Ignore, the PipResolver will parse these values
429 this.addPipconfigParam(new PipConfigParam(key.toString().substring(id.length() + 1),
430 properties.getProperty(key.toString())));
435 * Gets the configuration.
437 * @param name the name
438 * @return the configuration
441 public Map<String, String> getConfiguration(String name) {
444 prefix = Integer.toString(this.id);
448 if (!prefix.endsWith(".")) {
449 prefix = prefix + ".";
451 Map<String, String> map = new HashMap<>();
452 map.put(prefix + "classname", this.classname);
453 map.put(prefix + "name", this.name);
454 if (this.description != null) {
455 map.put(prefix + "description", this.description);
457 if (this.issuer != null) {
458 map.put(prefix + "issuer", this.issuer);
461 for (PipConfigParam param : this.pipconfigParams) {
462 map.put(prefix + param.getParamName(), param.getParamValue());
465 List<String> ids = new ArrayList<>();
466 Iterator<PipResolver> iter = this.pipresolvers.iterator();
467 while (iter.hasNext()) {
468 PipResolver resolver = iter.next();
469 String idd = Integer.toString(resolver.getId());
470 Map<String, String> resolverMap = resolver.getConfiguration(prefix + "resolver." + idd);
471 map.putAll(resolverMap);
474 if (!ids.isEmpty()) {
475 map.put(prefix + "resolvers", Joiner.on(',').join(ids));
481 * Generate properties.
483 * @param name the name
484 * @return the properties
487 public Properties generateProperties(String name) {
490 prefix = Integer.toString(this.id);
492 if (name.endsWith(".")) {
497 * Instantiates a new PIP configuration.
502 Properties props = new Properties();
503 props.setProperty("xacml.pip.engines", prefix);
504 props.setProperty(prefix + "classname", this.classname);
505 props.setProperty(prefix + "name", this.name);
506 if (this.description != null) {
507 props.setProperty(prefix + "description", this.description);
509 if (this.issuer != null && !this.issuer.isEmpty()) {
510 props.setProperty(prefix + "issuer", this.issuer);
513 for (PipConfigParam param : this.pipconfigParams) {
514 props.setProperty(prefix + param.getParamName(), param.getParamValue());
517 List<String> ids = new ArrayList<>();
518 Iterator<PipResolver> iter = this.pipresolvers.iterator();
519 while (iter.hasNext()) {
520 PipResolver resolver = iter.next();
521 String idd = Integer.toString(resolver.getId());
522 resolver.generateProperties(props, prefix + "resolver." + idd);
525 if (!ids.isEmpty()) {
526 props.setProperty(prefix + "resolvers", Joiner.on(',').join(ids));