Change Management Schedule Optimization 25/67925/1
authorRamaPrasad Amaranarayana (ra5425) <ra5425@att.com>
Wed, 19 Sep 2018 22:34:31 +0000 (18:34 -0400)
committerRamaPrasad Amaranarayana (ra5425) <ra5425@att.com>
Wed, 19 Sep 2018 22:38:15 +0000 (18:38 -0400)
Adding CMSO Service Common Utilities and Table Model Dao Files for Change Management Schedule Optimization

Change-Id: I18ee4e1d37b3b5d2284cfda4971b3066c52684c2
Issue-ID: OPTFRA-353
Signed-off-by: RamaPrasad Amaranarayana (ra5425) <ra5425@att.com>
13 files changed:
cmso-service/src/main/java/org/onap/optf/cmso/common/ApprovalStatusEnum.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/ApprovalTypesEnum.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/BasicAuthenticatorFilter.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/CMSRequestError.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/CMSStatusEnum.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/CmHelpers.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/DomainsEnum.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/LogMessages.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/Mdc.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/PropertiesManagement.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSAlreadyExistsException.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSException.java [new file with mode: 0644]
cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSNotFoundException.java [new file with mode: 0644]

diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/ApprovalStatusEnum.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/ApprovalStatusEnum.java
new file mode 100644 (file)
index 0000000..0069f26
--- /dev/null
@@ -0,0 +1,47 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+public enum ApprovalStatusEnum {\r
+    Accepted("Accepted"), Rejected("Rejected"),;\r
+\r
+    private final String text;\r
+\r
+    private ApprovalStatusEnum(String text) {\r
+        this.text = text;\r
+    }\r
+\r
+    public String toString() {\r
+        return text;\r
+    }\r
+\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/ApprovalTypesEnum.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/ApprovalTypesEnum.java
new file mode 100644 (file)
index 0000000..927dbf1
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+public enum ApprovalTypesEnum {\r
+    Tier2("Tier 2"),;\r
+\r
+    private final String text;\r
+\r
+    private ApprovalTypesEnum(String text) {\r
+        this.text = text;\r
+    }\r
+\r
+    public String toString() {\r
+        return text;\r
+    }\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/BasicAuthenticatorFilter.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/BasicAuthenticatorFilter.java
new file mode 100644 (file)
index 0000000..25b6583
--- /dev/null
@@ -0,0 +1,95 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+import java.io.IOException;\r
+import java.io.UnsupportedEncodingException;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.ws.rs.client.ClientRequestContext;\r
+import javax.ws.rs.client.ClientRequestFilter;\r
+import javax.ws.rs.core.MultivaluedMap;\r
+import javax.xml.bind.DatatypeConverter;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+\r
+public class BasicAuthenticatorFilter implements ClientRequestFilter {\r
+    private static EELFLogger log = EELFManager.getInstance().getLogger(BasicAuthenticatorFilter.class);\r
+    private final String user;\r
+    private final String password;\r
+\r
+    public BasicAuthenticatorFilter(String user, String password) {\r
+        this.user = user;\r
+        this.password = password;\r
+        log.info("user: " + user + " pass:" + password);\r
+    }\r
+\r
+    @Override\r
+    public void filter(ClientRequestContext requestContext) throws IOException {\r
+        MultivaluedMap<String, Object> headers = requestContext.getHeaders();\r
+        final String basicAuthentication = getBasicAuthentication();\r
+        headers.add("Authorization", basicAuthentication);\r
+    }\r
+\r
+    private String getBasicAuthentication() {\r
+        String token = this.user + ":" + this.password;\r
+        try {\r
+            return "Basic " + DatatypeConverter.printBase64Binary(token.getBytes("UTF-8"));\r
+        } catch (UnsupportedEncodingException ex) {\r
+            throw new IllegalStateException("Cannot encode with UTF-8", ex);\r
+        }\r
+    }\r
+    \r
+    public static String getUser(HttpServletRequest request) {\r
+        String user = "";\r
+        String header = request.getHeader("Authorization");\r
+        if (header != null) {\r
+            String[] auth = header.split("Basic ");\r
+            if (auth.length == 2) {\r
+                String token = getToken(auth[1]);\r
+                if (token.contains(":")) {\r
+                    String[] tokens = token.split(":");\r
+                    user = tokens[0];\r
+                }\r
+            }\r
+        }\r
+        return user;\r
+    }\r
+\r
+    private static String getToken(String auth) {\r
+        try {\r
+            String token = new String(DatatypeConverter.parseBase64Binary(auth));\r
+            return token;\r
+        } catch (Exception e) {\r
+            return auth;\r
+        }\r
+    }\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/CMSRequestError.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/CMSRequestError.java
new file mode 100644 (file)
index 0000000..161fe9b
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+import com.fasterxml.jackson.annotation.JsonProperty;\r
+\r
+public class CMSRequestError implements Serializable {\r
+    private static final long serialVersionUID = 1L;\r
+    private static EELFLogger log = EELFManager.getInstance().getLogger(CMSRequestError.class);\r
+    @JsonProperty\r
+    RequestError requestError;\r
+\r
+    public CMSRequestError(String messageId, String text, List<String> variables) {\r
+        requestError = new RequestError(messageId, text, variables);\r
+    }\r
+\r
+    public CMSRequestError(String messageId, String text) {\r
+        requestError = new RequestError(messageId, text, new ArrayList<String>());\r
+    }\r
+\r
+    public class RequestError {\r
+        @JsonProperty\r
+        private String messageId;\r
+        @JsonProperty\r
+        private String text;\r
+        @JsonProperty\r
+        private List<String> variables;\r
+\r
+        private RequestError(String messageId, String text, List<String> variables) {\r
+            this.messageId = "Scheduler." + messageId;\r
+            this.text = text;\r
+            this.variables = variables;\r
+        }\r
+\r
+        public String toString() {\r
+            StringBuffer sb = new StringBuffer();\r
+            sb.append(messageId).append(":").append(text).append(":").append(variables);\r
+            return sb.toString();\r
+\r
+        }\r
+    }\r
+\r
+    public String toString() {\r
+        return requestError.toString();\r
+    }\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/CMSStatusEnum.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/CMSStatusEnum.java
new file mode 100644 (file)
index 0000000..de1e701
--- /dev/null
@@ -0,0 +1,102 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+public enum CMSStatusEnum {\r
+    PendingSchedule("Pending Schedule",\r
+            "Schedule request as been accepted. Pending determination of recommended schedule."), SchedulingFailed(\r
+                    "Scheduling Failed", "Failed to determine recommended schedule."), ScheduleFailed("Schedule Failed",\r
+                            "Determination of recommended schedule failed."), OptimizationInProgress(\r
+                                    "Optimization In Progress",\r
+                                    "Determination of recommended schedule is in progress."), PendingApproval(\r
+                                            "Pending Approval",\r
+                                            "Pending approval of the recommended schedule."), OptimizationFailed(\r
+                                                    "Optimization Failed",\r
+                                                    "Unable to determine recommended schedule."), Accepted("Accepted",\r
+                                                            "Recommended schedule has been accepted."), Scheduled(\r
+                                                                    "Scheduled",\r
+                                                                    "All approvals received. Recommended schedule is pending execution."), ScheduledImmediate(\r
+                                                                            "Scheduled Immediate",\r
+                                                                            "All approvals received. Event is scheduled for immediate execution."), Triggered(\r
+                                                                                    "Triggered",\r
+                                                                                    "Scheduled event has been triggered."), ApprovalRejected(\r
+                                                                                            "Approval Rejected",\r
+                                                                                            "Recommended schedule has been rejected."), PastDue(\r
+                                                                                                    "Past due",\r
+                                                                                                    "Scheduled event time has passed. Queued event was not dispatched."), Error(\r
+                                                                                                            "Error",\r
+                                                                                                            "Attempt to displatch event failed."), Failed(\r
+                                                                                                                    "Failed",\r
+                                                                                                                    "Triggered event reported a failure."), Rejected(\r
+                                                                                                                            "Rejected",\r
+                                                                                                                            "Recommended schedule has been rejected."), NotificationsInitiated(\r
+                                                                                                                                    "Notifications Initiated",\r
+                                                                                                                                    "Notifications of scheduled events has been initiated."), Completed(\r
+                                                                                                                                            "Completed",\r
+                                                                                                                                            "Notification of all scheduled events have been sent."), CompletedWithError(\r
+                                                                                                                                                    "Completed with error(s)",\r
+                                                                                                                                                    "All scheduled events have completed, some with errors."), Deleted(\r
+                                                                                                                                                            "Deleted",\r
+                                                                                                                                                            "Schedule deleted prior to acceptance or after execution."), Cancelled(\r
+                                                                                                                                                                    "Cancelled",\r
+                                                                                                                                                                    "Scheduled event cancelled before execution."),;\r
+\r
+    private final String text;\r
+    private final String description;\r
+\r
+    private CMSStatusEnum(String text, String description) {\r
+        this.text = text;\r
+        this.description = description;\r
+    }\r
+\r
+    public String toString() {\r
+        return text;\r
+    }\r
+\r
+    public CMSStatusEnum fromString(String text) {\r
+        for (CMSStatusEnum e : CMSStatusEnum.values())\r
+            if (e.text.equals(text))\r
+                return e;\r
+        return null;\r
+    }\r
+\r
+    // To include in the AID.\r
+    public static void main(String argv[]) {\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("<html><body><table border=\"1\">\n");\r
+        for (CMSStatusEnum v : CMSStatusEnum.values())\r
+            sb.append("<tr><td>").append(v.text).append("</td><td>").append(v.description).append("</td></tr>\n");\r
+        sb.append("</table></body></html>\n");\r
+        System.out.println(sb.toString());\r
+    }\r
+\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/CmHelpers.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/CmHelpers.java
new file mode 100644 (file)
index 0000000..832acb7
--- /dev/null
@@ -0,0 +1,59 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+import java.util.List;\r
+import org.onap.optf.cmso.model.DomainData;\r
+import org.onap.optf.cmso.model.Schedule;\r
+import org.onap.optf.cmso.service.rs.models.CmDomainDataEnum;\r
+\r
+/**\r
+ * Collection of commann static helper methods for CHangeManagement\r
+ * \r
+ * @author jf9860\r
+ *\r
+ */\r
+public class CmHelpers {\r
+\r
+    public static String getDomainData(Schedule schedule, CmDomainDataEnum key) {\r
+        return getDomainData(schedule.getDomainData(), key);\r
+    }\r
+\r
+    public static String getDomainData(List<DomainData> domainData, CmDomainDataEnum key) {\r
+        for (DomainData map : domainData) {\r
+            if (map.getName().equals(key.toString()))\r
+                return map.getValue();\r
+        }\r
+        return null;\r
+    }\r
+\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/DomainsEnum.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/DomainsEnum.java
new file mode 100644 (file)
index 0000000..cd6af4c
--- /dev/null
@@ -0,0 +1,36 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+public enum DomainsEnum {\r
+    ChangeManagement,\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/LogMessages.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/LogMessages.java
new file mode 100644 (file)
index 0000000..6026bc4
--- /dev/null
@@ -0,0 +1,151 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+import java.io.IOException;\r
+import java.nio.file.Files;\r
+import java.nio.file.Paths;\r
+import com.att.eelf.configuration.EELFManager;\r
+import com.att.eelf.i18n.EELFResolvableErrorEnum;\r
+import com.att.eelf.i18n.EELFResourceManager;\r
+\r
+public enum LogMessages implements EELFResolvableErrorEnum {\r
+\r
+    // Let developer provide the initial properties here.\r
+    // We can merge them to logmessages.properties when we need to.\r
+    SEARCH_SCHEDULE_REQUEST_DETAILS("Search Schedule Request Details {0} from {1}: {2}"), SEARCH_SCHEDULE_REQUEST(\r
+            "Search Schedule Request {0} from {1}: {2} : {3}"), CREATE_SCHEDULE_REQUEST(\r
+                    "Create Schedule Request {0} from {1}: {2} : {3}"), DELETE_SCHEDULE_REQUEST(\r
+                            "Delete Schedule Request {0} from {1}: {2} : {3}"), GET_SCHEDULE_REQUEST_INFO(\r
+                                    "Get Schedule Request Info {0} from {1}: {2} : {3}"), PROCESS_OPTIMIZER_CALLBACK(\r
+                                            "Change management optimizer callback {0} from {1}: {2} "), APPROVE_SCHEDULE_REQUEST(\r
+                                                    "Approve Schedule Request {0} from {1}: {2} : {3}"), SCHEDULE_ALREADY_EXISTS(\r
+                                                            "Schedule already exists domain={0} schedule id={1}"), SCHEDULE_NOT_FOUND(\r
+                                                                    "Schedule not found domain={0} schedule id={1}"), INVALID_ATTRIBUTE(\r
+                                                                            "Invalid attribute {0}={1}"), MISSING_REQUIRED_ATTRIBUTE(\r
+                                                                                    "Missing required attribute '{0}'"), INVALID_REQUEST(\r
+                                                                                            "The input data structure is incorrect"), REQUEST_TIMED_OUT(\r
+                                                                                                    "Request timed out."), UNEXPECTED_EXCEPTION(\r
+                                                                                                            "Unexpected exception encountered during processing. Please contact support : {0}"), AUTHORIZATION_FAILED(\r
+                                                                                                                    "Authorization Failed"), UNDEFINED_DOMAIN_DATA_ATTRIBUTE(\r
+                                                                                                                            "Domain data attribute not defined domain={0} name={1} value={2}"), UNDEFINED_FILTER_ATTRIBUTE(\r
+                                                                                                                                    "Undefined filter attribute {0}"), INVALID_DATE_FILTER(\r
+                                                                                                                                            "Invalid date filter provided {0}=(1}"), OPTIMIZER_QUARTZ_JOB(\r
+                                                                                                                                                    "Quartz scheduling of OptimizerQuartzJob: {0}"), OPTIMIZER_EXCEPTION(\r
+                                                                                                                                                            "Exception making client call to optimizer {0}"), OPTIMIZER_CALLBACK_STATE_ERROR(\r
+                                                                                                                                                                    "Optimizer callback on schedule in invalid state. Should be {0} but was {1}."), CHANGE_MANAGEMENT_GROUP_NOT_FOUND(\r
+                                                                                                                                                                            "ChangeManagementGroup not found on optimizer callback scheduleId={0} groupId={1}"), UNABLE_TO_ALLOCATE_VNF_TIMESLOTS(\r
+                                                                                                                                                                                    "Unable to allocate VNF timeslots with Optimizer results startTime={0}, latestStartTime={1}, totalDuration={2}, concurrency={3} nvfs={4}"), UNABLE_TO_LOCATE_SCHEDULE_DETAIL(\r
+                                                                                                                                                                                            "Unable to locate ChangeManagementSchedule for VNF. scheduleId={0}, groupId={1}, vnfName={2}"), CM_JOB(\r
+                                                                                                                                                                                                    "Quartz scheduling of CmJob: {0}"), CM_QUARTZ_JOB(\r
+                                                                                                                                                                                                            "Quartz scheduling of CmQuartzJob: {0}"), NOT_PENDING_APPROVAL(\r
+                                                                                                                                                                                                                    "Approval request received for schedule that is not in Pending Approval state: domain={0} scheduleId={1} state={3}"), SCHEDULE_PAST_DUE(\r
+                                                                                                                                                                                                                            "Attempt to dispatch an event that is Past due scheduleId={0}, vnf={1}, now={2}, startTime={3}"), MSO_POLLING_MISSING_SCHEDULE(\r
+                                                                                                                                                                                                                                    "Attempt to poll MSO for request id {1} for missing ChangeManagementSchedule id={0}"), MSO_STATUS_JOB(\r
+                                                                                                                                                                                                                                            "Polling MSO {0} for requestId={1} for id={2}"), UNEXPECTED_RESPONSE(\r
+                                                                                                                                                                                                                                                    "Unexpected response from {0} HTTP Status={1} : {2}"), SCHEDULE_STATUS_JOB(\r
+                                                                                                                                                                                                                                                            "Quartz scheduling of ScheduleStatusJob: {0}"), CM_TICKET_NOT_APPROVED(\r
+                                                                                                                                                                                                                                                                    "Attempt to dispatch a change management event that has no TM Ticket approved. scheduleId={0} VNF Name={1} TM ChangeId={2} Status={3} Approval Status={4}"), MULTIPLE_GROUPS_NOT_SUPPORTED(\r
+                                                                                                                                                                                                                                                                            "Multiple groups not supported on immediate requests"), TM_CREATE_CHANGE_RECORD(\r
+                                                                                                                                                                                                                                                                                    "TM Create Change Record:{0} : Schedule ID: {1}"), TM_LIST(\r
+                                                                                                                                                                                                                                                                                            "TM list:{0} : URL : {1}"), TM_API(\r
+                                                                                                                                                                                                                                                                                                    "TM API Call: URL : {0}"), UNABLE_TO_CREATE_CHANGE_TICKET(\r
+                                                                                                                                                                                                                                                                                                            "Unable to create change ticket in TM: Schedule ID: {0} : Reason : {1}"), TM_UPDATE_CHECKLIST(\r
+                                                                                                                                                                                                                                                                                                                    "TM Fetch Checklist:{0} : Schedule ID: {1} : Change Id : {2} : URL : {3}"), OPTIMIZER_REQUEST(\r
+                                                                                                                                                                                                                                                                                                                            "Optimi Request:{0} : Schedule ID: {1} : URL : {2}"), TM_CLOSE_CHANGE_RECORD(\r
+                                                                                                                                                                                                                                                                                                                                    "TM Close Change Record:{0} : Schedule ID: {1} : Change Id : {2}"), UNABLE_TO_CLOSE_CHANGE_TICKET(\r
+                                                                                                                                                                                                                                                                                                                                            "Unable to close change ticket in TM:  Schedule ID: {0} : changeid: {1} :  Reason: {2}"), CANNOT_CANCEL_IN_PROGRESS(\r
+                                                                                                                                                                                                                                                                                                                                                    "Cannot delete/cancel a schedule with events in progress."), UNABLE_TO_PARSE_SCHEDULING_INFO(\r
+                                                                                                                                                                                                                                                                                                                                                            "Cannot parse scheduling info."), UNABLE_TO_LOCATE_CHANGE_RECORD(\r
+                                                                                                                                                                                                                                                                                                                                                                    "Unable to locate TM change record {2} to check status before displacth of {1} for schedulId={0}"), INVALID_CHANGE_WINDOW(\r
+                                                                                                                                                                                                                                                                                                                                                                            "Change window end time {1} must be after start time {0}"), NODE_LIST_CONTAINS_EMTPY_NODE(\r
+                                                                                                                                                                                                                                                                                                                                                                                    "vnfDetails node list contains at least one empty node."), SO_API(\r
+                                                                                                                                                                                                                                                                                                                                                                                            "SO Poll Request {0}"), EXPECTED_EXCEPTION(\r
+                                                                                                                                                                                                                                                                                                                                                                                                    "Expected exception encountered during processing. Make Sonar happy: {0}"), TM_UPDATE_CHANGE_RECORD(\r
+                                                                                                                                                                                                                                                                                                                                                                                                            "TM Update Change Record:{0} : Schedule ID: {1} : Change Id : {2} : URL : {3}"), UNABLE_TO_UPDATE_CHANGE_TICKET(\r
+                                                                                                                                                                                                                                                                                                                                                                                                                    "Unable to update change ticket in TM: Schedule ID: {0} : changeid: {1} :  Reason: {2}"),;\r
+\r
+    private final String defaultId;\r
+    private final String defaultMessage;\r
+    private final String defaultResolution;\r
+    private final String defaultAction;\r
+\r
+    private LogMessages(String message) {\r
+        defaultMessage = message;\r
+        this.defaultId = this.name();\r
+        this.defaultResolution = "No resolution needed";\r
+        this.defaultAction = "No action is required";\r
+    }\r
+\r
+    private LogMessages(String message, String id, String resolution, String action) {\r
+        defaultMessage = message;\r
+        this.defaultId = id;\r
+        this.defaultResolution = resolution;\r
+        this.defaultAction = action;\r
+    }\r
+\r
+    static {\r
+        EELFResourceManager.loadMessageBundle("logmessages");\r
+    }\r
+\r
+    public String genProperties() {\r
+        // Use this to regenerate properties file. The desire to change messages without\r
+        // updating code is\r
+        // well understood, but the developer should be able to code the defaults\r
+        // without having to update 2 different files and\r
+        // get it wrong.\r
+        StringBuilder sb = new StringBuilder();\r
+        sb.append("# Generated from ").append(this.getClass().getName()).append("\n");\r
+        for (LogMessages lm : values()) {\r
+            sb.append(lm.name());\r
+            sb.append(" ").append(lm.defaultId);\r
+            sb.append("|").append(lm.defaultMessage);\r
+            sb.append("|").append(lm.defaultResolution);\r
+            sb.append("|").append(lm.defaultAction);\r
+            sb.append("\n");\r
+        }\r
+        return sb.toString();\r
+    }\r
+\r
+    public static void main(String argv[]) {\r
+        System.out.println(LogMessages.CREATE_SCHEDULE_REQUEST.genProperties());\r
+        try {\r
+            Files.write(Paths.get("src/main/resources/logmessages.properties"),\r
+                    LogMessages.CREATE_SCHEDULE_REQUEST.genProperties().getBytes());\r
+        } catch (IOException e) {\r
+            EELFManager.getInstance().getDebugLogger().debug("Failed to update properties file.", e);\r
+\r
+        }\r
+\r
+    }\r
+\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/Mdc.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/Mdc.java
new file mode 100644 (file)
index 0000000..30451b5
--- /dev/null
@@ -0,0 +1,382 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+import static com.att.eelf.configuration.Configuration.MDC_BEGIN_TIMESTAMP;\r
+import static com.att.eelf.configuration.Configuration.MDC_ELAPSED_TIME;\r
+import static com.att.eelf.configuration.Configuration.MDC_END_TIMESTAMP;\r
+import static com.att.eelf.configuration.Configuration.MDC_INSTANCE_UUID;\r
+import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;\r
+import static com.att.eelf.configuration.Configuration.MDC_PARTNER_NAME;\r
+import static com.att.eelf.configuration.Configuration.MDC_REMOTE_HOST;\r
+import static com.att.eelf.configuration.Configuration.MDC_RESPONSE_CODE;\r
+import static com.att.eelf.configuration.Configuration.MDC_RESPONSE_DESC;\r
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;\r
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;\r
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_INSTANCE_ID;\r
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;\r
+import static com.att.eelf.configuration.Configuration.MDC_STATUS_CODE;\r
+import static com.att.eelf.configuration.Configuration.MDC_TARGET_ENTITY;\r
+import static com.att.eelf.configuration.Configuration.MDC_TARGET_SERVICE_NAME;\r
+import java.net.InetAddress;\r
+import java.net.URI;\r
+import java.util.Date;\r
+import java.util.Map;\r
+import java.util.UUID;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.ws.rs.core.Response;\r
+import org.onap.optf.cmso.filters.MessageHeaders;\r
+import org.quartz.JobExecutionContext;\r
+import org.slf4j.MDC;\r
+import com.att.eelf.utils.Stopwatch;\r
+\r
+/**\r
+ * ECOMP EELF logging MDC fields not defined in the MDC Configuration (i.e.\r
+ * MDC_ALERT_SEVERITY)\r
+ **/\r
+public class Mdc {\r
+    public enum Enum {\r
+        // BeginTimestamp,\r
+        // EndTimeStamp,\r
+        // RequestId,\r
+        // ServiceInstanceId,\r
+        VirtualServerName,\r
+        // ServiceName,\r
+        // PartnerName,\r
+        // StatusCOde,\r
+        // ResponseCode,\r
+        // ResponseDescription,\r
+        // InstanceUUID,\r
+        // AlertSeverity,\r
+        // ServerIPAddress,\r
+        // ElapsedTime,\r
+        // ServerFQDN,\r
+        // RemoteHost,\r
+        ClassName, Unused,\r
+        // ProcessKey,\r
+        CustomField1, CustomField2, CustomField3, CustomField4,\r
+        // TargetVirtualEntity,\r
+        // TargetEntity,\r
+        // TargetServiceName,\r
+        ErrorCode, ErrorDescription, Timer,\r
+    }\r
+\r
+    public static void begin(HttpServletRequest request, String requestId) {\r
+        MDC.clear();\r
+        Stopwatch.start();\r
+        // MDC.put(MDC_ALERT_SEVERITY, "");\r
+        MDC.put(MDC_BEGIN_TIMESTAMP, Stopwatch.isoFormatter.format(new Date()));\r
+        // MDC.put(MDC_ELAPSED_TIME, String.valueOf(Stopwatch.getDuration()));\r
+        // MDC.put(MDC_END_TIMESTAMP, "");\r
+        MDC.put(MDC_INSTANCE_UUID, UUID.randomUUID().toString());\r
+        // MDC.put(MDC_KEY_REQUEST_ID, requestId);\r
+        setRequestId(request, requestId);\r
+        // MDC.put(MDC_PROCESS_KEY, "");\r
+        MDC.put(MDC_REMOTE_HOST, request.getRemoteHost());\r
+        // MDC.put(MDC_RESPONSE_CODE, "");\r
+        // MDC.put(MDC_RESPONSE_DESC, "");\r
+        // MDC.put(MDC_SERVICE_NAME, "");\r
+        try {\r
+            MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());\r
+        } catch (Exception e) {\r
+            MDC.put(MDC_SERVER_FQDN, e.getMessage());\r
+        }\r
+        try {\r
+            MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());\r
+        } catch (Exception e) {\r
+            MDC.put(MDC_SERVER_FQDN, e.getMessage());\r
+        }\r
+        MDC.put(MDC_SERVICE_INSTANCE_ID, "UNKNOWN");\r
+        MDC.put(MDC_SERVICE_NAME, "ecomp-cmso");\r
+        // MDC.put(MDC_STATUS_CODE, "");\r
+        setPartherTargetFromUri(request.getRequestURL().toString());\r
+        // Override partner hostname with username\r
+        MDC.put(MDC_PARTNER_NAME, BasicAuthenticatorFilter.getUser(request));\r
+        // MDC.put(MDC_TARGET_ENTITY, "");\r
+        // MDC.put(MDC_TARGET_SERVICE_NAME, "");\r
+        // MDC.put(MDC_TARGET_VIRTUAL_ENTITY, "");\r
+        MDC.put(Enum.ClassName.name(), getCaller(3));\r
+        // MDC.put(MdcEnum.CustomField1.name(), "");\r
+        // MDC.put(MdcEnum.CustomField2.name(), "");\r
+        // MDC.put(MdcEnum.CustomField3.name(), "");\r
+        // MDC.put(MdcEnum.CustomField4.name(), "");\r
+        // MDC.put(MdcEnum.ErrorCode.name(), "");\r
+        // MDC.put(MdcEnum.ErrorDescription.name(), "");\r
+        // MDC.put(MdcEnum.Timer.name(), "");\r
+        // MDC.put(MdcEnum.Unused.name(), "");\r
+        // MDC.put(MdcEnum.VirtualServerName.name(), "");\r
+\r
+    }\r
+\r
+    private static void setRequestId(HttpServletRequest request, String requestId) {\r
+\r
+        String transactionId = request.getHeader(MessageHeaders.HeadersEnum.TransactionID.toString());\r
+        if (transactionId == null) {\r
+            transactionId = requestId;\r
+        }\r
+        if (transactionId == null)\r
+            transactionId = "Unknown";\r
+        MDC.put(MDC_KEY_REQUEST_ID, transactionId);\r
+    }\r
+\r
+    public static void end(Response response) {\r
+        Stopwatch.stop();\r
+        // MDC.put(MDC_ALERT_SEVERITY, "");\r
+        // MDC.put(MDC_BEGIN_TIMESTAMP, Stopwatch.isoFormatter.format(new\r
+        // Date()));\r
+        MDC.put(MDC_ELAPSED_TIME, String.valueOf(Stopwatch.getDuration()));\r
+        MDC.put(MDC_END_TIMESTAMP, Stopwatch.isoFormatter.format(new Date()));\r
+        // MDC.put(MDC_INSTANCE_UUID, "");\r
+        // MDC.put(MDC_KEY_REQUEST_ID, "");\r
+        // MDC.put(MDC_PARTNER_NAME, "");\r
+        // MDC.put(MDC_PROCESS_KEY, "");\r
+        // MDC.put(MDC_REMOTE_HOST, "");\r
+        MDC.put(MDC_RESPONSE_CODE, String.valueOf(response.getStatus()));\r
+        MDC.put(MDC_RESPONSE_DESC, response.getStatusInfo().getReasonPhrase());\r
+        // MDC.put(MDC_SERVICE_NAME, "");\r
+        // MDC.put(MDC_SERVER_FQDN, "");\r
+        // MDC.put(MDC_SERVER_IP_ADDRESS, "");\r
+        // MDC.put(MDC_SERVICE_INSTANCE_ID, "");\r
+        // MDC.put(MDC_SERVICE_NAME, "");\r
+        MDC.put(MDC_STATUS_CODE, "COMPLETE");\r
+        if (response.getStatus() == 500)\r
+            MDC.put(MDC_STATUS_CODE, "ERROR");\r
+        // MDC.put(MDC_TARGET_ENTITY, "");\r
+        // MDC.put(MDC_TARGET_SERVICE_NAME, "");\r
+        // MDC.put(MDC_TARGET_VIRTUAL_ENTITY, "");\r
+        MDC.put(Enum.ClassName.name(), getCaller(3));\r
+        // MDC.put(MdcEnum.CustomField1.name(), "");\r
+        // MDC.put(MdcEnum.CustomField2.name(), "");\r
+        // MDC.put(MdcEnum.CustomField3.name(), "");\r
+        // MDC.put(MdcEnum.CustomField4.name(), "");\r
+        // MDC.put(MdcEnum.ErrorCode.name(), "");\r
+        // MDC.put(MdcEnum.ErrorDescription.name(), "");\r
+        // MDC.put(MdcEnum.Timer.name(), "");\r
+        // MDC.put(MdcEnum.Unused.name(), "");\r
+        // MDC.put(MdcEnum.VirtualServerName.name(), "");\r
+\r
+    }\r
+\r
+    public static String getCaller(int back) {\r
+        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();\r
+        return stackTraceElements[back].getClassName() + "." + stackTraceElements[back].getMethodName();\r
+    }\r
+\r
+    public static void quartzJobBegin(JobExecutionContext context) {\r
+        MDC.clear();\r
+        Stopwatch.start();\r
+        // MDC.put(MDC_ALERT_SEVERITY, "");\r
+        MDC.put(MDC_BEGIN_TIMESTAMP, Stopwatch.isoFormatter.format(new Date()));\r
+        // MDC.put(MDC_ELAPSED_TIME, String.valueOf(Stopwatch.getDuration()));\r
+        // MDC.put(MDC_END_TIMESTAMP, "");\r
+        MDC.put(MDC_INSTANCE_UUID, UUID.randomUUID().toString());\r
+        // MDC.put(MDC_KEY_REQUEST_ID);\r
+        // MDC.put(MDC_PARTNER_NAME, request.getRemoteUser());\r
+        // MDC.put(MDC_PROCESS_KEY, "");\r
+        // MDC.put(MDC_REMOTE_HOST, request.getRemoteHost());\r
+        // MDC.put(MDC_RESPONSE_CODE, "");\r
+        // MDC.put(MDC_RESPONSE_DESC, "");\r
+        // MDC.put(MDC_SERVICE_NAME, "");\r
+        try {\r
+            MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());\r
+        } catch (Exception e) {\r
+            MDC.put(MDC_SERVER_FQDN, e.getMessage());\r
+        }\r
+        try {\r
+            MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());\r
+        } catch (Exception e) {\r
+            MDC.put(MDC_SERVER_FQDN, e.getMessage());\r
+        }\r
+        MDC.put(MDC_SERVICE_INSTANCE_ID, "UNKNOWN");\r
+        MDC.put(MDC_SERVICE_NAME, "ecomp-cmso");\r
+        // MDC.put(MDC_STATUS_CODE, "");\r
+        // MDC.put(MDC_TARGET_ENTITY, "");\r
+        // MDC.put(MDC_TARGET_SERVICE_NAME, "");\r
+        // MDC.put(MDC_TARGET_VIRTUAL_ENTITY, "");\r
+        MDC.put(Enum.ClassName.name(), getCaller(3));\r
+        // MDC.put(MdcEnum.CustomField1.name(), "");\r
+        // MDC.put(MdcEnum.CustomField2.name(), "");\r
+        // MDC.put(MdcEnum.CustomField3.name(), "");\r
+        // MDC.put(MdcEnum.CustomField4.name(), "");\r
+        // MDC.put(MdcEnum.ErrorCode.name(), "");\r
+        // MDC.put(MdcEnum.ErrorDescription.name(), "");\r
+        // MDC.put(MdcEnum.Timer.name(), "");\r
+        // MDC.put(MdcEnum.Unused.name(), "");\r
+        // MDC.put(MdcEnum.VirtualServerName.name(), "");\r
+\r
+    }\r
+\r
+    public static void quartzJobEnd(JobExecutionContext context) {\r
+        Stopwatch.stop();\r
+        // MDC.put(MDC_ALERT_SEVERITY, "");\r
+        MDC.put(MDC_END_TIMESTAMP, Stopwatch.isoFormatter.format(new Date()));\r
+        MDC.put(MDC_ELAPSED_TIME, String.valueOf(Stopwatch.getDuration()));\r
+        // MDC.put(MDC_START_TIMESTAMP, "");\r
+        // MDC.put(MDC_INSTANCE_UUID, UUID.randomUUID().toString());\r
+        // MDC.put(MDC_KEY_REQUEST_ID);\r
+        // MDC.put(MDC_PARTNER_NAME, request.getRemoteUser());\r
+        // MDC.put(MDC_PROCESS_KEY, "");\r
+        // MDC.put(MDC_REMOTE_HOST, request.getRemoteHost());\r
+        // MDC.put(MDC_RESPONSE_CODE, "");\r
+        // MDC.put(MDC_RESPONSE_DESC, "");\r
+        // MDC.put(MDC_SERVICE_NAME, "");\r
+        // try{ MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName()); }\r
+        // catch (Exception e){ MDC.put(MDC_SERVER_FQDN, e.getMessage());}\r
+        // try{ MDC.put(MDC_SERVER_IP_ADDRESS,\r
+        // InetAddress.getLocalHost().getHostAddress()); } catch (Exception e){\r
+        // MDC.put(MDC_SERVER_FQDN, e.getMessage());}\r
+        // MDC.put(MDC_SERVICE_INSTANCE_ID, "UNKNOWN");\r
+        // MDC.put(MDC_SERVICE_NAME, "ecomp-cmso");\r
+        // MDC.put(MDC_STATUS_CODE, "");\r
+        // MDC.put(MDC_TARGET_ENTITY, "");\r
+        // MDC.put(MDC_TARGET_SERVICE_NAME, "");\r
+        // MDC.put(MDC_TARGET_VIRTUAL_ENTITY, "");\r
+        MDC.put(Enum.ClassName.name(), getCaller(3));\r
+        // MDC.put(MdcEnum.CustomField1.name(), "");\r
+        // MDC.put(MdcEnum.CustomField2.name(), "");\r
+        // MDC.put(MdcEnum.CustomField3.name(), "");\r
+        // MDC.put(MdcEnum.CustomField4.name(), "");\r
+        // MDC.put(MdcEnum.ErrorCode.name(), "");\r
+        // MDC.put(MdcEnum.ErrorDescription.name(), "");\r
+        // MDC.put(MdcEnum.Timer.name(), "");\r
+        // MDC.put(MdcEnum.Unused.name(), "");\r
+        // MDC.put(MdcEnum.VirtualServerName.name(), "");\r
+\r
+    }\r
+\r
+    public static Map<String, String> save() {\r
+        Map<String, String> save = MDC.getCopyOfContextMap();\r
+        return save;\r
+    }\r
+\r
+    public static void restore(Map<String, String> mdcSave) {\r
+        MDC.clear();\r
+        for (String name : mdcSave.keySet())\r
+            MDC.put(name, mdcSave.get(name));\r
+    }\r
+\r
+    public static void metricStart(String requestId, String url) {\r
+        MDC.put(MDC_BEGIN_TIMESTAMP, Stopwatch.isoFormatter.format(new Date()));\r
+        // MDC.put(MDC_ELAPSED_TIME, String.valueOf(Stopwatch.getDuration()));\r
+        // MDC.put(MDC_END_TIMESTAMP, "");\r
+        // MDC.put(MDC_INSTANCE_UUID, UUID.randomUUID().toString());\r
+        // MDC.put(MDC_KEY_REQUEST_ID, requestId);\r
+        // MDC.put(MDC_PARTNER_NAME, invocationBuilder.ge.getRemoteUser());\r
+        // MDC.put(MDC_PROCESS_KEY, "");\r
+        // MDC.put(MDC_REMOTE_HOST, request.getRemoteHost());\r
+        // MDC.put(MDC_RESPONSE_CODE, "");\r
+        // MDC.put(MDC_RESPONSE_DESC, "");\r
+        // MDC.put(MDC_SERVICE_NAME, "");\r
+        // try{ MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName()); }\r
+        // catch (Exception e){ MDC.put(MDC_SERVER_FQDN, e.getMessage());}\r
+        // try{ MDC.put(MDC_SERVER_IP_ADDRESS,\r
+        // InetAddress.getLocalHost().getHostAddress()); } catch (Exception e){\r
+        // MDC.put(MDC_SERVER_FQDN, e.getMessage());}\r
+        // MDC.put(MDC_SERVICE_INSTANCE_ID, "UNKNOWN");\r
+        // MDC.put(MDC_SERVICE_NAME, "ecomp-cmso");\r
+        // MDC.put(MDC_STATUS_CODE, "");\r
+        setPartherTargetFromUri(url);\r
+        // MDC.put(MDC_TARGET_ENTITY, "");\r
+        // MDC.put(MDC_TARGET_SERVICE_NAME, "");\r
+        // MDC.put(MDC_TARGET_VIRTUAL_ENTITY, "");\r
+        MDC.put(Enum.ClassName.name(), getCaller(3));\r
+        // MDC.put(MdcEnum.CustomField1.name(), "");\r
+        // MDC.put(MdcEnum.CustomField2.name(), "");\r
+        // MDC.put(MdcEnum.CustomField3.name(), "");\r
+        // MDC.put(MdcEnum.CustomField4.name(), "");\r
+        // MDC.put(MdcEnum.ErrorCode.name(), "");\r
+        // MDC.put(MdcEnum.ErrorDescription.name(), "");\r
+        // MDC.put(MdcEnum.Timer.name(), "");\r
+        // MDC.put(MdcEnum.Unused.name(), "");\r
+        // MDC.put(MdcEnum.VirtualServerName.name(), "");\r
+\r
+    }\r
+\r
+    public static void metricEnd(Response response) {\r
+\r
+        // MDC.put(MDC_BEGIN_TIMESTAMP, Stopwatch.isoFormatter.format(new Date()));\r
+        try {\r
+            Long then = Stopwatch.isoFormatter.parse(MDC.get(MDC_BEGIN_TIMESTAMP)).getTime();\r
+            Long now = System.currentTimeMillis();\r
+            MDC.put(MDC_ELAPSED_TIME, String.valueOf(now - then));\r
+        } catch (Exception e) {\r
+            MDC.put(MDC_ELAPSED_TIME, "");\r
+        }\r
+        MDC.put(MDC_END_TIMESTAMP, Stopwatch.isoFormatter.format(new Date()));\r
+\r
+        // MDC.put(MDC_INSTANCE_UUID, UUID.randomUUID().toString());\r
+        // MDC.put(MDC_KEY_REQUEST_ID, requestId);\r
+        // MDC.put(MDC_PARTNER_NAME, invocationBuilder.ge.getRemoteUser());\r
+        // MDC.put(MDC_PROCESS_KEY, "");\r
+        // MDC.put(MDC_REMOTE_HOST, response.getLocation().toString());\r
+        MDC.put(MDC_RESPONSE_CODE, String.valueOf(response.getStatus()));\r
+        MDC.put(MDC_RESPONSE_DESC, response.getStatusInfo().getReasonPhrase());\r
+        // MDC.put(MDC_SERVICE_NAME, "");\r
+        // try{ MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName()); }\r
+        // catch (Exception e){ MDC.put(MDC_SERVER_FQDN, e.getMessage());}\r
+        // try{ MDC.put(MDC_SERVER_IP_ADDRESS,\r
+        // InetAddress.getLocalHost().getHostAddress()); } catch (Exception e){\r
+        // MDC.put(MDC_SERVER_FQDN, e.getMessage());}\r
+        // MDC.put(MDC_SERVICE_INSTANCE_ID, "UNKNOWN");\r
+        // MDC.put(MDC_SERVICE_NAME, "ecomp-cmso");\r
+        MDC.put(MDC_STATUS_CODE, "COMPLETE");\r
+        if (response.getStatus() == 500)\r
+            MDC.put(MDC_STATUS_CODE, "ERROR");\r
+        // MDC.put(MDC_TARGET_ENTITY, "");\r
+        // MDC.put(MDC_TARGET_SERVICE_NAME, "");\r
+        // MDC.put(MDC_TARGET_VIRTUAL_ENTITY, "");\r
+        MDC.put(Enum.ClassName.name(), getCaller(3));\r
+        // MDC.put(MdcEnum.CustomField1.name(), "");\r
+        // MDC.put(MdcEnum.CustomField2.name(), "");\r
+        // MDC.put(MdcEnum.CustomField3.name(), "");\r
+        // MDC.put(MdcEnum.CustomField4.name(), "");\r
+        // MDC.put(MdcEnum.ErrorCode.name(), "");\r
+        // MDC.put(MdcEnum.ErrorDescription.name(), "");\r
+        // MDC.put(MdcEnum.Timer.name(), "");\r
+        // MDC.put(MdcEnum.Unused.name(), "");\r
+        // MDC.put(MdcEnum.VirtualServerName.name(), "");\r
+\r
+    }\r
+\r
+    private static void setPartherTargetFromUri(String url) {\r
+        try {\r
+            URI uri = new URI(url);\r
+            MDC.put(MDC_PARTNER_NAME, uri.getHost());\r
+            MDC.put(MDC_TARGET_ENTITY, uri.getScheme() + "://" + uri.getHost() + ":" + uri.getPort());\r
+            MDC.put(MDC_TARGET_SERVICE_NAME, uri.getPath());\r
+        } catch (Exception e) {\r
+            MDC.put(MDC_PARTNER_NAME, "UNKNOWN");\r
+            MDC.put(MDC_TARGET_ENTITY, "UNKNOWN");\r
+            MDC.put(MDC_TARGET_SERVICE_NAME, url);\r
+        }\r
+    }\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/PropertiesManagement.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/PropertiesManagement.java
new file mode 100644 (file)
index 0000000..4514a57
--- /dev/null
@@ -0,0 +1,130 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common;\r
+\r
+import java.io.UnsupportedEncodingException;\r
+import javax.crypto.Cipher;\r
+import javax.crypto.spec.IvParameterSpec;\r
+import javax.crypto.spec.SecretKeySpec;\r
+import javax.xml.bind.DatatypeConverter;\r
+import org.apache.commons.codec.binary.Base64;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.core.env.Environment;\r
+import org.springframework.stereotype.Component;\r
+import com.att.eelf.configuration.EELFLogger;\r
+import com.att.eelf.configuration.EELFManager;\r
+\r
+@Component\r
+public class PropertiesManagement {\r
+\r
+    private static EELFLogger debug = EELFManager.getInstance().getDebugLogger();\r
+    private static EELFLogger errors = EELFManager.getInstance().getErrorLogger();\r
+\r
+    private final static String algorithm = "AES";\r
+    private final static String cipherMode = "CBC";\r
+    private final static String paddingScheme = "PKCS5Padding";\r
+    private final static String transformation = algorithm + "/" + cipherMode + "/" + paddingScheme;\r
+\r
+    private static final String initVector = "ONAPCMSOVECTORIV"; // 16 bytes IV\r
+\r
+    @Autowired\r
+    Environment env;\r
+\r
+    public String getProperty(String key, String defaultValue) {\r
+        String value = env.getProperty(key, defaultValue);\r
+        value = getDecryptedValue(value);\r
+        return value;\r
+    }\r
+\r
+    public static String getDecryptedValue(String value) {\r
+        if (value.startsWith("enc:")) {\r
+            String secret = getSecret();\r
+            value = decrypt(secret, initVector, value.substring(4));\r
+        }\r
+        return value;\r
+    }\r
+\r
+    public static String getEncryptedValue(String value) {\r
+        String secret = getSecret();\r
+        value = encrypt(secret, initVector, value);\r
+        return value;\r
+    }\r
+\r
+    private static final String encrypt(String key, String initVector, String value) {\r
+        try {\r
+            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));\r
+            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");\r
+            Cipher cipher = Cipher.getInstance(transformation);\r
+            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);\r
+            byte[] encrypted = cipher.doFinal(value.getBytes());\r
+            return Base64.encodeBase64String(encrypted);\r
+        } catch (Exception ex) {\r
+            errors.error("Unexpected exception {0}", ex.getMessage());\r
+            debug.debug("Unexpected exception", ex);\r
+        }\r
+\r
+        return null;\r
+    }\r
+\r
+    private static final String decrypt(String key, String initVector, String encrypted) {\r
+        try {\r
+            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));\r
+            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");\r
+            Cipher cipher = Cipher.getInstance(transformation);\r
+            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);\r
+            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));\r
+            return new String(original);\r
+        } catch (Exception ex) {\r
+            errors.error("Unexpected exception {0}", ex.getMessage());\r
+            debug.debug("Unexpected exception", ex);\r
+        }\r
+        return null;\r
+    }\r
+\r
+    private static String getSecret() {\r
+        return "ONAPCMSOSECRETIV";\r
+    }\r
+\r
+    public static void main(String[] args) {\r
+        try {\r
+            String pass = getDecryptedValue("enc:bfodXf8qRfCqMvlxVBYNWQ==");\r
+            //System.out.println("Decrypt - "+pass);\r
+            pass = getEncryptedValue("cmso@onap.org");\r
+            //System.out.println("Encrypt - "+pass);\r
+            //System.out.println(DatatypeConverter.printBase64Binary("cmso@onap.org:cmso@onap.org".getBytes("UTF-8")));\r
+        } catch (Exception e) {\r
+            // TODO Auto-generated catch block\r
+            e.printStackTrace();\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSAlreadyExistsException.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSAlreadyExistsException.java
new file mode 100644 (file)
index 0000000..d461e4f
--- /dev/null
@@ -0,0 +1,43 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common.exceptions;\r
+\r
+import javax.ws.rs.core.Response.Status;\r
+import org.onap.optf.cmso.common.LogMessages;\r
+\r
+public class CMSAlreadyExistsException extends CMSException {\r
+    private static final long serialVersionUID = 1L;\r
+\r
+    public CMSAlreadyExistsException(String... args) {\r
+        super(Status.CONFLICT, LogMessages.SCHEDULE_ALREADY_EXISTS, args);\r
+    }\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSException.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSException.java
new file mode 100644 (file)
index 0000000..c49d02f
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common.exceptions;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import javax.ws.rs.core.Response.Status;\r
+import org.onap.optf.cmso.common.CMSRequestError;\r
+import org.onap.optf.cmso.common.LogMessages;\r
+import com.att.eelf.i18n.EELFResourceManager;\r
+\r
+public class CMSException extends Exception {\r
+    private static final long serialVersionUID = 1L;\r
+\r
+    protected CMSRequestError requestError = null;\r
+    private List<String> variables = new ArrayList<String>();\r
+    protected LogMessages messageCode;\r
+    protected Status status;\r
+\r
+    public CMSException(Status status, LogMessages messageCode, String... args) {\r
+        super(EELFResourceManager.format(messageCode, args));\r
+        this.status = status;\r
+        this.messageCode = messageCode;\r
+        for (String arg : args)\r
+            variables.add(arg);\r
+        requestError = new CMSRequestError(messageCode.name(), getMessage(), variables);\r
+    }\r
+\r
+    public Status getStatus() {\r
+        return status;\r
+    }\r
+\r
+    public LogMessages getMessageCode() {\r
+        return messageCode;\r
+    }\r
+\r
+    public String[] getVariables() {\r
+        return variables.toArray(new String[variables.size()]);\r
+    }\r
+\r
+    public CMSRequestError getRequestError() {\r
+        return requestError;\r
+    }\r
+}\r
diff --git a/cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSNotFoundException.java b/cmso-service/src/main/java/org/onap/optf/cmso/common/exceptions/CMSNotFoundException.java
new file mode 100644 (file)
index 0000000..2a46e21
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * Copyright © 2017-2018 AT&T Intellectual Property.\r
+ * Modifications Copyright © 2018 IBM.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * \r
+ * \r
+ * Unless otherwise specified, all documentation contained herein is licensed\r
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");\r
+ * you may not use this documentation except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *         https://creativecommons.org/licenses/by/4.0/\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, documentation\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+*/\r
+\r
+package org.onap.optf.cmso.common.exceptions;\r
+\r
+import javax.ws.rs.core.Response.Status;\r
+import org.onap.optf.cmso.common.LogMessages;\r
+\r
+public class CMSNotFoundException extends CMSException {\r
+    private static final long serialVersionUID = 1L;\r
+\r
+    public CMSNotFoundException(String... args) {\r
+        super(Status.NOT_FOUND, LogMessages.SCHEDULE_NOT_FOUND, args);\r
+    }\r
+\r
+}\r