Unit/SONAR/Checkstyle in ONAP-REST
[policy/engine.git] / ONAP-REST / src / main / java / org / onap / policy / rest / jpa / PipConfiguration.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-REST
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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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=========================================================
20  */
21
22 package org.onap.policy.rest.jpa;
23
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;
29
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;
38 import java.util.Map;
39 import java.util.Properties;
40 import java.util.Set;
41
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;
58
59 import lombok.Getter;
60 import lombok.NoArgsConstructor;
61 import lombok.Setter;
62 import lombok.ToString;
63
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;
69
70 /**
71  * The persistent class for the PipConfiguration database table.
72  *
73  */
74 @Entity
75 @Table(name = "PipConfiguration")
76 @NamedQuery(name = "PipConfiguration.findAll", query = "SELECT p FROM PipConfiguration p")
77 @Getter
78 @Setter
79 @NoArgsConstructor
80 @ToString
81 public class PipConfiguration implements Serializable {
82     private static final long serialVersionUID = 1L;
83     private static final Log logger = LogFactory.getLog(PipConfiguration.class);
84
85     @Id
86     @GeneratedValue(strategy = GenerationType.AUTO)
87     @Column(name = "id")
88     private int id;
89
90     @Column(name = "DESCRIPTION", nullable = true, length = 2048)
91     private String description;
92
93     @Column(name = "NAME", nullable = false, length = 255)
94     private String name;
95
96     @Column(name = "CLASSNAME", nullable = false, length = 2048)
97     private String classname;
98
99     @Column(name = "ISSUER", nullable = true, length = 1024)
100     private String issuer;
101
102     @Column(name = "READ_ONLY", nullable = false)
103     private char readOnly = '0';
104
105     @Column(name = "REQUIRES_RESOLVER", nullable = false)
106     private char requiresResolvers;
107
108     @Column(name = "CREATED_BY", nullable = false, length = 255)
109     private String createdBy = "guest";
110
111     @Temporal(TemporalType.TIMESTAMP)
112     @Column(name = "CREATED_DATE", nullable = false, updatable = false)
113     private Date createdDate;
114
115     @Column(name = "MODIFIED_BY", nullable = false, length = 255)
116     private String modifiedBy = "guest";
117
118     @Temporal(TemporalType.TIMESTAMP)
119     @Column(name = "MODIFIED_DATE", nullable = false)
120     private Date modifiedDate;
121
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<>();
125
126     // bi-directional many-to-one association to PipType
127     @ManyToOne
128     @JoinColumn(name = "TYPE")
129     private PipType piptype;
130
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<>();
134
135     /**
136      * Instantiates a new PIP configuration.
137      *
138      * @param config the config
139      * @param user the user
140      */
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));
151         }
152         for (PipResolver resolver : config.pipresolvers) {
153             this.addPipresolver(new PipResolver(resolver));
154         }
155     }
156
157     /**
158      * Instantiates a new PIP configuration.
159      *
160      * @param id the id
161      * @param properties the properties
162      * @throws PIPException the PIP exception
163      */
164     public PipConfiguration(String id, Properties properties) throws PIPException {
165         this.readProperties(id, properties);
166     }
167
168     /**
169      * Instantiates a new PIP configuration.
170      *
171      * @param id the id
172      * @param properties the properties
173      * @param user the user
174      * @throws PIPException the PIP exception
175      */
176     public PipConfiguration(String id, Properties properties, String user) throws PIPException {
177         this.createdBy = user;
178         this.modifiedBy = user;
179         this.readProperties(id, properties);
180     }
181
182     /**
183      * Pre persist.
184      */
185     @PrePersist
186     public void prePersist() {
187         Date date = new Date();
188         this.createdDate = date;
189         this.modifiedDate = date;
190     }
191
192     /**
193      * Pre update.
194      */
195     @PreUpdate
196     public void preUpdate() {
197         this.modifiedDate = new Date();
198     }
199
200     /**
201      * Adds the pipconfig param.
202      *
203      * @param pipconfigParam the pipconfig param
204      * @return the PIP config param
205      */
206     public PipConfigParam addPipconfigParam(PipConfigParam pipconfigParam) {
207         getPipconfigParams().add(pipconfigParam);
208         pipconfigParam.setPipconfiguration(this);
209
210         return pipconfigParam;
211     }
212
213     /**
214      * Removes the pipconfig param.
215      *
216      * @param pipconfigParam the pipconfig param
217      * @return the PIP config param
218      */
219     public PipConfigParam removePipconfigParam(PipConfigParam pipconfigParam) {
220         if (pipconfigParam == null) {
221             return pipconfigParam;
222         }
223         getPipconfigParams().remove(pipconfigParam);
224         pipconfigParam.setPipconfiguration(null);
225
226         return pipconfigParam;
227     }
228
229     /**
230      * Clear config params.
231      */
232     @Transient
233     public void clearConfigParams() {
234         while (!this.pipconfigParams.isEmpty()) {
235             this.removePipconfigParam(this.pipconfigParams.iterator().next());
236         }
237     }
238
239     /**
240      * Adds the pipresolver.
241      *
242      * @param pipresolver the pipresolver
243      * @return the PIP resolver
244      */
245     public PipResolver addPipresolver(PipResolver pipresolver) {
246         getPipresolvers().add(pipresolver);
247         pipresolver.setPipconfiguration(this);
248
249         return pipresolver;
250     }
251
252     /**
253      * Removes the pipresolver.
254      *
255      * @param pipresolver the pipresolver
256      * @return the PIP resolver
257      */
258     public PipResolver removePipresolver(PipResolver pipresolver) {
259         getPipresolvers().remove(pipresolver);
260         pipresolver.setPipconfiguration(null);
261
262         return pipresolver;
263     }
264
265     /**
266      * Checks if is read only.
267      *
268      * @return true, if is read only
269      */
270     @Transient
271     public boolean isReadOnly() {
272         return this.readOnly == '1';
273     }
274
275     /**
276      * Sets the read only flag.
277      *
278      * @param readOnly the new read only flag
279      */
280     @Transient
281     public void setReadOnlyFlag(boolean readOnly) {
282         if (readOnly) {
283             this.readOnly = '1';
284         } else {
285             this.readOnly = '0';
286         }
287     }
288
289     /**
290      * Requires resolvers.
291      *
292      * @return true, if successful
293      */
294     @Transient
295     public boolean requiresResolvers() {
296         return this.requiresResolvers == '1';
297     }
298
299     /**
300      * Sets the requires resolvers flag.
301      *
302      * @param requires the new requires resolvers flag
303      */
304     @Transient
305     public void setRequiresResolversFlag(boolean requires) {
306         if (requires) {
307             this.requiresResolvers = '1';
308         } else {
309             this.requiresResolvers = '0';
310         }
311     }
312
313     /**
314      * Import PIP configurations.
315      *
316      * @param properties the properties
317      * @return the collection
318      */
319     @Transient
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;
325         }
326         for (String id : Splitter.on(',').trimResults().omitEmptyStrings().split(engines)) {
327             PipConfiguration configuration;
328             try {
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");
337             }
338         }
339
340         return configurations;
341     }
342
343     /**
344      * Read properties.
345      *
346      * @param id the id
347      * @param properties the properties
348      * @throws PIPException the PIP exception
349      */
350     @Transient
351     protected void readProperties(String id, Properties properties) throws PIPException {
352         //
353         // Save the id if we don't have one already
354         //
355
356         if (this.id == 0) {
357             try {
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");
362             }
363         }
364         //
365         // Get its classname, this MUST exist.
366         //
367         this.classname = properties.getProperty(id + ".classname");
368         if (this.classname == null) {
369             throw new PIPException("PIP Engine defined without a classname");
370         }
371         //
372         // Go through each property
373         //
374         for (Object propertyKey : properties.keySet()) {
375             readProperty(id, properties, propertyKey);
376         }
377         //
378         // Make sure we have a name at least
379         //
380         if (this.name == null) {
381             this.name = id;
382         }
383     }
384
385     /**
386      * Read a property into the PIP configuration.
387      *
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
392      */
393     private void readProperty(String id, Properties properties, Object key) throws PIPException {
394         if (!key.toString().startsWith(id)) {
395             return;
396         }
397         if (key.equals(id + ".classname")) {
398             //
399             // We already saved this
400             //
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")) {
408             //
409             // It has resolvers, make sure this is set to true if
410             // it has been already.
411             //
412             this.setRequiresResolversFlag(true);
413             //
414             // Parse the resolvers
415             //
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);
420             }
421         } else if (key.toString().startsWith(id + ".resolver")) {
422             //
423             // Ignore, the PipResolver will parse these values
424             //
425         } else {
426             //
427             // Config Parameter
428             //
429             this.addPipconfigParam(new PipConfigParam(key.toString().substring(id.length() + 1),
430                             properties.getProperty(key.toString())));
431         }
432     }
433
434     /**
435      * Gets the configuration.
436      *
437      * @param name the name
438      * @return the configuration
439      */
440     @Transient
441     public Map<String, String> getConfiguration(String name) {
442         String prefix;
443         if (name == null) {
444             prefix = Integer.toString(this.id);
445         } else {
446             prefix = name;
447         }
448         if (!prefix.endsWith(".")) {
449             prefix = prefix + ".";
450         }
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);
456         }
457         if (this.issuer != null) {
458             map.put(prefix + "issuer", this.issuer);
459         }
460
461         for (PipConfigParam param : this.pipconfigParams) {
462             map.put(prefix + param.getParamName(), param.getParamValue());
463         }
464
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);
472             ids.add(idd);
473         }
474         if (!ids.isEmpty()) {
475             map.put(prefix + "resolvers", Joiner.on(',').join(ids));
476         }
477         return map;
478     }
479
480     /**
481      * Generate properties.
482      *
483      * @param name the name
484      * @return the properties
485      */
486     @Transient
487     public Properties generateProperties(String name) {
488         String prefix;
489         if (name == null) {
490             prefix = Integer.toString(this.id);
491         } else {
492             if (name.endsWith(".")) {
493                 prefix = name;
494             } else {
495                 prefix = name + ".";
496                 /**
497                  * Instantiates a new PIP configuration.
498                  */
499
500             }
501         }
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);
508         }
509         if (this.issuer != null && !this.issuer.isEmpty()) {
510             props.setProperty(prefix + "issuer", this.issuer);
511         }
512
513         for (PipConfigParam param : this.pipconfigParams) {
514             props.setProperty(prefix + param.getParamName(), param.getParamValue());
515         }
516
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);
523             ids.add(idd);
524         }
525         if (!ids.isEmpty()) {
526             props.setProperty(prefix + "resolvers", Joiner.on(',').join(ids));
527         }
528         return props;
529     }
530 }