2 * Copyright 2017 ZTE Corporation.
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
16 package org.onap.holmes.engine.manager;
\r
17 import java.io.StringReader;
\r
18 import java.util.ArrayList;
\r
19 import java.util.HashSet;
\r
20 import java.util.List;
\r
21 import java.util.Locale;
\r
22 import java.util.Set;
\r
23 import javax.annotation.PostConstruct;
\r
24 import javax.annotation.PreDestroy;
\r
25 import javax.inject.Inject;
\r
26 import lombok.extern.slf4j.Slf4j;
\r
27 import org.drools.compiler.kie.builder.impl.InternalKieModule;
\r
28 import org.jvnet.hk2.annotations.Service;
\r
29 import org.kie.api.KieBase;
\r
30 import org.kie.api.KieServices;
\r
31 import org.kie.api.builder.KieBuilder;
\r
32 import org.kie.api.builder.KieFileSystem;
\r
33 import org.kie.api.builder.KieRepository;
\r
34 import org.kie.api.builder.Message;
\r
35 import org.kie.api.builder.Message.Level;
\r
36 import org.kie.api.builder.model.KieBaseModel;
\r
37 import org.kie.api.builder.model.KieModuleModel;
\r
38 import org.kie.api.builder.model.KieSessionModel;
\r
39 import org.kie.api.conf.EqualityBehaviorOption;
\r
40 import org.kie.api.conf.EventProcessingOption;
\r
41 import org.kie.api.definition.KiePackage;
\r
42 import org.kie.api.io.KieResources;
\r
43 import org.kie.api.io.ResourceType;
\r
44 import org.kie.api.runtime.KieContainer;
\r
45 import org.kie.api.runtime.KieSession;
\r
46 import org.kie.api.runtime.conf.ClockTypeOption;
\r
47 import org.kie.api.runtime.rule.FactHandle;
\r
48 import org.onap.holmes.common.api.stat.VesAlarm;
\r
49 import org.onap.holmes.common.dmaap.DmaapService;
\r
50 import org.onap.holmes.engine.request.DeployRuleRequest;
\r
51 import org.onap.holmes.common.api.entity.CorrelationRule;
\r
52 import org.onap.holmes.common.exception.CorrelationException;
\r
53 import org.onap.holmes.common.utils.ExceptionUtil;
\r
54 import org.onap.holmes.engine.wrapper.RuleMgtWrapper;
\r
58 public class DroolsEngine {
\r
60 private final static int ENABLE = 1;
\r
61 private final Set<String> packageNames = new HashSet<String>();
\r
63 private RuleMgtWrapper ruleMgtWrapper;
\r
65 private KieBase kieBase;
\r
66 private KieSession kieSession;
\r
67 private KieContainer kieContainer;
\r
68 private KieFileSystem kfs;
\r
69 private KieServices ks;
\r
70 private KieBuilder kieBuilder;
\r
71 private KieResources resources;
\r
72 private KieRepository kieRepository;
\r
75 private void init() {
\r
79 } catch (Exception e) {
\r
80 log.error("Failed to start the service: " + e.getMessage(), e);
\r
81 throw ExceptionUtil.buildExceptionResponse("Failed to start the drools engine!");
\r
85 private void start() throws CorrelationException {
\r
86 log.info("Drools Engine Initialize Beginning...");
\r
88 initEngineParameter();
\r
91 log.info("Business Rule Engine Initialize Successfully.");
\r
94 public void stop() {
\r
95 this.kieSession.dispose();
\r
98 public void initEngineParameter() {
\r
99 this.ks = KieServices.Factory.get();
\r
100 this.resources = ks.getResources();
\r
101 this.kieRepository = ks.getRepository();
\r
102 this.kfs = createKieFileSystemWithKProject(ks);
\r
104 this.kieBuilder = ks.newKieBuilder(kfs).buildAll();
\r
105 this.kieContainer = ks.newKieContainer(kieRepository.getDefaultReleaseId());
\r
107 this.kieBase = kieContainer.getKieBase();
\r
108 this.kieSession = kieContainer.newKieSession();
\r
111 private void initDeployRule() throws CorrelationException {
\r
112 List<CorrelationRule> rules = ruleMgtWrapper.queryRuleByEnable(ENABLE);
\r
114 if (rules.isEmpty()) {
\r
117 for (CorrelationRule rule : rules) {
\r
118 if (rule.getContent() != null) {
\r
119 deployRuleFromDB(rule.getContent());
\r
120 DmaapService.loopControlNames.put(rule.getPackageName(), rule.getClosedControlLoopName());
\r
125 private void deployRuleFromDB(String ruleContent) throws CorrelationException {
\r
127 StringReader reader = new StringReader(ruleContent);
\r
128 kfs.write("src/main/resources/rules/rule.drl",
\r
129 this.resources.newReaderResource(reader,"UTF-8").setResourceType(ResourceType.DRL));
\r
130 kieBuilder = ks.newKieBuilder(kfs).buildAll();
\r
132 InternalKieModule internalKieModule = (InternalKieModule)kieBuilder.getKieModule();
\r
133 kieContainer.updateToVersion(internalKieModule.getReleaseId());
\r
134 } catch (Exception e) {
\r
135 throw new CorrelationException(e.getMessage(), e);
\r
137 kieSession.fireAllRules();
\r
140 public synchronized String deployRule(DeployRuleRequest rule, Locale locale)
\r
141 throws CorrelationException {
\r
143 StringReader reader = new StringReader(rule.getContent());
\r
144 kfs.write("src/main/resources/rules/rule.drl",
\r
145 this.resources.newReaderResource(reader,"UTF-8").setResourceType(ResourceType.DRL));
\r
146 kieBuilder = ks.newKieBuilder(kfs).buildAll();
\r
148 judgeRuleContent(locale, kieBuilder, true);
\r
150 InternalKieModule internalKieModule = (InternalKieModule)kieBuilder.getKieModule();;
\r
151 String packageName = internalKieModule.getKnowledgePackagesForKieBase("KBase").iterator().next().getName();
\r
153 kieContainer.updateToVersion(internalKieModule.getReleaseId());
\r
154 } catch (Exception e) {
\r
155 throw new CorrelationException("Failed to deploy the rule.", e);
\r
157 packageNames.add(packageName);
\r
158 kieSession.fireAllRules();
\r
159 return packageName;
\r
162 public synchronized void undeployRule(String packageName, Locale locale)
\r
163 throws CorrelationException {
\r
164 KiePackage kiePackage = kieBase.getKiePackage(packageName);
\r
165 if (null == kiePackage) {
\r
166 throw new CorrelationException("The rule " + packageName + " does not exist!");
\r
169 kieBase.removeKiePackage(kiePackage.getName());
\r
170 } catch (Exception e) {
\r
171 throw new CorrelationException("Failed to delete the rule: " + packageName, e);
\r
173 packageNames.remove(kiePackage.getName());
\r
176 public void compileRule(String content, Locale locale)
\r
177 throws CorrelationException {
\r
178 StringReader reader = new StringReader(content);
\r
180 kfs.write("src/main/resources/rules/rule.drl",
\r
181 this.resources.newReaderResource(reader,"UTF-8").setResourceType(ResourceType.DRL));
\r
183 kieBuilder = ks.newKieBuilder(kfs).buildAll();
\r
185 judgeRuleContent(locale, kieBuilder, false);
\r
188 private void judgeRuleContent(Locale locale, KieBuilder kbuilder, boolean judgePackageName)
\r
189 throws CorrelationException {
\r
190 if (kbuilder.getResults().hasMessages(Message.Level.ERROR)) {
\r
191 String errorMsg = "There are errors in the rule: " + kbuilder.getResults()
\r
192 .getMessages(Level.ERROR).toString();
\r
193 log.error(errorMsg);
\r
194 throw new CorrelationException(errorMsg);
\r
196 InternalKieModule internalKieModule = null;
\r
198 internalKieModule = (InternalKieModule) kbuilder.getKieModule();
\r
199 } catch (Exception e) {
\r
200 throw new CorrelationException("There are errors in the rule!" + e.getMessage(), e);
\r
202 if (internalKieModule == null) {
\r
203 throw new CorrelationException("There are errors in the rule!");
\r
205 String packageName = internalKieModule.getKnowledgePackagesForKieBase("KBase").iterator().next().getName();
\r
207 if (queryAllPackage().contains(packageName) && judgePackageName) {
\r
208 throw new CorrelationException("The rule " + packageName + " already exists in the drools engine.");
\r
212 public void putRaisedIntoStream(VesAlarm raiseAlarm) {
\r
213 FactHandle factHandle = this.kieSession.getFactHandle(raiseAlarm);
\r
214 if (factHandle != null) {
\r
215 Object obj = this.kieSession.getObject(factHandle);
\r
216 if (obj != null && obj instanceof VesAlarm) {
\r
217 raiseAlarm.setRootFlag(((VesAlarm) obj).getRootFlag());
\r
219 this.kieSession.delete(factHandle);
\r
221 this.kieSession.insert(raiseAlarm);
\r
222 this.kieSession.fireAllRules();
\r
225 public List<String> queryAllPackage() {
\r
226 List<KiePackage> kiePackages = (List<KiePackage>)kieBase.getKiePackages();
\r
227 List<String> list = new ArrayList<>();
\r
228 for(KiePackage kiePackage : kiePackages) {
\r
229 list.add(kiePackage.getName());
\r
234 private KieFileSystem createKieFileSystemWithKProject(KieServices ks) {
\r
235 KieModuleModel kieModuleModel = ks.newKieModuleModel();
\r
236 KieBaseModel kieBaseModel = kieModuleModel.newKieBaseModel("KBase")
\r
237 .addPackage("rules")
\r
239 .setEqualsBehavior(EqualityBehaviorOption.EQUALITY)
\r
240 .setEventProcessingMode(EventProcessingOption.STREAM);
\r
241 KieSessionModel kieSessionModel = kieBaseModel.newKieSessionModel("KSession")
\r
242 .setDefault( true )
\r
243 .setType( KieSessionModel.KieSessionType.STATEFUL )
\r
244 .setClockType( ClockTypeOption.get("realtime") );
\r
245 KieFileSystem kfs = ks.newKieFileSystem();
\r
246 kfs.writeKModuleXML(kieModuleModel.toXML());
\r
250 private void avoidDeployBug() {
\r
251 String tmp = Math.random() + "";
\r
252 String rule = "package justInOrderToAvoidDeployBug" + tmp.substring(2);
\r
253 kfs.write("src/main/resources/rules/rule.drl", rule);
\r
254 kieBuilder = ks.newKieBuilder(kfs).buildAll();
\r
255 InternalKieModule internalKieModule = (InternalKieModule)kieBuilder.getKieModule();
\r
256 String packageName = internalKieModule.getKnowledgePackagesForKieBase("KBase").iterator().next().getName();
\r
257 kieRepository.addKieModule(internalKieModule);
\r
258 kieContainer.updateToVersion(internalKieModule.getReleaseId());
\r
260 KiePackage kiePackage = kieBase.getKiePackage(packageName);
\r
261 kieBase.removeKiePackage(kiePackage.getName());
\r