Log exception
[policy/drools-pdp.git] / policy-management / src / main / java / org / onap / policy / drools / server / restful / RestManager.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * policy-management
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.drools.server.restful;
22
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Properties;
29 import java.util.UUID;
30 import java.util.regex.Pattern;
31
32 import javax.ws.rs.Consumes;
33 import javax.ws.rs.DELETE;
34 import javax.ws.rs.DefaultValue;
35 import javax.ws.rs.GET;
36 import javax.ws.rs.POST;
37 import javax.ws.rs.PUT;
38 import javax.ws.rs.Path;
39 import javax.ws.rs.PathParam;
40 import javax.ws.rs.Produces;
41 import javax.ws.rs.QueryParam;
42 import javax.ws.rs.core.MediaType;
43 import javax.ws.rs.core.Response;
44 import javax.ws.rs.core.Response.Status;
45
46 import org.onap.policy.drools.controller.DroolsController;
47 import org.onap.policy.drools.event.comm.TopicEndpoint;
48 import org.onap.policy.drools.event.comm.TopicSink;
49 import org.onap.policy.drools.event.comm.TopicSource;
50 import org.onap.policy.drools.event.comm.bus.DmaapTopicSink;
51 import org.onap.policy.drools.event.comm.bus.DmaapTopicSource;
52 import org.onap.policy.drools.event.comm.bus.NoopTopicSink;
53 import org.onap.policy.drools.event.comm.bus.UebTopicSink;
54 import org.onap.policy.drools.event.comm.bus.UebTopicSource;
55 import org.onap.policy.drools.features.PolicyControllerFeatureAPI;
56 import org.onap.policy.drools.features.PolicyEngineFeatureAPI;
57 import org.onap.policy.drools.properties.PolicyProperties;
58 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
59 import org.onap.policy.drools.protocol.coders.EventProtocolCoder.CoderFilters;
60 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
61 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter.FilterRule;
62 import org.onap.policy.drools.protocol.coders.ProtocolCoderToolset;
63 import org.onap.policy.drools.protocol.configuration.ControllerConfiguration;
64 import org.onap.policy.drools.protocol.configuration.PdpdConfiguration;
65 import org.onap.policy.drools.system.PolicyController;
66 import org.onap.policy.drools.system.PolicyEngine;
67 import org.onap.policy.drools.utils.LoggerUtil;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 import ch.qos.logback.classic.LoggerContext;
72 import io.swagger.annotations.Api;
73 import io.swagger.annotations.ApiOperation;
74 import io.swagger.annotations.ApiParam;
75 import io.swagger.annotations.ApiResponse;
76 import io.swagger.annotations.ApiResponses;
77 import io.swagger.annotations.Info;
78 import io.swagger.annotations.SwaggerDefinition;
79 import io.swagger.annotations.Tag;
80
81
82 /**
83  * Telemetry JAX-RS Interface to the PDP-D
84  */
85
86 @Path("/policy/pdp")
87 @Produces(MediaType.APPLICATION_JSON)
88 @Consumes(MediaType.APPLICATION_JSON)
89 @Api
90 @SwaggerDefinition(
91     info = @Info(description = "PDP-D Telemetry Services", version = "v1.0",
92         title = "PDP-D Telemetry"),
93     consumes = {MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN},
94     produces = {MediaType.APPLICATION_JSON}, schemes = {SwaggerDefinition.Scheme.HTTP},
95     tags = {@Tag(name = "pdp-d-telemetry", description = "Drools PDP Telemetry Operations")})
96 public class RestManager {
97   /**
98    * Logger
99    */
100   private static Logger logger = LoggerFactory.getLogger(RestManager.class);
101
102   @GET
103   @Path("engine")
104   @ApiOperation(value = "Retrieves the Engine Operational Status",
105       notes = "Top-level abstraction.  Provides a global view of resources",
106       response = PolicyEngine.class)
107   public Response engine() {
108     return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build();
109   }
110
111   @DELETE
112   @Path("engine")
113   @ApiOperation(value = "Shuts down the Engine",
114       notes = "Deleting the engine, the top-level abstraction, equivalenty shuts it down",
115       response = PolicyEngine.class)
116   public Response engineShutdown() {
117     try {
118       PolicyEngine.manager.shutdown();
119     } catch (final IllegalStateException e) {
120       logger.error("{}: cannot shutdown {} because of {}", this, PolicyEngine.manager,
121           e.getMessage(), e);
122       return Response.status(Response.Status.BAD_REQUEST).entity(PolicyEngine.manager).build();
123     }
124
125     return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build();
126   }
127
128   @GET
129   @Path("engine/features")
130   @ApiOperation(value = "Engine Features",
131       notes = "Provides the list of loaded features using the PolicyEngineFeatureAPI",
132       responseContainer = "List")
133   public Response engineFeatures() {
134     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build();
135   }
136
137   @GET
138   @Path("engine/features/inventory")
139   @ApiOperation(value = "Engine Detailed Feature Inventory",
140       notes = "Provides detailed list of loaded features using the PolicyEngineFeatureAPI",
141       responseContainer = "List", response = PolicyEngineFeatureAPI.class)
142   public Response engineFeaturesInventory() {
143     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatureProviders())
144         .build();
145   }
146
147   @GET
148   @Path("engine/features/{featureName}")
149   @ApiOperation(value = "Engine Feature",
150       notes = "Provides Details for a given feature Engine Provider",
151       response = PolicyEngineFeatureAPI.class)
152   @ApiResponses(value = {@ApiResponse(code = 404, message = "The feature cannot be found")})
153   public Response engineFeature(@ApiParam(value = "Feature Name",
154       required = true) @PathParam("featureName") String featureName) {
155     try {
156       return Response.status(Response.Status.OK)
157           .entity(PolicyEngine.manager.getFeatureProvider(featureName)).build();
158     } catch (final IllegalArgumentException iae) {
159       logger.debug("feature unavailable: {}", featureName, iae);
160       return Response.status(Response.Status.NOT_FOUND).entity(new Error(iae.getMessage())).build();
161     }
162   }
163
164   @GET
165   @Path("engine/inputs")
166   @ApiOperation(value = "Engine Input Ports", notes = "List of input ports",
167       responseContainer = "List")
168   public Response engineInputs() {
169     return Response.status(Response.Status.OK).entity(Arrays.asList(Inputs.values())).build();
170   }
171
172   @POST
173   @Path("engine/inputs/configuration")
174   @ApiOperation(value = "Engine Input Configuration Requests",
175       notes = "Feeds a configuration request input into the Engine")
176   @ApiResponses(
177       value = {@ApiResponse(code = 406, message = "The configuration request cannot be honored")})
178   public Response engineUpdate(@ApiParam(value = "Configuration to apply",
179       required = true) PdpdConfiguration configuration) {
180     final PolicyController controller = null;
181     boolean success = true;
182     try {
183       success = PolicyEngine.manager.configure(configuration);
184     } catch (final Exception e) {
185       success = false;
186       logger.info("{}: cannot configure {} because of {}", this, PolicyEngine.manager,
187           e.getMessage(), e);
188     }
189
190     if (!success)
191       return Response.status(Response.Status.NOT_ACCEPTABLE)
192           .entity(new Error("cannot perform operation")).build();
193     else
194       return Response.status(Response.Status.OK).entity(controller).build();
195   }
196
197   @GET
198   @Path("engine/properties")
199   @ApiOperation(value = "Engine Configuration Properties",
200       notes = "Used for booststrapping the engine", response = Properties.class)
201   public Response engineProperties() {
202     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getProperties()).build();
203   }
204
205   @GET
206   @Path("engine/environment")
207   @ApiOperation(value = "Engine Environment Properties",
208       notes = "Installation and OS environment properties used by the engine",
209       response = Properties.class)
210   public Response engineEnvironment() {
211     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getEnvironment())
212         .build();
213   }
214
215   @GET
216   @Path("engine/environment/{envProperty}")
217   @Consumes(MediaType.TEXT_PLAIN)
218   @ApiOperation(value = "Gets an environment variable", response = String.class)
219   public Response engineEnvironment(@ApiParam(value = "Environment Property",
220       required = true) @PathParam("envProperty") String envProperty) {
221     return Response.status(Response.Status.OK)
222         .entity(PolicyEngine.manager.getEnvironmentProperty(envProperty)).build();
223   }
224
225   @PUT
226   @Path("engine/environment/{envProperty}")
227   @Consumes(MediaType.TEXT_PLAIN)
228   @Produces(MediaType.TEXT_PLAIN)
229   @ApiOperation(value = "Adds a new environment value to the engine", response = String.class)
230   public Response engineEnvironmentAdd(
231       @ApiParam(value = "Environment Property",
232           required = true) @PathParam("envProperty") String envProperty,
233       @ApiParam(value = "Environment Value", required = true) String envValue) {
234     final String previousValue = PolicyEngine.manager.setEnvironmentProperty(envProperty, envValue);
235     return Response.status(Response.Status.OK).entity(previousValue).build();
236   }
237
238   @GET
239   @Path("engine/switches")
240   @ApiOperation(value = "Engine Control Switches", notes = "List of the Engine Control Switches",
241       responseContainer = "List")
242   public Response engineSwitches() {
243     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
244   }
245
246   @PUT
247   @Path("engine/switches/activation")
248   @ApiOperation(value = "Switches on the Engine Activation Switch",
249       notes = "Turns on Activation Switch on the Engine. This order entails that the engine "
250           + "and controllers are unlocked and started",
251       response = PolicyEngine.class)
252   public Response engineActivation() {
253     boolean success = true;
254     try {
255       PolicyEngine.manager.activate();
256     } catch (final Exception e) {
257       success = false;
258       logger.info("{}: cannot activate {} because of {}", this, PolicyEngine.manager,
259           e.getMessage(), e);
260     }
261
262     if (!success)
263       return Response.status(Response.Status.NOT_ACCEPTABLE)
264           .entity(new Error("cannot perform operation")).build();
265     else
266       return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build();
267   }
268
269   @DELETE
270   @Path("engine/switches/activation")
271   @ApiOperation(value = "Switches off Engine Activation Switch",
272       notes = "Turns off the Activation Switch on the Engine. This order entails that the engine "
273           + "and controllers are locked (with the exception of those resources defined as unmanaged)",
274       response = PolicyEngine.class)
275   public Response engineDeactivation() {
276     boolean success = true;
277     try {
278       PolicyEngine.manager.deactivate();
279     } catch (final Exception e) {
280       success = false;
281       logger.info("{}: cannot deactivate {} because of {}", this, PolicyEngine.manager,
282           e.getMessage(), e);
283     }
284
285     if (!success)
286       return Response.status(Response.Status.NOT_ACCEPTABLE)
287           .entity(new Error("cannot perform operation")).build();
288     else
289       return Response.status(Response.Status.OK).entity(PolicyEngine.manager).build();
290   }
291
292   @PUT
293   @Path("engine/switches/lock")
294   @ApiOperation(value = "Switches on the Engine Lock Control",
295       notes = "This switch locks all the engine resources as a whole, except those that are defined unmanaged",
296       response = PolicyEngine.class)
297   @ApiResponses(value = {
298       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
299           + "this request to be fulfilled")})
300   public Response engineLock() {
301     final boolean success = PolicyEngine.manager.lock();
302     if (success)
303       return Response.status(Status.OK).entity(PolicyEngine.manager).build();
304     else
305       return Response.status(Status.NOT_ACCEPTABLE).entity(new Error("cannot perform operation"))
306           .build();
307   }
308
309   @DELETE
310   @Path("engine/switches/lock")
311   @ApiOperation(value = "Switches off the Lock control",
312       notes = "This switch locks all the engine resources as a whole, except those that are defined unmanaged",
313       response = PolicyEngine.class)
314   @ApiResponses(value = {
315       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
316           + "this request to be fulfilled")})
317   public Response engineUnlock() {
318     final boolean success = PolicyEngine.manager.unlock();
319     if (success)
320       return Response.status(Status.OK).entity(PolicyEngine.manager).build();
321     else
322       return Response.status(Status.NOT_ACCEPTABLE).entity(new Error("cannot perform operation"))
323           .build();
324   }
325
326   @GET
327   @Path("engine/controllers")
328   @ApiOperation(value = "Lists the Policy Controllers Names",
329       notes = "Unique Policy Controller Identifiers", responseContainer = "List")
330   public Response controllers() {
331     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllerIds())
332         .build();
333   }
334
335   @GET
336   @Path("engine/controllers/inventory")
337   @ApiOperation(value = "Lists the Policy Controllers",
338       notes = "Detailed list of Policy Controllers", responseContainer = "List",
339       response = PolicyController.class)
340   public Response controllerInventory() {
341     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getPolicyControllers())
342         .build();
343   }
344
345   @POST
346   @Path("engine/controllers")
347   @ApiOperation(value = "Creates and starts a new Policy Controller",
348       notes = "Controller creation based on properties", response = PolicyController.class)
349   @ApiResponses(value = {
350       @ApiResponse(code = 400, message = "Invalid configuration information has been provided"),
351       @ApiResponse(code = 304, message = "The controller already exists"),
352       @ApiResponse(code = 406,
353           message = "The administrative state of the system prevents it "
354               + "from processing this request"),
355       @ApiResponse(code = 206,
356           message = "The controller has been created " + "but cannot be started"),
357       @ApiResponse(code = 201,
358           message = "The controller has been succesfully created and started")})
359   public Response controllerAdd(
360       @ApiParam(value = "Configuration Properties to apply", required = true) Properties config) {
361     if (config == null)
362       return Response.status(Response.Status.BAD_REQUEST)
363           .entity(new Error("A configuration must be provided")).build();
364
365     final String controllerName = config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME);
366     if (controllerName == null || controllerName.isEmpty())
367       return Response.status(Response.Status.BAD_REQUEST)
368           .entity(new Error(
369               "Configuration must have an entry for " + PolicyProperties.PROPERTY_CONTROLLER_NAME))
370           .build();
371
372     PolicyController controller;
373     try {
374       controller = PolicyController.factory.get(controllerName);
375       if (controller != null)
376         return Response.status(Response.Status.NOT_MODIFIED).entity(controller).build();
377     } catch (final IllegalArgumentException e) {
378         logger.trace("OK ", e);
379       // This is OK
380     } catch (final IllegalStateException e) {
381       logger.info("{}: cannot get policy-controller because of {}", this, e.getMessage(), e);
382       return Response.status(Response.Status.NOT_ACCEPTABLE)
383           .entity(new Error(controllerName + " not found")).build();
384     }
385
386     try {
387       controller = PolicyEngine.manager.createPolicyController(
388           config.getProperty(PolicyProperties.PROPERTY_CONTROLLER_NAME), config);
389     } catch (IllegalArgumentException | IllegalStateException e) {
390       logger.warn("{}: cannot create policy-controller because of {}", this, e.getMessage(), e);
391       return Response.status(Response.Status.BAD_REQUEST).entity(new Error(e.getMessage())).build();
392     }
393
394     try {
395       final boolean success = controller.start();
396       if (!success) {
397         logger.info("{}: cannot start {}", this, controller);
398         return Response.status(Response.Status.PARTIAL_CONTENT)
399             .entity(new Error(controllerName + " can't be started")).build();
400       }
401     } catch (final IllegalStateException e) {
402       logger.info("{}: cannot start {} because of {}", this, controller, e.getMessage(), e);;
403       return Response.status(Response.Status.PARTIAL_CONTENT).entity(controller).build();
404     }
405
406     return Response.status(Response.Status.CREATED).entity(controller).build();
407   }
408
409   @GET
410   @Path("engine/controllers/features")
411   @ApiOperation(value = "Lists of Feature Providers Identifiers",
412       notes = "Unique Policy Controller Identifiers", responseContainer = "List")
413   public Response controllerFeatures() {
414     return Response.status(Response.Status.OK).entity(PolicyEngine.manager.getFeatures()).build();
415   }
416
417   @GET
418   @Path("engine/controllers/features/inventory")
419   @ApiOperation(value = "Detailed Controllers Feature Inventory",
420       notes = "Provides detailed list of loaded features using the PolicyControllerFeatureAPI",
421       responseContainer = "List", response = PolicyControllerFeatureAPI.class)
422   public Response controllerFeaturesInventory() {
423     return Response.status(Response.Status.OK)
424         .entity(PolicyController.factory.getFeatureProviders()).build();
425   }
426
427   @GET
428   @Path("engine/controllers/features/{featureName}")
429   @ApiOperation(value = "Controller Feature",
430       notes = "Provides Details for a given Policy Controller feature provider",
431       response = PolicyControllerFeatureAPI.class)
432   @ApiResponses(value = {@ApiResponse(code = 404, message = "The feature cannot be found")})
433   public Response controllerFeature(@ApiParam(value = "Feature Name",
434       required = true) @PathParam("featureName") String featureName) {
435     try {
436       return Response.status(Response.Status.OK)
437           .entity(PolicyController.factory.getFeatureProvider(featureName)).build();
438     } catch (final IllegalArgumentException iae) {
439       logger.debug("{}: cannot feature {} because of {}", this, featureName, iae.getMessage(), iae);
440       return Response.status(Response.Status.NOT_FOUND).entity(new Error(iae.getMessage())).build();
441     }
442   }
443
444   @GET
445   @Path("engine/controllers/{controller}")
446   @ApiOperation(value = "Retrieves a Policy Controller",
447       notes = "A Policy Controller is a concrete drools application abstraction.  "
448           + "It aggregates networking, drools, and other resources,"
449           + "as provides operational controls over drools applications",
450       response = PolicyController.class)
451   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
452       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
453           + "this request to be fulfilled")})
454   public Response controller(@ApiParam(value = "Policy Controller Name",
455       required = true) @PathParam("controller") String controllerName) {
456     try {
457       return Response.status(Response.Status.OK)
458           .entity(PolicyController.factory.get(controllerName)).build();
459     } catch (final IllegalArgumentException e) {
460       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
461           e.getMessage(), e);
462       return Response.status(Response.Status.NOT_FOUND)
463           .entity(new Error(controllerName + " not found")).build();
464     } catch (final IllegalStateException e) {
465       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
466           e.getMessage(), e);
467       return Response.status(Response.Status.NOT_ACCEPTABLE)
468           .entity(new Error(controllerName + " not acceptable")).build();
469     }
470   }
471
472   @DELETE
473   @Path("engine/controllers/{controller}")
474   @ApiOperation(value = "Deletes a Policy Controller",
475       notes = "A Policy Controller is a concrete drools application abstraction.  "
476           + "It aggregates networking, drools, and other resources,"
477           + "as provides operational controls over drools applications",
478       response = PolicyController.class)
479   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
480       @ApiResponse(code = 406,
481           message = "The system is an administrative state that prevents "
482               + "this request to be fulfilled"),
483       @ApiResponse(code = 500,
484           message = "A problem has occurred while deleting the Policy Controller")})
485   public Response controllerDelete(@ApiParam(value = "Policy Controller Name",
486       required = true) @PathParam("controller") String controllerName) {
487
488     PolicyController controller;
489     try {
490       controller = PolicyController.factory.get(controllerName);
491       if (controller == null)
492         return Response.status(Response.Status.BAD_REQUEST)
493             .entity(new Error(controllerName + "  does not exist")).build();
494     } catch (final IllegalArgumentException e) {
495       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
496           e.getMessage(), e);
497       return Response.status(Response.Status.BAD_REQUEST)
498           .entity(new Error(controllerName + " not found: " + e.getMessage())).build();
499     } catch (final IllegalStateException e) {
500       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
501           e.getMessage(), e);
502       return Response.status(Response.Status.NOT_ACCEPTABLE)
503           .entity(new Error(controllerName + " not acceptable")).build();
504     }
505
506     try {
507       PolicyEngine.manager.removePolicyController(controllerName);
508     } catch (IllegalArgumentException | IllegalStateException e) {
509       logger.debug("{}: cannot remove policy-controller {} because of {}", this, controllerName,
510           e.getMessage(), e);
511       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
512           .entity(new Error(e.getMessage())).build();
513     }
514
515     return Response.status(Response.Status.OK).entity(controller).build();
516   }
517
518   @GET
519   @Path("engine/controllers/{controller}/properties")
520   @ApiOperation(value = "Retrieves the configuration properties of a Policy Controller",
521       notes = "Configuration resources used by the controller if Properties format",
522       response = PolicyController.class)
523   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
524       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
525           + "this request to be fulfilled")})
526   public Response controllerProperties(@ApiParam(value = "Policy Controller Name",
527       required = true) @PathParam("controller") String controllerName) {
528     try {
529       final PolicyController controller = PolicyController.factory.get(controllerName);
530       return Response.status(Response.Status.OK).entity(controller.getProperties()).build();
531     } catch (final IllegalArgumentException e) {
532       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
533           e.getMessage(), e);
534       return Response.status(Response.Status.NOT_FOUND)
535           .entity(new Error(controllerName + " not found")).build();
536     } catch (final IllegalStateException e) {
537       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
538           e.getMessage(), e);
539       return Response.status(Response.Status.NOT_ACCEPTABLE)
540           .entity(new Error(controllerName + " not acceptable")).build();
541     }
542   }
543
544   @GET
545   @Path("engine/controllers/{controller}/inputs")
546   @ApiOperation(value = "Policy Controller Input Ports", notes = "List of input ports",
547       responseContainer = "List")
548   public Response controllerInputs() {
549     return Response.status(Response.Status.OK).entity(Arrays.asList(Inputs.values())).build();
550   }
551
552   @POST
553   @Path("engine/controllers/{controller}/inputs/configuration")
554   @ApiOperation(value = "Policy Controller Input Configuration Requests",
555       notes = "Feeds a configuration request input into the given Policy Controller")
556   @ApiResponses(value = {@ApiResponse(code = 400, message = "The configuration request is invalid"),
557       @ApiResponse(code = 406, message = "The configuration request cannot be honored")})
558   public Response controllerUpdate(
559       @ApiParam(value = "Policy Controller Name",
560           required = true) @PathParam("controller") String controllerName,
561       @ApiParam(value = "Configuration to apply",
562           required = true) ControllerConfiguration controllerConfiguration) {
563
564     if (controllerName == null || controllerName.isEmpty() || controllerConfiguration == null
565         || controllerConfiguration.getName().intern() != controllerName)
566       return Response.status(Response.Status.BAD_REQUEST)
567           .entity("A valid or matching controller names must be provided").build();
568
569     PolicyController controller;
570     try {
571       controller = PolicyEngine.manager.updatePolicyController(controllerConfiguration);
572       if (controller == null)
573         return Response.status(Response.Status.BAD_REQUEST)
574             .entity(new Error(controllerName + "  does not exist")).build();
575     } catch (final IllegalArgumentException e) {
576       logger.info("{}: cannot update policy-controller {} because of {}", this, controllerName,
577           e.getMessage(), e);
578       return Response.status(Response.Status.BAD_REQUEST)
579           .entity(new Error(controllerName + " not found: " + e.getMessage())).build();
580     } catch (final Exception e) {
581       logger.info("{}: cannot update policy-controller {} because of {}", this, controllerName,
582           e.getMessage(), e);
583       return Response.status(Response.Status.NOT_ACCEPTABLE)
584           .entity(new Error(controllerName + " not acceptable")).build();
585     }
586
587     return Response.status(Response.Status.OK).entity(controller).build();
588   }
589
590   @GET
591   @Path("engine/controllers/{controller}/switches")
592   @ApiOperation(value = "Policy Controller Switches",
593       notes = "List of the Policy Controller Switches", responseContainer = "List")
594   public Response controllerSwitches() {
595     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
596   }
597
598   @PUT
599   @Path("engine/controllers/{controller}/switches/lock")
600   @ApiOperation(value = "Switches on the Policy Controller Lock Control",
601       notes = "This action on the switch locks the Policy Controller",
602       response = PolicyController.class)
603   @ApiResponses(value = {
604       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
605           + "this request to be fulfilled")})
606   public Response controllerLock(@ApiParam(value = "Policy Controller Name",
607       required = true) @PathParam("controller") String controllerName) {
608     final PolicyController policyController = PolicyController.factory.get(controllerName);
609     final boolean success = policyController.lock();
610     if (success)
611       return Response.status(Status.OK).entity(policyController).build();
612     else
613       return Response.status(Status.NOT_ACCEPTABLE)
614           .entity(new Error("Controller " + controllerName + " cannot be locked")).build();
615   }
616
617   @DELETE
618   @Path("engine/controllers/{controller}/switches/lock")
619   @ApiOperation(value = "Switches off the Policy Controller Lock Control",
620       notes = "This action on the switch unlocks the Policy Controller",
621       response = PolicyController.class)
622   @ApiResponses(value = {
623       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
624           + "this request to be fulfilled")})
625   public Response controllerUnlock(@ApiParam(value = "Policy Controller Name",
626       required = true) @PathParam("controller") String controllerName) {
627     final PolicyController policyController = PolicyController.factory.get(controllerName);
628     final boolean success = policyController.unlock();
629     if (success)
630       return Response.status(Status.OK).entity(policyController).build();
631     else
632       return Response.status(Status.NOT_ACCEPTABLE)
633           .entity(new Error("Controller " + controllerName + " cannot be unlocked")).build();
634   }
635
636   @GET
637   @Path("engine/controllers/{controller}/drools")
638   @ApiOperation(value = "Retrieves the Drools Controller subcomponent of the Policy Controller",
639       notes = "The Drools Controller provides an abstraction over the Drools subsystem",
640       response = DroolsController.class)
641   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
642       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
643           + "this request to be fulfilled")})
644   public Response drools(@ApiParam(value = "Policy Controller Name",
645       required = true) @PathParam("controller") String controllerName) {
646     try {
647       final DroolsController drools = this.getDroolsController(controllerName);
648       return Response.status(Response.Status.OK).entity(drools).build();
649     } catch (final IllegalArgumentException e) {
650       logger.debug("{}: cannot get drools-controller {} because of {}", this, controllerName,
651           e.getMessage(), e);
652       return Response.status(Response.Status.NOT_FOUND)
653           .entity(new Error(controllerName + " not found")).build();
654     } catch (final IllegalStateException e) {
655       logger.debug("{}: cannot get drools-controller {} because of {}", this, controllerName,
656           e.getMessage(), e);
657       return Response.status(Response.Status.NOT_ACCEPTABLE)
658           .entity(new Error(controllerName + " not acceptable")).build();
659     }
660   }
661
662   @GET
663   @Path("engine/controllers/{controller}/drools/facts")
664   @ApiOperation(value = "Retrieves Facts Summary information for a given controller",
665       notes = "Provides the session names, and a count of fact object in the drools working memory",
666       responseContainer = "Map")
667   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
668       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
669           + "this request to be fulfilled")})
670   public Response droolsFacts(@ApiParam(value = "Policy Controller Name",
671       required = true) @PathParam("controller") String controllerName) {
672     try {
673       final Map<String, Long> sessionCounts = new HashMap<>();
674       final DroolsController drools = this.getDroolsController(controllerName);
675       for (final String session : drools.getSessionNames()) {
676         sessionCounts.put(session, drools.factCount(session));
677       }
678       return Response.status(Response.Status.OK).entity(sessionCounts).build();
679     } catch (final IllegalArgumentException e) {
680       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
681           e.getMessage(), e);
682       return Response.status(Response.Status.NOT_FOUND)
683           .entity(new Error(controllerName + " not found")).build();
684     } catch (final IllegalStateException e) {
685       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
686           e.getMessage(), e);
687       return Response.status(Response.Status.NOT_ACCEPTABLE)
688           .entity(new Error(controllerName + " not acceptable")).build();
689     }
690   }
691
692   @GET
693   @Path("engine/controllers/{controller}/drools/facts/{session}")
694   @ApiOperation(value = "Retrieves Fact Types (classnames) for a given controller and its count",
695       notes = "The fact types are the classnames of the objects inserted in the drools working memory",
696       responseContainer = "Map")
697   @ApiResponses(
698       value = {@ApiResponse(code = 404, message = "The controller or session cannot be found"),
699           @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
700               + "this request to be fulfilled")})
701   public Response droolsFacts(
702       @ApiParam(value = "Policy Controller Name",
703           required = true) @PathParam("controller") String controllerName,
704       @ApiParam(value = "Drools Session Name",
705           required = true) @PathParam("session") String sessionName) {
706     try {
707       final DroolsController drools = this.getDroolsController(controllerName);
708       return Response.status(Response.Status.OK).entity(drools.factClassNames(sessionName)).build();
709     } catch (final IllegalArgumentException e) {
710       logger.debug("{}: cannot get drools-controller {} because of {}", this, controllerName,
711           e.getMessage(), e);
712       return Response.status(Response.Status.NOT_FOUND).entity(new Error("entity not found"))
713           .build();
714     } catch (final IllegalStateException e) {
715       logger.debug("{}: cannot get drools-controller {} because of {}", this, controllerName,
716           e.getMessage(), e);
717       return Response.status(Response.Status.NOT_ACCEPTABLE)
718           .entity(new Error(controllerName + ":" + sessionName + " not acceptable")).build();
719     }
720   }
721
722   @GET
723   @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}")
724   @ApiOperation(
725       value = "Retrieves fact objects of a given type in the drools working memory"
726           + "for a given controller and session",
727       notes = "The fact types are the classnames of the objects inserted in the drools working memory",
728       responseContainer = "List")
729   @ApiResponses(value = {
730       @ApiResponse(code = 404, message = "The controller, session, or fact type cannot be found"),
731       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
732           + "this request to be fulfilled")})
733   public Response droolsFacts(
734       @ApiParam(value = "Fact count",
735           required = false) @DefaultValue("false") @QueryParam("count") boolean count,
736       @ApiParam(value = "Policy Controller Name",
737           required = true) @PathParam("controller") String controllerName,
738       @ApiParam(value = "Drools Session Name",
739           required = true) @PathParam("session") String sessionName,
740       @ApiParam(value = "Drools Fact Type",
741           required = true) @PathParam("factType") String factType) {
742     try {
743       final DroolsController drools = this.getDroolsController(controllerName);
744       final List<Object> facts = drools.facts(sessionName, factType, false);
745       if (!count)
746         return Response.status(Response.Status.OK).entity(facts).build();
747       else
748         return Response.status(Response.Status.OK).entity(facts.size()).build();
749     } catch (final IllegalArgumentException e) {
750       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
751           e.getMessage(), e);
752       return Response.status(Response.Status.NOT_FOUND)
753           .entity(new Error(controllerName + ":" + sessionName + ":" + factType + " not found"))
754           .build();
755     } catch (final IllegalStateException e) {
756       logger.debug("{}: cannot get policy-controller {} because of {}", this, controllerName,
757           e.getMessage(), e);
758       return Response.status(Response.Status.NOT_ACCEPTABLE)
759           .entity(
760               new Error(controllerName + ":" + sessionName + ":" + factType + " not acceptable"))
761           .build();
762     }
763   }
764
765   @DELETE
766   @Path("engine/controllers/{controller}/drools/facts/{session}/{factType}")
767   @ApiOperation(
768       value = "Deletes all the fact objects of a given type from the drools working memory"
769           + "for a given controller and session.   The objects retracted from the working "
770           + "memory are provided in the response.",
771       notes = "The fact types are the classnames of the objects inserted in the drools working memory",
772       responseContainer = "List")
773   @ApiResponses(value = {
774       @ApiResponse(code = 404, message = "The controller, session, or fact type, cannot be found"),
775       @ApiResponse(code = 406,
776           message = "The system is an administrative state that prevents "
777               + "this request to be fulfilled"),
778       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
779   public Response droolsFactsDelete(
780       @ApiParam(value = "Policy Controller Name",
781           required = true) @PathParam("controller") String controllerName,
782       @ApiParam(value = "Drools Session Name",
783           required = true) @PathParam("session") String sessionName,
784       @ApiParam(value = "Drools Fact Type",
785           required = true) @PathParam("factType") String factType) {
786     try {
787       final DroolsController drools = this.getDroolsController(controllerName);
788       final List<Object> facts = drools.facts(sessionName, factType, true);
789       return Response.status(Response.Status.OK).entity(facts).build();
790     } catch (final IllegalArgumentException e) {
791       logger.debug("{}: cannot get: drools-controller {}, session {}, factType {}, because of {}",
792           this, controllerName, sessionName, factType, e.getMessage(), e);
793       return Response.status(Response.Status.NOT_FOUND)
794           .entity(new Error(controllerName + ":" + sessionName + ":" + factType + " not found"))
795           .build();
796     } catch (final IllegalStateException e) {
797       logger.debug("{}: cannot get: drools-controller {}, session {}, factType {}, because of {}",
798           this, controllerName, sessionName, factType, e.getMessage(), e);
799       return Response.status(Response.Status.NOT_ACCEPTABLE)
800           .entity(
801               new Error(controllerName + ":" + sessionName + ":" + factType + " not acceptable"))
802           .build();
803     } catch (final Exception e) {
804       logger.debug("{}: cannot get: drools-controller {}, session {}, factType {}, because of {}",
805           this, controllerName, sessionName, factType, e.getMessage(), e);
806       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
807           .entity(new Error(e.getMessage())).build();
808     }
809   }
810
811   @GET
812   @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}")
813   @ApiOperation(
814       value = "Gets all the fact objects returned by a DRL query with no parameters from the drools working memory"
815           + "for a given controller and session",
816       notes = "The DRL query must be defined in the DRL file", responseContainer = "List")
817   @ApiResponses(value = {
818       @ApiResponse(code = 404,
819           message = "The controller, session, or query information, cannot be found"),
820       @ApiResponse(code = 406,
821           message = "The system is an administrative state that prevents "
822               + "this request to be fulfilled"),
823       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
824   public Response droolsFacts(
825       @ApiParam(value = "Fact count",
826           required = false) @DefaultValue("false") @QueryParam("count") boolean count,
827       @ApiParam(value = "Policy Controller Name",
828           required = true) @PathParam("controller") String controllerName,
829       @ApiParam(value = "Drools Session Name",
830           required = true) @PathParam("session") String sessionName,
831       @ApiParam(value = "Query Name Present in DRL",
832           required = true) @PathParam("query") String queryName,
833       @ApiParam(value = "Query Identifier Present in the DRL Query",
834           required = true) @PathParam("queriedEntity") String queriedEntity) {
835     try {
836       final DroolsController drools = this.getDroolsController(controllerName);
837       final List<Object> facts = drools.factQuery(sessionName, queryName, queriedEntity, false);
838       if (!count)
839         return Response.status(Response.Status.OK).entity(facts).build();
840       else
841         return Response.status(Response.Status.OK).entity(facts.size()).build();
842     } catch (final IllegalArgumentException e) {
843       logger.debug(
844           "{}: cannot get: drools-controller {}, session {}, query {}, entity {} because of {}",
845           this, controllerName, sessionName, queryName, queriedEntity, e.getMessage(), e);
846       return Response.status(Response.Status.NOT_FOUND)
847           .entity(new Error(
848               controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not found"))
849           .build();
850     } catch (final IllegalStateException e) {
851       logger.debug(
852           "{}: cannot get: drools-controller {}, session {}, query {}, entity {} because of {}",
853           this, controllerName, sessionName, queryName, queriedEntity, e.getMessage(), e);
854       return Response.status(Response.Status.NOT_ACCEPTABLE).entity(new Error(
855           controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not acceptable"))
856           .build();
857     } catch (final Exception e) {
858       logger.debug(
859           "{}: cannot get: drools-controller {}, session {}, query {}, entity {} because of {}",
860           this, controllerName, sessionName, queryName, queriedEntity, e.getMessage(), e);
861       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
862           .entity(new Error(e.getMessage())).build();
863     }
864   }
865
866   @POST
867   @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}")
868   @ApiOperation(
869       value = "Gets all the fact objects returned by a DRL query with parameters from the drools working memory"
870           + "for a given controller and session",
871       notes = "The DRL query with parameters must be defined in the DRL file",
872       responseContainer = "List")
873   @ApiResponses(value = {
874       @ApiResponse(code = 404,
875           message = "The controller, session, or query information, cannot be found"),
876       @ApiResponse(code = 406,
877           message = "The system is an administrative state that prevents "
878               + "this request to be fulfilled"),
879       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
880   public Response droolsFacts(
881       @ApiParam(value = "Policy Controller Name",
882           required = true) @PathParam("controller") String controllerName,
883       @ApiParam(value = "Drools Session Name",
884           required = true) @PathParam("session") String sessionName,
885       @ApiParam(value = "Query Name Present in DRL",
886           required = true) @PathParam("query") String queryName,
887       @ApiParam(value = "Query Identifier Present in the DRL Query",
888           required = true) @PathParam("queriedEntity") String queriedEntity,
889       @ApiParam(value = "Query Parameter Values to pass in the DRL Query",
890           required = false) List<Object> queryParameters) {
891     try {
892       final DroolsController drools = this.getDroolsController(controllerName);
893       List<Object> facts;
894       if (queryParameters == null || queryParameters.isEmpty())
895         facts = drools.factQuery(sessionName, queryName, queriedEntity, false);
896       else
897         facts = drools.factQuery(sessionName, queryName, queriedEntity, false,
898             queryParameters.toArray());
899       return Response.status(Response.Status.OK).entity(facts).build();
900     } catch (final IllegalArgumentException e) {
901       logger.debug(
902           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
903           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
904           e.getMessage(), e);
905       return Response.status(Response.Status.NOT_FOUND)
906           .entity(new Error(
907               controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not found"))
908           .build();
909     } catch (final IllegalStateException e) {
910       logger.debug(
911           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
912           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
913           e.getMessage(), e);
914       return Response.status(Response.Status.NOT_ACCEPTABLE).entity(new Error(
915           controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not acceptable"))
916           .build();
917     } catch (final Exception e) {
918       logger.debug(
919           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
920           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
921           e.getMessage(), e);
922       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
923           .entity(new Error(e.getMessage())).build();
924     }
925   }
926
927   @DELETE
928   @Path("engine/controllers/{controller}/drools/facts/{session}/{query}/{queriedEntity}")
929   @ApiOperation(
930       value = "Deletes all the fact objects returned by a DRL query with parameters from the drools working memory"
931           + "for a given controller and session",
932       notes = "The DRL query with parameters must be defined in the DRL file",
933       responseContainer = "List")
934   @ApiResponses(value = {
935       @ApiResponse(code = 404,
936           message = "The controller, session, or query information, cannot be found"),
937       @ApiResponse(code = 406,
938           message = "The system is an administrative state that prevents "
939               + "this request to be fulfilled"),
940       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
941   public Response droolsFactsDelete(
942       @ApiParam(value = "Policy Controller Name",
943           required = true) @PathParam("controller") String controllerName,
944       @ApiParam(value = "Drools Session Name",
945           required = true) @PathParam("session") String sessionName,
946       @ApiParam(value = "Query Name Present in DRL",
947           required = true) @PathParam("query") String queryName,
948       @ApiParam(value = "Query Identifier Present in the DRL Query",
949           required = true) @PathParam("queriedEntity") String queriedEntity,
950       @ApiParam(value = "Query Parameter Values to pass in the DRL Query",
951           required = false) List<Object> queryParameters) {
952     try {
953       final DroolsController drools = this.getDroolsController(controllerName);
954       List<Object> facts;
955       if (queryParameters == null || queryParameters.isEmpty())
956         facts = drools.factQuery(sessionName, queryName, queriedEntity, true);
957       else
958         facts = drools.factQuery(sessionName, queryName, queriedEntity, true,
959             queryParameters.toArray());
960       return Response.status(Response.Status.OK).entity(facts).build();
961     } catch (final IllegalArgumentException e) {
962       logger.debug(
963           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
964           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
965           e.getMessage(), e);
966       return Response.status(Response.Status.NOT_FOUND)
967           .entity(new Error(
968               controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not found"))
969           .build();
970     } catch (final IllegalStateException e) {
971       logger.debug(
972           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
973           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
974           e.getMessage(), e);
975       return Response.status(Response.Status.NOT_ACCEPTABLE).entity(new Error(
976           controllerName + ":" + sessionName + ":" + queryName + queriedEntity + " not acceptable"))
977           .build();
978     } catch (final Exception e) {
979       logger.debug(
980           "{}: cannot get: drools-controller {}, session {}, query {}, entity {}, params {} because of {}",
981           this, controllerName, sessionName, queryName, queriedEntity, queryParameters,
982           e.getMessage(), e);
983       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
984           .entity(new Error(e.getMessage())).build();
985     }
986   }
987
988   @POST
989   @Path("engine/controllers/tools/coders/decoders/filters/rules/{ruleName}")
990   @ApiOperation(
991       value = "Produces a Decoder Rule Filter in a format that the Policy Controller can understand",
992       notes = "The result can be used with other APIs to attach a filter to a decoder")
993   public Response rules(
994       @ApiParam(value = "Negate regex?",
995           required = true) @DefaultValue("false") @QueryParam("negate") boolean negate,
996       @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String name,
997       @ApiParam(value = "Regex expression", required = true) String regex) {
998     String literalRegex = Pattern.quote(regex);
999     if (negate)
1000       literalRegex = "^(?!" + literalRegex + "$).*";
1001
1002     return Response.status(Status.OK).entity(new JsonProtocolFilter.FilterRule(name, literalRegex))
1003         .build();
1004   }
1005
1006   @GET
1007   @Path("engine/controllers/{controller}/decoders")
1008   @ApiOperation(value = "Gets all the decoders used by a controller",
1009       notes = "A Policy Controller uses decoders to deserialize incoming network messages from "
1010           + "subscribed network topics into specific (fact) objects. "
1011           + "The deserialized (fact) object will typically be inserted in the drools working "
1012           + " memory of the controlled drools application.",
1013       responseContainer = "List", response = ProtocolCoderToolset.class)
1014   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
1015       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1016           + "this request to be fulfilled")})
1017   public Response decoders(@ApiParam(value = "Policy Controller Name",
1018       required = true) @PathParam("controller") String controllerName) {
1019     try {
1020       final DroolsController drools = this.getDroolsController(controllerName);
1021       final List<ProtocolCoderToolset> decoders =
1022           EventProtocolCoder.manager.getDecoders(drools.getGroupId(), drools.getArtifactId());
1023       return Response.status(Response.Status.OK).entity(decoders).build();
1024     } catch (final IllegalArgumentException e) {
1025       logger.debug("{}: cannot get decoders for policy-controller {} because of {}", this,
1026           controllerName, e.getMessage(), e);
1027       return Response.status(Response.Status.NOT_FOUND)
1028           .entity(new Error(controllerName + " not found")).build();
1029     } catch (final IllegalStateException e) {
1030       logger.debug("{}: cannot get decoders for policy-controller {} because of {}", this,
1031           controllerName, e.getMessage(), e);
1032       return Response.status(Response.Status.NOT_ACCEPTABLE)
1033           .entity(new Error(controllerName + " not acceptable")).build();
1034     }
1035   }
1036
1037   @GET
1038   @Path("engine/controllers/{controller}/decoders/filters")
1039   @ApiOperation(value = "Gets all the filters used by a controller",
1040       notes = "A Policy Controller uses decoders to deserialize incoming network messages from "
1041           + "subscribed network topics into specific (fact) objects. "
1042           + "The deserialized (fact) object will typically be inserted in the drools working "
1043           + " memory of the controlled drools application."
1044           + "Acceptance filters are used to filter out undesired network messages for the given controller",
1045       responseContainer = "List", response = CoderFilters.class)
1046   @ApiResponses(value = {@ApiResponse(code = 404, message = "The controller cannot be found"),
1047       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1048           + "this request to be fulfilled")})
1049   public Response decoderFilters(@ApiParam(value = "Policy Controller Name",
1050       required = true) @PathParam("controller") String controllerName) {
1051     try {
1052       final DroolsController drools = this.getDroolsController(controllerName);
1053       final List<CoderFilters> filters =
1054           EventProtocolCoder.manager.getDecoderFilters(drools.getGroupId(), drools.getArtifactId());
1055       return Response.status(Response.Status.OK).entity(filters).build();
1056     } catch (final IllegalArgumentException e) {
1057       logger.debug("{}: cannot get decoders for policy-controller {} because of {}", this,
1058           controllerName, e.getMessage(), e);
1059       return Response.status(Response.Status.NOT_FOUND)
1060           .entity(new Error(controllerName + " not found")).build();
1061     } catch (final IllegalStateException e) {
1062       logger.debug("{}: cannot get decoders for policy-controller {} because of {}", this,
1063           controllerName, e.getMessage(), e);
1064       return Response.status(Response.Status.NOT_ACCEPTABLE)
1065           .entity(new Error(controllerName + " not acceptable")).build();
1066     }
1067   }
1068
1069   @GET
1070   @Path("engine/controllers/{controller}/decoders/{topic}")
1071   @ApiOperation(value = "Gets all the decoders in use by a controller for a networked topic",
1072       notes = "A Policy Controller uses decoders to deserialize incoming network messages from "
1073           + "subscribed network topics into specific (fact) objects. "
1074           + "The deserialized (fact) object will typically be inserted in the drools working "
1075           + " memory of the controlled drools application.",
1076       responseContainer = "List", response = ProtocolCoderToolset.class)
1077   @ApiResponses(
1078       value = {@ApiResponse(code = 404, message = "The controller or topic cannot be found"),
1079           @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1080               + "this request to be fulfilled")})
1081   public Response decoder(
1082       @ApiParam(value = "Policy Controller Name",
1083           required = true) @PathParam("controller") String controllerName,
1084       @ApiParam(value = "Networked Topic Name", required = true) @PathParam("topic") String topic) {
1085     try {
1086       final DroolsController drools = this.getDroolsController(controllerName);
1087       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1088           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1089       return Response.status(Response.Status.OK).entity(decoder).build();
1090     } catch (final IllegalArgumentException e) {
1091       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1092           controllerName, topic, e.getMessage(), e);
1093       return Response.status(Response.Status.NOT_FOUND)
1094           .entity(new Error(controllerName + ":" + topic + " not found")).build();
1095     } catch (final IllegalStateException e) {
1096       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1097           controllerName, topic, e.getMessage(), e);
1098       return Response.status(Response.Status.NOT_ACCEPTABLE)
1099           .entity(new Error(controllerName + ":" + topic + " not acceptable")).build();
1100     }
1101   }
1102
1103   @GET
1104   @Path("engine/controllers/{controller}/decoders/{topic}/filters")
1105   @ApiOperation(
1106       value = "Gets all filters attached to decoders for a given networked topic in use by a controller",
1107       notes = "A Policy Controller uses decoders to deserialize incoming network messages from "
1108           + "subscribed network topics into specific (fact) objects. "
1109           + "The deserialized (fact) object will typically be inserted in the drools working "
1110           + " memory of the controlled drools application."
1111           + "Acceptance filters are used to filter out undesired network messages for the given controller",
1112       responseContainer = "List", response = CoderFilters.class)
1113   @ApiResponses(
1114       value = {@ApiResponse(code = 404, message = "The controller or topic cannot be found"),
1115           @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1116               + "this request to be fulfilled")})
1117   public Response decoderFilter(
1118       @ApiParam(value = "Policy Controller Name",
1119           required = true) @PathParam("controller") String controllerName,
1120       @ApiParam(value = "Networked Topic Name", required = true) @PathParam("topic") String topic) {
1121     try {
1122       final DroolsController drools = this.getDroolsController(controllerName);
1123       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1124           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1125       if (decoder == null)
1126         return Response.status(Response.Status.BAD_REQUEST)
1127             .entity(new Error(topic + "  does not exist")).build();
1128       else
1129         return Response.status(Response.Status.OK).entity(decoder.getCoders()).build();
1130     } catch (final IllegalArgumentException e) {
1131       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1132           controllerName, topic, e.getMessage(), e);
1133       return Response.status(Response.Status.NOT_FOUND)
1134           .entity(new Error(controllerName + ":" + topic + " not found")).build();
1135     } catch (final IllegalStateException e) {
1136       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1137           controllerName, topic, e.getMessage(), e);
1138       return Response.status(Response.Status.NOT_ACCEPTABLE)
1139           .entity(new Error(controllerName + ":" + topic + " not acceptable")).build();
1140     }
1141   }
1142
1143   @GET
1144   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}")
1145   @ApiOperation(
1146       value = "Gets all filters attached to decoders for a given subscribed networked topic "
1147           + "and fact type",
1148       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1149           + "multiple topics and therefore its attached decoders. "
1150           + "A Policy Controller uses filters to further specify the fact mapping.  "
1151           + "Filters are applied on a per fact type (classname).",
1152       responseContainer = "List", response = CoderFilters.class)
1153   @ApiResponses(value = {
1154       @ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"),
1155       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1156           + "this request to be fulfilled")})
1157   public Response decoderFilter(
1158       @ApiParam(value = "Policy Controller Name",
1159           required = true) @PathParam("controller") String controllerName,
1160       @ApiParam(value = "Networked Topic Name", required = true) @PathParam("topic") String topic,
1161       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass) {
1162     try {
1163       final DroolsController drools = this.getDroolsController(controllerName);
1164       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1165           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1166       final CoderFilters filters = decoder.getCoder(factClass);
1167       if (filters == null)
1168         return Response.status(Response.Status.BAD_REQUEST)
1169             .entity(new Error(topic + ":" + factClass + "  does not exist")).build();
1170       else
1171         return Response.status(Response.Status.OK).entity(filters).build();
1172     } catch (final IllegalArgumentException e) {
1173       logger.debug(
1174           "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}",
1175           this, controllerName, topic, factClass, e.getMessage(), e);
1176       return Response.status(Response.Status.NOT_FOUND)
1177           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build();
1178     } catch (final IllegalStateException e) {
1179       logger.debug(
1180           "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}",
1181           this, controllerName, topic, factClass, e.getMessage(), e);
1182       return Response.status(Response.Status.NOT_ACCEPTABLE)
1183           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable"))
1184           .build();
1185     }
1186   }
1187
1188   @PUT
1189   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}")
1190   @ApiOperation(
1191       value = "Attaches filters to the decoder for a given networked topic " + "and fact type",
1192       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1193           + "multiple topics and therefore its attached decoders. "
1194           + "A Policy Controller uses filters to further specify the fact mapping.  "
1195           + "Filters are applied on a per fact type (classname).",
1196       responseContainer = "List", response = CoderFilters.class)
1197   @ApiResponses(value = {
1198       @ApiResponse(code = 404,
1199           message = "The controller, topic, fact type, cannot be found, "
1200               + "or a filter has not been provided"),
1201       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1202           + "this request to be fulfilled")})
1203   public Response decoderFilter(
1204       @ApiParam(value = "Policy Controller Name",
1205           required = true) @PathParam("controller") String controllerName,
1206       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1207       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass,
1208       @ApiParam(value = "Configuration Filter", required = true) JsonProtocolFilter configFilters) {
1209
1210     if (configFilters == null) {
1211       return Response.status(Response.Status.BAD_REQUEST)
1212           .entity(new Error("Configuration Filters not provided")).build();
1213     }
1214
1215     try {
1216       final DroolsController drools = this.getDroolsController(controllerName);
1217       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1218           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1219       final CoderFilters filters = decoder.getCoder(factClass);
1220       if (filters == null)
1221         return Response.status(Response.Status.BAD_REQUEST)
1222             .entity(new Error(topic + ":" + factClass + "  does not exist")).build();
1223       filters.setFilter(configFilters);
1224       return Response.status(Response.Status.OK).entity(filters).build();
1225     } catch (final IllegalArgumentException e) {
1226       logger.debug(
1227           "{}: cannot get decoder filters for policy-controller {} topic {} type {} filters {} because of {}",
1228           this, controllerName, topic, factClass, configFilters, e.getMessage(), e);
1229       return Response.status(Response.Status.NOT_FOUND)
1230           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build();
1231     } catch (final IllegalStateException e) {
1232       logger.debug(
1233           "{}: cannot get decoder filters for policy-controller {} topic {} type {} filters {} because of {}",
1234           this, controllerName, topic, factClass, configFilters, e.getMessage(), e);
1235       return Response.status(Response.Status.NOT_ACCEPTABLE)
1236           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable"))
1237           .build();
1238     }
1239   }
1240
1241   @GET
1242   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules")
1243   @ApiOperation(value = "Gets the filter rules attached to a topic decoder of a controller",
1244       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1245           + "multiple topics and therefore its attached decoders. "
1246           + "A Policy Controller uses filters to further specify the fact mapping.  "
1247           + "Filters are applied on a per fact type and are composed of field matching rules. ",
1248       responseContainer = "List", response = FilterRule.class)
1249   @ApiResponses(value = {
1250       @ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"),
1251       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1252           + "this request to be fulfilled")})
1253   public Response decoderFilterRules(
1254       @ApiParam(value = "Policy Controller Name",
1255           required = true) @PathParam("controller") String controllerName,
1256       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1257       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass) {
1258     try {
1259       final DroolsController drools = this.getDroolsController(controllerName);
1260       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1261           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1262
1263       final CoderFilters filters = decoder.getCoder(factClass);
1264       if (filters == null)
1265         return Response.status(Response.Status.BAD_REQUEST)
1266             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  does not exist"))
1267             .build();
1268
1269       final JsonProtocolFilter filter = filters.getFilter();
1270       if (filter == null)
1271         return Response.status(Response.Status.BAD_REQUEST)
1272             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  no filters"))
1273             .build();
1274
1275       return Response.status(Response.Status.OK).entity(filter.getRules()).build();
1276     } catch (final IllegalArgumentException e) {
1277       logger.debug(
1278           "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}",
1279           this, controllerName, topic, factClass, e.getMessage(), e);
1280       return Response.status(Response.Status.NOT_FOUND)
1281           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build();
1282     } catch (final IllegalStateException e) {
1283       logger.debug(
1284           "{}: cannot get decoder filters for policy-controller {} topic {} type {} because of {}",
1285           this, controllerName, topic, factClass, e.getMessage(), e);
1286       return Response.status(Response.Status.NOT_ACCEPTABLE)
1287           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable"))
1288           .build();
1289     }
1290   }
1291
1292   @GET
1293   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}")
1294   @ApiOperation(value = "Gets a filter rule by name attached to a topic decoder of a controller",
1295       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1296           + "multiple topics and therefore its attached decoders. "
1297           + "A Policy Controller uses filters to further specify the fact mapping.  "
1298           + "Filters are applied on a per fact type and are composed of field matching rules. ",
1299       responseContainer = "List", response = FilterRule.class)
1300   @ApiResponses(value = {
1301       @ApiResponse(code = 404,
1302           message = "The controller, topic, fact type, or rule name cannot be found"),
1303       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1304           + "this request to be fulfilled")})
1305   public Response decoderFilterRules(
1306       @ApiParam(value = "Policy Controller Name",
1307           required = true) @PathParam("controller") String controllerName,
1308       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1309       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass,
1310       @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName) {
1311     try {
1312       final DroolsController drools = this.getDroolsController(controllerName);
1313       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1314           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1315
1316       final CoderFilters filters = decoder.getCoder(factClass);
1317       if (filters == null)
1318         return Response.status(Response.Status.BAD_REQUEST)
1319             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  does not exist"))
1320             .build();
1321
1322       final JsonProtocolFilter filter = filters.getFilter();
1323       if (filter == null)
1324         return Response.status(Response.Status.BAD_REQUEST)
1325             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  no filters"))
1326             .build();
1327
1328       return Response.status(Response.Status.OK).entity(filter.getRules(ruleName)).build();
1329     } catch (final IllegalArgumentException e) {
1330       logger.debug(
1331           "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}",
1332           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1333       return Response.status(Response.Status.NOT_FOUND)
1334           .entity(new Error(
1335               controllerName + ":" + topic + ":" + factClass + ": " + ruleName + " not found"))
1336           .build();
1337     } catch (final IllegalStateException e) {
1338       logger.debug(
1339           "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}",
1340           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1341       return Response.status(Response.Status.NOT_ACCEPTABLE)
1342           .entity(new Error(
1343               controllerName + ":" + topic + ":" + factClass + ":" + ruleName + " not acceptable"))
1344           .build();
1345     }
1346   }
1347
1348   @DELETE
1349   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules/{ruleName}")
1350   @ApiOperation(value = "Deletes a filter rule by name attached to a topic decoder of a controller",
1351       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1352           + "multiple topics and therefore its attached decoders. "
1353           + "A Policy Controller uses filters to further specify the fact mapping.  "
1354           + "Filters are applied on a per fact type and are composed of field matching rules. ",
1355       responseContainer = "List", response = FilterRule.class)
1356   @ApiResponses(value = {
1357       @ApiResponse(code = 404,
1358           message = "The controller, topic, fact type, or rule name cannot be found"),
1359       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1360           + "this request to be fulfilled")})
1361   public Response decoderFilterRuleDelete(
1362       @ApiParam(value = "Policy Controller Name",
1363           required = true) @PathParam("controller") String controllerName,
1364       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1365       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass,
1366       @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName,
1367       @ApiParam(value = "Filter Rule", required = true) FilterRule rule) {
1368
1369     try {
1370       final DroolsController drools = this.getDroolsController(controllerName);
1371       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1372           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1373
1374       final CoderFilters filters = decoder.getCoder(factClass);
1375       if (filters == null)
1376         return Response.status(Response.Status.BAD_REQUEST)
1377             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  does not exist"))
1378             .build();
1379
1380       final JsonProtocolFilter filter = filters.getFilter();
1381       if (filter == null)
1382         return Response.status(Response.Status.BAD_REQUEST)
1383             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  no filters"))
1384             .build();
1385
1386       if (rule == null) {
1387         filter.deleteRules(ruleName);
1388         return Response.status(Response.Status.OK).entity(filter.getRules()).build();
1389       }
1390
1391       if (rule.getName() == null || !rule.getName().equals(ruleName))
1392         return Response.status(Response.Status.BAD_REQUEST)
1393             .entity(new Error(controllerName + ":" + topic + ":" + factClass + ":" + ruleName
1394                 + " rule name request inconsistencies (" + rule.getName() + ")"))
1395             .build();
1396
1397       filter.deleteRule(ruleName, rule.getRegex());
1398       return Response.status(Response.Status.OK).entity(filter.getRules()).build();
1399     } catch (final IllegalArgumentException e) {
1400       logger.debug(
1401           "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}",
1402           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1403       return Response.status(Response.Status.NOT_FOUND)
1404           .entity(new Error(
1405               controllerName + ":" + topic + ":" + factClass + ": " + ruleName + " not found"))
1406           .build();
1407     } catch (final IllegalStateException e) {
1408       logger.debug(
1409           "{}: cannot get decoder filters for policy-controller {} topic {} type {} rule {} because of {}",
1410           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1411       return Response.status(Response.Status.NOT_ACCEPTABLE)
1412           .entity(new Error(
1413               controllerName + ":" + topic + ":" + factClass + ":" + ruleName + " not acceptable"))
1414           .build();
1415     }
1416   }
1417
1418   @PUT
1419   @Path("engine/controllers/{controller}/decoders/{topic}/filters/{factType}/rules")
1420   @ApiOperation(value = "Places a new filter rule in a topic decoder",
1421       notes = "Decoders are associated with networked topics. A Policy Controller manages "
1422           + "multiple topics and therefore its attached decoders. "
1423           + "A Policy Controller uses filters to further specify the fact mapping.  "
1424           + "Filters are applied on a per fact type and are composed of field matching rules. ",
1425       responseContainer = "List", response = FilterRule.class)
1426   @ApiResponses(value = {
1427       @ApiResponse(code = 404, message = "The controller, topic, or fact type cannot be found"),
1428       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1429           + "this request to be fulfilled")})
1430   public Response decoderFilterRule(
1431       @ApiParam(value = "Policy Controller Name",
1432           required = true) @PathParam("controller") String controllerName,
1433       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1434       @ApiParam(value = "Fact Type", required = true) @PathParam("factType") String factClass,
1435       @ApiParam(value = "Rule Name", required = true) @PathParam("ruleName") String ruleName,
1436       @ApiParam(value = "Filter Rule", required = true) FilterRule rule) {
1437
1438     try {
1439       final DroolsController drools = this.getDroolsController(controllerName);
1440       final ProtocolCoderToolset decoder = EventProtocolCoder.manager
1441           .getDecoders(drools.getGroupId(), drools.getArtifactId(), topic);
1442
1443       final CoderFilters filters = decoder.getCoder(factClass);
1444       if (filters == null)
1445         return Response.status(Response.Status.BAD_REQUEST)
1446             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  does not exist"))
1447             .build();
1448
1449       final JsonProtocolFilter filter = filters.getFilter();
1450       if (filter == null)
1451         return Response.status(Response.Status.BAD_REQUEST)
1452             .entity(new Error(controllerName + ":" + topic + ":" + factClass + "  no filters"))
1453             .build();
1454
1455       if (rule.getName() == null)
1456         return Response
1457             .status(Response.Status.BAD_REQUEST).entity(new Error(controllerName + ":" + topic + ":"
1458                 + factClass + " rule name request inconsistencies (" + rule.getName() + ")"))
1459             .build();
1460
1461       filter.addRule(rule.getName(), rule.getRegex());
1462       return Response.status(Response.Status.OK).entity(filter.getRules()).build();
1463     } catch (final IllegalArgumentException e) {
1464       logger.debug(
1465           "{}: cannot access decoder filter rules for policy-controller {} topic {} type {} rule {} because of {}",
1466           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1467       return Response.status(Response.Status.NOT_FOUND)
1468           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not found")).build();
1469     } catch (final IllegalStateException e) {
1470       logger.debug(
1471           "{}: cannot access decoder filter rules for policy-controller {} topic {} type {} rule {} because of {}",
1472           this, controllerName, topic, factClass, ruleName, e.getMessage(), e);
1473       return Response.status(Response.Status.NOT_ACCEPTABLE)
1474           .entity(new Error(controllerName + ":" + topic + ":" + factClass + " not acceptable"))
1475           .build();
1476     }
1477   }
1478
1479   @POST
1480   @Path("engine/controllers/{controller}/decoders/{topic}")
1481   @Consumes(MediaType.TEXT_PLAIN)
1482   @ApiOperation(value = "Decodes a string into a fact object, and encodes it back into a string",
1483       notes = "Tests the decode/encode functions of a controller", response = CodingResult.class)
1484   @ApiResponses(value = {@ApiResponse(code = 400, message = "Bad input has been provided"),
1485       @ApiResponse(code = 404, message = "The controller cannot be found"),
1486       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1487           + "this request to be fulfilled")})
1488   public Response decode(
1489       @ApiParam(value = "Policy Controller Name",
1490           required = true) @PathParam("controller") String controllerName,
1491       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1492       @ApiParam(value = "JSON String to decode", required = true) String json) {
1493
1494     PolicyController policyController;
1495     try {
1496       policyController = PolicyController.factory.get(controllerName);
1497     } catch (final IllegalArgumentException e) {
1498       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1499           controllerName, topic, e.getMessage(), e);
1500       return Response.status(Response.Status.NOT_FOUND)
1501           .entity(new Error(controllerName + ":" + topic + ":" + " not found")).build();
1502     } catch (final IllegalStateException e) {
1503       logger.debug("{}: cannot get decoders for policy-controller {} topic {} because of {}", this,
1504           controllerName, topic, e.getMessage(), e);
1505       return Response.status(Response.Status.NOT_ACCEPTABLE)
1506           .entity(new Error(controllerName + ":" + topic + ":" + " not acceptable")).build();
1507     }
1508
1509     final CodingResult result = new CodingResult();
1510     result.decoding = false;
1511     result.encoding = false;
1512     result.jsonEncoding = null;
1513
1514     Object event;
1515     try {
1516       event = EventProtocolCoder.manager.decode(policyController.getDrools().getGroupId(),
1517           policyController.getDrools().getArtifactId(), topic, json);
1518       result.decoding = true;
1519     } catch (final Exception e) {
1520       logger.debug("{}: cannot get policy-controller {} topic {} because of {}", this,
1521           controllerName, topic, e.getMessage(), e);
1522       return Response.status(Response.Status.BAD_REQUEST).entity(new Error(e.getMessage())).build();
1523     }
1524
1525     try {
1526       result.jsonEncoding = EventProtocolCoder.manager.encode(topic, event);
1527       result.encoding = true;
1528     } catch (final Exception e) {
1529       // continue so to propagate decoding results ..
1530       logger.debug("{}: cannot encode for policy-controller {} topic {} because of {}", this,
1531           controllerName, topic, e.getMessage(), e);
1532     }
1533
1534     return Response.status(Response.Status.OK).entity(result).build();
1535   }
1536
1537   @GET
1538   @Path("engine/controllers/{controller}/encoders")
1539   @ApiOperation(value = "Retrieves the encoder filters of a controller",
1540       notes = "The encoders serializes a fact object, typically for network transmission",
1541       responseContainer = "List", response = CoderFilters.class)
1542   @ApiResponses(value = {@ApiResponse(code = 400, message = "Bad input has been provided"),
1543       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1544           + "this request to be fulfilled")})
1545   public Response encoderFilters(@ApiParam(value = "Policy Controller Name",
1546       required = true) @PathParam("controller") String controllerName) {
1547     List<CoderFilters> encoders;
1548     try {
1549       final PolicyController controller = PolicyController.factory.get(controllerName);
1550       final DroolsController drools = controller.getDrools();
1551       encoders =
1552           EventProtocolCoder.manager.getEncoderFilters(drools.getGroupId(), drools.getArtifactId());
1553     } catch (final IllegalArgumentException e) {
1554       logger.debug("{}: cannot get encoder filters for policy-controller {} because of {}", this,
1555           controllerName, e.getMessage(), e);
1556       return Response.status(Response.Status.BAD_REQUEST)
1557           .entity(new Error(controllerName + " not found: " + e.getMessage())).build();
1558     } catch (final IllegalStateException e) {
1559       logger.debug("{}: cannot get encoder filters for policy-controller {} because of {}", this,
1560           controllerName, e.getMessage(), e);
1561       return Response.status(Response.Status.NOT_ACCEPTABLE)
1562           .entity(new Error(controllerName + " is not accepting the request")).build();
1563     }
1564
1565     return Response.status(Response.Status.OK).entity(encoders).build();
1566   }
1567
1568   @GET
1569   @Path("engine/topics")
1570   @ApiOperation(value = "Retrieves the managed topics", notes = "Network Topics Aggregation",
1571       response = TopicEndpoint.class)
1572   public Response topics() {
1573     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager).build();
1574   }
1575
1576   @GET
1577   @Path("engine/topics/switches")
1578   @ApiOperation(value = "Topics Control Switches", notes = "List of the Topic Control Switches",
1579       responseContainer = "List")
1580   public Response topicSwitches() {
1581     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
1582   }
1583
1584   @PUT
1585   @Path("engine/topics/switches/lock")
1586   @ApiOperation(value = "Locks all the managed topics",
1587       notes = "The operation affects all managed sources and sinks", response = TopicEndpoint.class)
1588   @ApiResponses(value = {
1589       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1590           + "this request to be fulfilled")})
1591   public Response topicsLock() {
1592     final boolean success = TopicEndpoint.manager.lock();
1593     if (success)
1594       return Response.status(Status.OK).entity(TopicEndpoint.manager).build();
1595     else
1596       return Response.status(Status.NOT_ACCEPTABLE).entity(new Error("cannot perform operation"))
1597           .build();
1598   }
1599
1600   @DELETE
1601   @Path("engine/topics/switches/lock")
1602   @ApiOperation(value = "Unlocks all the managed topics",
1603       notes = "The operation affects all managed sources and sinks", response = TopicEndpoint.class)
1604   @ApiResponses(value = {
1605       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1606           + "this request to be fulfilled")})
1607   public Response topicsUnlock() {
1608     final boolean success = TopicEndpoint.manager.unlock();
1609     if (success)
1610       return Response.status(Status.OK).entity(TopicEndpoint.manager).build();
1611     else
1612       return Response.status(Status.NOT_ACCEPTABLE).entity(new Error("cannot perform operation"))
1613           .build();
1614   }
1615
1616   @GET
1617   @Path("engine/topics/sources")
1618   @ApiOperation(value = "Retrieves the managed topic sources",
1619       notes = "Network Topic Sources Agregation", responseContainer = "List",
1620       response = TopicSource.class)
1621   public Response sources() {
1622     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getTopicSources())
1623         .build();
1624   }
1625
1626   @GET
1627   @Path("engine/topics/sinks")
1628   @ApiOperation(value = "Retrieves the managed topic sinks",
1629       notes = "Network Topic Sinks Agregation", responseContainer = "List",
1630       response = TopicSink.class)
1631   public Response sinks() {
1632     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getTopicSinks())
1633         .build();
1634   }
1635
1636   @GET
1637   @Path("engine/topics/sources/ueb")
1638   @ApiOperation(value = "Retrieves the UEB managed topic sources",
1639       notes = "UEB Topic Sources Agregation", responseContainer = "List",
1640       response = UebTopicSource.class)
1641   public Response uebSources() {
1642     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getUebTopicSources())
1643         .build();
1644   }
1645
1646   @GET
1647   @Path("engine/topics/sinks/ueb")
1648   @ApiOperation(value = "Retrieves the UEB managed topic sinks",
1649       notes = "UEB Topic Sinks Agregation", responseContainer = "List",
1650       response = UebTopicSink.class)
1651   public Response uebSinks() {
1652     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getUebTopicSinks())
1653         .build();
1654   }
1655
1656   @GET
1657   @Path("engine/topics/sources/dmaap")
1658   @ApiOperation(value = "Retrieves the DMaaP managed topic sources",
1659       notes = "DMaaP Topic Sources Agregation", responseContainer = "List",
1660       response = DmaapTopicSource.class)
1661   public Response dmaapSources() {
1662     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getDmaapTopicSources())
1663         .build();
1664   }
1665
1666   @GET
1667   @Path("engine/topics/sinks/dmaap")
1668   @ApiOperation(value = "Retrieves the DMaaP managed topic sinks",
1669       notes = "DMaaP Topic Sinks Agregation", responseContainer = "List",
1670       response = DmaapTopicSink.class)
1671   public Response dmaapSinks() {
1672     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getDmaapTopicSinks())
1673         .build();
1674   }
1675
1676   @GET
1677   @Path("engine/topics/sources/ueb/{topic}")
1678   @ApiOperation(value = "Retrieves an UEB managed topic source",
1679       notes = "This is an UEB Network Communicaton Endpoint source of messages for the Engine",
1680       response = UebTopicSource.class)
1681   public Response uebSourceTopic(
1682       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1683     return Response.status(Response.Status.OK)
1684         .entity(TopicEndpoint.manager.getUebTopicSource(topic)).build();
1685   }
1686
1687   @GET
1688   @Path("engine/topics/sinks/ueb/{topic}")
1689   @ApiOperation(value = "Retrieves an UEB managed topic sink",
1690       notes = "This is an UEB Network Communicaton Endpoint destination of messages from the Engine",
1691       response = UebTopicSink.class)
1692   public Response uebSinkTopic(
1693       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1694     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getUebTopicSink(topic))
1695         .build();
1696   }
1697
1698   @GET
1699   @Path("engine/topics/sources/dmaap/{topic}")
1700   @ApiOperation(value = "Retrieves a DMaaP managed topic source",
1701       notes = "This is a DMaaP Network Communicaton Endpoint source of messages for the Engine",
1702       response = DmaapTopicSource.class)
1703   public Response dmaapSourceTopic(
1704       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1705     return Response.status(Response.Status.OK)
1706         .entity(TopicEndpoint.manager.getDmaapTopicSource(topic)).build();
1707   }
1708
1709   @GET
1710   @Path("engine/topics/sinks/dmaap/{topic}")
1711   @ApiOperation(value = "Retrieves a DMaaP managed topic sink",
1712       notes = "This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine",
1713       response = DmaapTopicSink.class)
1714   public Response dmaapSinkTopic(
1715       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1716     return Response.status(Response.Status.OK)
1717         .entity(TopicEndpoint.manager.getDmaapTopicSink(topic)).build();
1718   }
1719
1720   @GET
1721   @Path("engine/topics/sources/ueb/{topic}/events")
1722   @ApiOperation(value = "Retrieves the latest events received by an UEB topic",
1723       notes = "This is a UEB Network Communicaton Endpoint source of messages for the Engine",
1724       responseContainer = "List")
1725   public Response uebSourceEvents(
1726       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1727     return Response.status(Status.OK)
1728         .entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents()))
1729         .build();
1730   }
1731
1732   @GET
1733   @Path("engine/topics/sinks/ueb/{topic}/events")
1734   @ApiOperation(value = "Retrieves the latest events sent from a topic",
1735       notes = "This is a UEB Network Communicaton Endpoint sink of messages from the Engine",
1736       responseContainer = "List")
1737   public Response uebSinkEvents(
1738       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1739     return Response.status(Status.OK)
1740         .entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSink(topic).getRecentEvents()))
1741         .build();
1742   }
1743
1744   @GET
1745   @Path("engine/topics/sources/dmaap/{topic}/events")
1746   @ApiOperation(value = "Retrieves the latest events received by a DMaaP topic",
1747       notes = "This is a DMaaP Network Communicaton Endpoint source of messages for the Engine",
1748       responseContainer = "List")
1749   public Response dmaapSourceEvents(
1750       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1751     return Response.status(Status.OK)
1752         .entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents()))
1753         .build();
1754   }
1755
1756   @GET
1757   @Path("engine/topics/sinks/dmaap/{topic}/events")
1758   @ApiOperation(value = "Retrieves the latest events send through a DMaaP topic",
1759       notes = "This is a DMaaP Network Communicaton Endpoint destination of messages from the Engine",
1760       responseContainer = "List")
1761   public Response dmaapSinkEvents(@PathParam("topic") String topic) {
1762     return Response.status(Status.OK)
1763         .entity(Arrays.asList(TopicEndpoint.manager.getDmaapTopicSink(topic).getRecentEvents()))
1764         .build();
1765   }
1766
1767   @GET
1768   @Path("engine/topics/sinks/noop")
1769   @ApiOperation(value = "Retrieves the NOOP managed topic sinks",
1770       notes = "NOOP Topic Sinks Agregation", responseContainer = "List",
1771       response = NoopTopicSink.class)
1772   public Response noopSinks() {
1773     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getNoopTopicSinks())
1774         .build();
1775   }
1776
1777   @GET
1778   @Path("engine/topics/sinks/noop/{topic}")
1779   @ApiOperation(value = "Retrieves a NOOP managed topic sink",
1780       notes = "NOOP is an dev/null Network Communicaton Sink", response = NoopTopicSink.class)
1781   public Response noopSinkTopic(
1782       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1783     return Response.status(Response.Status.OK).entity(TopicEndpoint.manager.getNoopTopicSink(topic))
1784         .build();
1785   }
1786
1787   @GET
1788   @Path("engine/topics/sinks/noop/{topic}/events")
1789   @ApiOperation(value = "Retrieves the latest events send through a NOOP topic",
1790       notes = "NOOP is an dev/null Network Communicaton Sink", responseContainer = "List")
1791   public Response noopSinkEvents(@PathParam("topic") String topic) {
1792     return Response.status(Status.OK)
1793         .entity(Arrays.asList(TopicEndpoint.manager.getNoopTopicSink(topic).getRecentEvents()))
1794         .build();
1795   }
1796
1797   @GET
1798   @Path("engine/topics/sources/ueb/{topic}/switches")
1799   @ApiOperation(value = "UEB Topic Control Switches",
1800       notes = "List of the UEB Topic Control Switches", responseContainer = "List")
1801   public Response uebTopicSwitches() {
1802     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
1803   }
1804
1805   @PUT
1806   @Path("engine/topics/sources/ueb/{topic}/switches/lock")
1807   @ApiOperation(value = "Locks an UEB Source topic", response = UebTopicSource.class)
1808   @ApiResponses(value = {
1809       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1810           + "this request to be fulfilled")})
1811   public Response uebTopicLock(
1812       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1813     final UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic);
1814     final boolean success = source.lock();
1815     if (success)
1816       return Response.status(Status.OK).entity(source).build();
1817     else
1818       return Response.status(Status.NOT_ACCEPTABLE)
1819           .entity(new Error("cannot perform operation on " + topic)).build();
1820   }
1821
1822   @DELETE
1823   @Path("engine/topics/sources/ueb/{topic}/switches/lock")
1824   @ApiOperation(value = "Unlocks an UEB Source topic", response = UebTopicSource.class)
1825   @ApiResponses(value = {
1826       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1827           + "this request to be fulfilled")})
1828   public Response uebTopicUnlock(
1829       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1830     final UebTopicSource source = TopicEndpoint.manager.getUebTopicSource(topic);
1831     final boolean success = source.unlock();
1832     if (success)
1833       return Response.status(Status.OK).entity(source).build();
1834     else
1835       return Response.status(Status.NOT_ACCEPTABLE)
1836           .entity(new Error("cannot perform operation on " + topic)).build();
1837   }
1838
1839   @GET
1840   @Path("engine/topics/sources/dmaap/{topic}/switches")
1841   @ApiOperation(value = "DMaaP Topic Control Switches",
1842       notes = "List of the DMaaP Topic Control Switches", responseContainer = "List")
1843   public Response dmaapTopicSwitches() {
1844     return Response.status(Response.Status.OK).entity(Arrays.asList(Switches.values())).build();
1845   }
1846
1847   @PUT
1848   @Path("engine/topics/sources/dmaap/{topic}/switches/lock")
1849   @ApiOperation(value = "Locks an DMaaP Source topic", response = DmaapTopicSource.class)
1850   @ApiResponses(value = {
1851       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1852           + "this request to be fulfilled")})
1853   public Response dmmapTopicLock(
1854       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1855     final DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic);
1856     final boolean success = source.lock();
1857     if (success)
1858       return Response.status(Status.OK).entity(source).build();
1859     else
1860       return Response.status(Status.NOT_ACCEPTABLE)
1861           .entity(new Error("cannot perform operation on " + topic)).build();
1862   }
1863
1864   @DELETE
1865   @Path("engine/topics/sources/dmaap/{topic}/switches/lock")
1866   @ApiOperation(value = "Unlocks an DMaaP Source topic", response = DmaapTopicSource.class)
1867   @ApiResponses(value = {
1868       @ApiResponse(code = 406, message = "The system is an administrative state that prevents "
1869           + "this request to be fulfilled")})
1870   public Response dmaapTopicUnlock(
1871       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic) {
1872     final DmaapTopicSource source = TopicEndpoint.manager.getDmaapTopicSource(topic);
1873     final boolean success = source.unlock();
1874     if (success)
1875       return Response.status(Status.OK).entity(source).build();
1876     else
1877       return Response.status(Status.SERVICE_UNAVAILABLE)
1878           .entity(new Error("cannot perform operation on " + topic)).build();
1879   }
1880
1881   @PUT
1882   @Path("engine/topics/sources/ueb/{topic}/events")
1883   @Consumes(MediaType.TEXT_PLAIN)
1884   @ApiOperation(value = "Offers an event to an UEB topic for internal processing by the engine",
1885       notes = "The offered event is treated as it was incoming from the network",
1886       responseContainer = "List")
1887   @ApiResponses(value = {
1888       @ApiResponse(code = 404, message = "The topic information cannot be found"),
1889       @ApiResponse(code = 406,
1890           message = "The system is an administrative state that prevents "
1891               + "this request to be fulfilled"),
1892       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
1893   public Response uebOffer(
1894       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1895       @ApiParam(value = "Network Message", required = true) String json) {
1896     try {
1897       final UebTopicSource uebReader = TopicEndpoint.manager.getUebTopicSource(topic);
1898       final boolean success = uebReader.offer(json);
1899       if (success)
1900         return Response.status(Status.OK)
1901             .entity(Arrays.asList(TopicEndpoint.manager.getUebTopicSource(topic).getRecentEvents()))
1902             .build();
1903       else
1904         return Response.status(Status.NOT_ACCEPTABLE)
1905             .entity(new Error("Failure to inject event over " + topic)).build();
1906     } catch (final IllegalArgumentException e) {
1907       logger.debug("{}: cannot offer for encoder ueb topic for {} because of {}", this, topic,
1908           e.getMessage(), e);
1909       return Response.status(Response.Status.NOT_FOUND).entity(new Error(topic + " not found"))
1910           .build();
1911     } catch (final IllegalStateException e) {
1912       logger.debug("{}: cannot offer for encoder ueb topic for {} because of {}", this, topic,
1913           e.getMessage(), e);
1914       return Response.status(Response.Status.NOT_ACCEPTABLE)
1915           .entity(new Error(topic + " not acceptable due to current state")).build();
1916     } catch (final Exception e) {
1917       logger.debug("{}: cannot offer for encoder ueb topic for {} because of {}", this, topic,
1918           e.getMessage(), e);
1919       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
1920           .entity(new Error(e.getMessage())).build();
1921     }
1922   }
1923
1924   @PUT
1925   @Path("engine/topics/sources/dmaap/{topic}/events")
1926   @Consumes(MediaType.TEXT_PLAIN)
1927   @ApiOperation(value = "Offers an event to a DMaaP topic for internal processing by the engine",
1928       notes = "The offered event is treated as it was incoming from the network",
1929       responseContainer = "List")
1930   @ApiResponses(value = {
1931       @ApiResponse(code = 404, message = "The topic information cannot be found"),
1932       @ApiResponse(code = 406,
1933           message = "The system is an administrative state that prevents "
1934               + "this request to be fulfilled"),
1935       @ApiResponse(code = 500, message = "A server error has occurred processing this request")})
1936   public Response dmaapOffer(
1937       @ApiParam(value = "Topic Name", required = true) @PathParam("topic") String topic,
1938       @ApiParam(value = "Network Message", required = true) String json) {
1939     try {
1940       final DmaapTopicSource dmaapReader = TopicEndpoint.manager.getDmaapTopicSource(topic);
1941       final boolean success = dmaapReader.offer(json);
1942       if (success)
1943         return Response.status(Status.OK)
1944             .entity(
1945                 Arrays.asList(TopicEndpoint.manager.getDmaapTopicSource(topic).getRecentEvents()))
1946             .build();
1947       else
1948         return Response.status(Status.NOT_ACCEPTABLE)
1949             .entity(new Error("Failure to inject event over " + topic)).build();
1950     } catch (final IllegalArgumentException e) {
1951       logger.debug("{}: cannot offer for encoder dmaap topic for {} because of {}", this, topic,
1952           e.getMessage(), e);
1953       return Response.status(Response.Status.NOT_FOUND).entity(new Error(topic + " not found"))
1954           .build();
1955     } catch (final IllegalStateException e) {
1956       logger.debug("{}: cannot offer for encoder dmaap topic for {} because of {}", this, topic,
1957           e.getMessage(), e);
1958       return Response.status(Response.Status.NOT_ACCEPTABLE)
1959           .entity(new Error(topic + " not acceptable due to current state")).build();
1960     } catch (final Exception e) {
1961       logger.debug("{}: cannot offer for encoder dmaap topic for {} because of {}", this, topic,
1962           e.getMessage(), e);
1963       return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
1964           .entity(new Error(e.getMessage())).build();
1965     }
1966   }
1967
1968   @GET
1969   @Path("engine/tools/uuid")
1970   @ApiOperation(value = "Produces an UUID", notes = "UUID generation utility")
1971   @Produces(MediaType.TEXT_PLAIN)
1972   public Response uuid() {
1973     return Response.status(Status.OK).entity(UUID.randomUUID().toString()).build();
1974   }
1975
1976   @GET
1977   @Path("engine/tools/loggers")
1978   @ApiOperation(value = "all active loggers", responseContainer = "List")
1979   @ApiResponses(value = {@ApiResponse(code = 500, message = "logging misconfiguration")})
1980   public Response loggers() {
1981     final List<String> names = new ArrayList<String>();
1982     if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) {
1983       logger.warn("The SLF4J logger factory is not configured for logback");
1984       return Response.status(Status.INTERNAL_SERVER_ERROR).entity(names).build();
1985     }
1986
1987     final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
1988     for (final Logger logger : context.getLoggerList()) {
1989       names.add(logger.getName());
1990     }
1991
1992     return Response.status(Status.OK).entity(names).build();
1993   }
1994
1995   @GET
1996   @Path("engine/tools/loggers/{logger}")
1997   @Produces(MediaType.TEXT_PLAIN)
1998   @ApiOperation(value = "logging level of a logger")
1999   @ApiResponses(value = {@ApiResponse(code = 500, message = "logging misconfiguration"),
2000       @ApiResponse(code = 404, message = "logger not found")})
2001   public Response loggerName(
2002       @ApiParam(value = "Logger Name", required = true) @PathParam("logger") String loggerName) {
2003     if (!(LoggerFactory.getILoggerFactory() instanceof LoggerContext)) {
2004       logger.warn("The SLF4J logger factory is not configured for logback");
2005       return Response.status(Status.INTERNAL_SERVER_ERROR).build();
2006     }
2007
2008     final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
2009     final ch.qos.logback.classic.Logger logger = context.getLogger(loggerName);
2010     if (logger == null) {
2011       return Response.status(Status.NOT_FOUND).build();
2012     }
2013
2014     final String loggerLevel = (logger.getLevel() != null) ? logger.getLevel().toString() : "";
2015     return Response.status(Status.OK).entity(loggerLevel).build();
2016   }
2017
2018   @PUT
2019   @Path("engine/tools/loggers/{logger}/{level}")
2020   @Produces(MediaType.TEXT_PLAIN)
2021   @Consumes(MediaType.TEXT_PLAIN)
2022   @ApiOperation(value = "sets the logger level", notes = "Please use the SLF4J logger levels")
2023   @ApiResponses(value = {@ApiResponse(code = 500, message = "logging misconfiguration"),
2024       @ApiResponse(code = 404, message = "logger not found")})
2025   public Response loggerName(
2026       @ApiParam(value = "Logger Name", required = true) @PathParam("logger") String loggerName,
2027       @ApiParam(value = "Logger Level", required = true) @PathParam("level") String loggerLevel) {
2028
2029     String newLevel;
2030     try {
2031       newLevel = LoggerUtil.setLevel(loggerName, loggerLevel);
2032     } catch (final IllegalArgumentException e) {
2033       logger.warn("{}: no logger {}", this, loggerName, loggerLevel, e);
2034       return Response.status(Status.NOT_FOUND).build();
2035     } catch (final IllegalStateException e) {
2036       logger.warn("{}: logging framework unavailable for {} / {}", this, loggerName, loggerLevel,
2037           e);
2038       return Response.status(Status.INTERNAL_SERVER_ERROR).build();
2039     }
2040
2041     return Response.status(Status.OK).entity(newLevel
2042
2043     ).build();
2044   }
2045
2046   /**
2047    * gets the underlying drools controller from the named policy controller
2048    *
2049    * @param controllerName the policy controller name
2050    * @return the underlying drools controller
2051    * @throws IllegalArgumentException if an invalid controller name has been passed in
2052    */
2053   protected DroolsController getDroolsController(String controllerName) {
2054     final PolicyController controller = PolicyController.factory.get(controllerName);
2055     if (controller == null)
2056       throw new IllegalArgumentException(controllerName + "  does not exist");
2057
2058     final DroolsController drools = controller.getDrools();
2059     if (drools == null)
2060       throw new IllegalArgumentException(controllerName + "  has no drools configuration");
2061
2062     return drools;
2063   }
2064
2065   /*
2066    * Helper classes for aggregation of results
2067    */
2068
2069   @Override
2070   public String toString() {
2071     final StringBuilder builder = new StringBuilder();
2072     builder.append("rest-telemetry-api []");
2073     return builder.toString();
2074   }
2075
2076   /**
2077    * Coding/Encoding Results Aggregation Helper class
2078    */
2079   public static class CodingResult {
2080     /**
2081      * serialized output
2082      */
2083
2084     public String jsonEncoding;
2085     /**
2086      * encoding result
2087      */
2088
2089     public Boolean encoding;
2090
2091     /**
2092      * decoding result
2093      */
2094     public Boolean decoding;
2095   }
2096
2097   /**
2098    * Generic Error Reporting class
2099    */
2100   public static class Error {
2101     public String error;
2102
2103     public Error(String error) {
2104       this.error = error;
2105     }
2106   }
2107
2108   /**
2109    * Feed Ports into Resources
2110    */
2111   public enum Inputs {
2112     configuration,
2113   }
2114
2115   /**
2116    * Resource Toggles
2117    */
2118   public enum Switches {
2119     activation, lock,
2120   }
2121 }
2122