diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/util/Utils.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/util/Utils.java index 29845990d7..369f357ddd 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/util/Utils.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.integration.client/src/main/java/org/wso2/carbon/apimgt/integration/client/util/Utils.java @@ -235,4 +235,4 @@ public class Utils { throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { return loadKeyStore(trustStorePath,tsPassword,TRUST_STORE_TYPE); } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java index e65ebe2fa4..88b662e1b2 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java @@ -286,4 +286,4 @@ public class DeviceManagementDataHolder { public void setDeviceInformationManager(DeviceInformationManager deviceInformationManager) { this.deviceInformationManager = deviceInformationManager; } -} \ No newline at end of file +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/pom.xml b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/pom.xml new file mode 100644 index 0000000000..c95d8f2d6f --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/pom.xml @@ -0,0 +1,180 @@ + + + + + + + org.wso2.carbon.devicemgt + task-allocation + 4.1.11-SNAPSHOT + ../pom.xml + + + 4.0.0 + io.entgra.dynamic.task.allocation.framework + bundle + Entgra - Task Allocation Framework + Entgra - Framework for partitioning tasks evenly amongst multiple nodes + http://entgra.io + + + + + org.apache.felix + maven-scr-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + ${carbon.device.mgt.version} + Entgra - Task Allocation Framework Bundle + io.entgra.dynamic.task.allocation.framework.internal + + org.apache.axis2.*;version="${axis2.osgi.version.range}", + org.apache.axiom.*; version="${axiom.osgi.version.range}", + org.osgi.framework, + org.osgi.service.component, + org.apache.commons.logging, + javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional, + org.wso2.carbon.context, + org.wso2.carbon.utils.*, + org.wso2.carbon.registry.api, + org.w3c.dom, + org.apache.velocity;version="${velocity.version}", + org.apache.velocity.app;version="${velocity.version}", + org.apache.velocity.context;version="${velocity.version}", + org.apache.velocity.exception;version="${velocity.version}", + org.apache.velocity.runtime.resource;version="${velocity.version}", + org.apache.velocity.runtime.resource.loader;version="${velocity.version}", + org.apache.commons.io, + org.apache.axis2.transport.mail, + org.wso2.carbon.registry.core.service, + org.wso2.carbon.registry.core.session, + org.apache.commons.collections + + + !io.entgra.dynamic.task.allocation.framework.internal, + io.entgra.dynamic.task.allocation.framework.* + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + file:src/test/resources/log4j.properties + + + src/test/resources/testng.xml + + + + + org.jacoco + jacoco-maven-plugin + + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + test + + report + + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/site + + + + + + + + + + org.eclipse.osgi + org.eclipse.osgi + + + org.eclipse.osgi + org.eclipse.osgi.services + + + org.wso2.carbon + org.wso2.carbon.logging + + + org.wso2.carbon + org.wso2.carbon.utils + + + org.testng + testng + + + org.wso2.carbon + org.wso2.carbon.registry.api + + + org.wso2.carbon + org.wso2.carbon.base + + + org.apache.axis2.wso2 + axis2 + + + org.wso2.orbit.org.apache.velocity + velocity + + + commons-io.wso2 + commons-io + + + org.apache.axis2.transport + axis2-transport-mail + + + org.wso2.carbon + org.wso2.carbon.registry.core + + + commons-collections.wso2 + commons-collections + + + + + diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/ContentProcessingInterruptedException.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/ContentProcessingInterruptedException.java new file mode 100644 index 0000000000..ccf4358c35 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/ContentProcessingInterruptedException.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +public class ContentProcessingInterruptedException extends Exception { + + private static final long serialVersionUID = -3151279311929070298L; + + public ContentProcessingInterruptedException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public ContentProcessingInterruptedException(String message, Throwable cause) { + super(message, cause); + } + + public ContentProcessingInterruptedException(String msg) { + super(msg); + } + + public ContentProcessingInterruptedException() { + super(); + } + + public ContentProcessingInterruptedException(Throwable cause) { + super(cause); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/ContentProviderInfo.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/ContentProviderInfo.java new file mode 100644 index 0000000000..0bfe4339f8 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/ContentProviderInfo.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +import java.util.Map; + +public class ContentProviderInfo { + + private String template; + private Map, Object>> params; + + public ContentProviderInfo(final String template, final Map, Object>> params) { + if (template == null || template.isEmpty()) { + throw new IllegalArgumentException("Template name cannot be null or empty"); + } + this.template = template; + if (params == null) { + throw new IllegalArgumentException("Place-holder parameter map cannot be null"); + } + this.params = params; + } + + public String getTemplate() { + return template; + } + + public Map, Object>> getParams() { + return params; + } + + public void addParam(String name, TypedValue, Object> param) { + params.put(name, param); + } + + public TypedValue, Object> getParam(String name) { + return params.get(name); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContentProvider.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContentProvider.java new file mode 100644 index 0000000000..dd0005282a --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContentProvider.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +import java.util.Map; + +public interface EmailContentProvider { + + EmailData getContent(String path, + Map, Object>> params) throws ContentProcessingInterruptedException; + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContentProviderFactory.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContentProviderFactory.java new file mode 100644 index 0000000000..2b75d014fc --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContentProviderFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +public class EmailContentProviderFactory { + + public static EmailContentProvider getContentProvider() { + return new VelocityBasedEmailContentProvider(); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContext.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContext.java new file mode 100644 index 0000000000..0e645cc564 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailContext.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +import java.util.*; + +public class EmailContext { + + private Set recipients; + private Properties properties; + private ContentProviderInfo contentProviderInfo; + + private EmailContext(final ContentProviderInfo contentProviderInfo, final Set recipients, final Properties properties) { + if (contentProviderInfo == null) { + throw new IllegalArgumentException("Content provider information cannot be null"); + } + this.contentProviderInfo = contentProviderInfo; + if (recipients == null) { + throw new IllegalArgumentException("Recipient list cannot be null"); + } + if (recipients.size() == 0) { + throw new IllegalArgumentException("No recipient is configured. Recipient list should carry at " + + "least one recipient"); + } + this.recipients = recipients; + if (properties == null) { + throw new IllegalArgumentException("Email Context property bag cannot be null"); + } + this.properties = properties; + } + + private EmailContext(final ContentProviderInfo contentProviderInfo, final String recipient, final Properties properties) { + if (contentProviderInfo == null) { + throw new IllegalArgumentException("Content provider information cannot be null"); + } + this.contentProviderInfo = contentProviderInfo; + if (recipient == null || recipient.isEmpty()) { + throw new IllegalArgumentException("Recipient can't be null or empty. Please specify a valid " + + "recipient email address"); + } + this.recipients = new HashSet() {{ + add(recipient); + }}; + if (properties == null) { + throw new IllegalArgumentException("Email Context property bag cannot be null"); + } + this.properties = properties; + } + + public Set getRecipients() { + return recipients; + } + + public Properties getProperties() { + return properties; + } + + public String getProperty(String name) { + return (String) properties.get(name); + } + + public void addProperty(String name, String value) { + properties.put(name, value); + } + + public ContentProviderInfo getContentProviderInfo() { + return contentProviderInfo; + } + + public static class EmailContextBuilder { + + private Set recipients; + private ContentProviderInfo contentProviderInfo; + private Properties properties; + + public EmailContextBuilder(final ContentProviderInfo contentProviderInfo, Set recipients) { + if (contentProviderInfo == null) { + throw new IllegalArgumentException("Content provider information cannot be null"); + } + this.contentProviderInfo = contentProviderInfo; + if (recipients == null) { + throw new IllegalArgumentException("Recipient list cannot be null"); + } + if (recipients.size() == 0) { + throw new IllegalArgumentException("No recipient is configured. Recipient list should carry at " + + "least one recipient"); + } + this.recipients = recipients; + this.properties = new Properties(); + } + + public EmailContextBuilder(final ContentProviderInfo contentProviderInfo, final String recipient, + final Properties properties) { + if (contentProviderInfo == null) { + throw new IllegalArgumentException("Content provider information cannot be null"); + } + this.contentProviderInfo = contentProviderInfo; + if (recipient == null || recipient.isEmpty()) { + throw new IllegalArgumentException("Recipient can't be null or empty. Please specify a valid " + + "recipient email address"); + } + this.recipients = new HashSet() {{ + add(recipient); + }}; + if (properties == null) { + throw new IllegalArgumentException("Email Context property bag cannot be null"); + } + this.properties = properties; + } + + public EmailContextBuilder addProperty(String name, String value) { + properties.setProperty(name, value); + return this; + } + + public EmailContext build() { + return new EmailContext(contentProviderInfo, recipients, properties); + } + + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailData.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailData.java new file mode 100644 index 0000000000..73381ddf7c --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailData.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "EmailConfig") +public class EmailData { + + private String subject; + private String body; + + @XmlElement(name = "Subject", required = true) + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + @XmlElement(name = "Body", required = true) + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderConfig.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderConfig.java new file mode 100644 index 0000000000..c356b4a117 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderConfig.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +import org.w3c.dom.Document; +import org.wso2.carbon.utils.CarbonUtils; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.File; + +@XmlRootElement(name = "EmailSenderConfig") +public class EmailSenderConfig { + + private int minThreads; + private int maxThreads; + private int keepAliveDuration; + private int threadQueueCapacity; + + private static EmailSenderConfig config; + + private static final String EMAIL_SENDER_CONFIG_PATH = + CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "email-sender-config.xml"; + + private EmailSenderConfig() { + } + + public static EmailSenderConfig getInstance() { + if (config == null) { + throw new InvalidConfigurationStateException("Webapp Authenticator Configuration is not " + + "initialized properly"); + } + return config; + } + + @XmlElement(name = "MinThreads", required = true) + public int getMinThreads() { + return minThreads; + } + + public void setMinThreads(int minThreads) { + this.minThreads = minThreads; + } + + @XmlElement(name = "MaxThreads", required = true) + public int getMaxThreads() { + return maxThreads; + } + + public void setMaxThreads(int maxThreads) { + this.maxThreads = maxThreads; + } + + @XmlElement(name = "KeepAliveDuration", required = true) + public int getKeepAliveDuration() { + return keepAliveDuration; + } + + public void setKeepAliveDuration(int keepAliveDuration) { + this.keepAliveDuration = keepAliveDuration; + } + @XmlElement(name = "ThreadQueueCapacity", required = true) + public int getThreadQueueCapacity() { + return threadQueueCapacity; + } + + public void setThreadQueueCapacity(int threadQueueCapacity) { + this.threadQueueCapacity = threadQueueCapacity; + } + + public static void init() throws EmailSenderConfigurationFailedException { + try { + File emailSenderConfig = new File(EMAIL_SENDER_CONFIG_PATH); + Document doc = EmailSenderUtil.convertToDocument(emailSenderConfig); + + /* Un-marshaling Email Sender configuration */ + JAXBContext ctx = JAXBContext.newInstance(EmailSenderConfig.class); + Unmarshaller unmarshaller = ctx.createUnmarshaller(); + //unmarshaller.setSchema(getSchema()); + config = (EmailSenderConfig) unmarshaller.unmarshal(doc); + } catch (JAXBException e) { + throw new EmailSenderConfigurationFailedException("Error occurred while un-marshalling Email " + + "Sender Config", e); + } + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderConfigurationFailedException.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderConfigurationFailedException.java new file mode 100644 index 0000000000..ee0535c30a --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderConfigurationFailedException.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +public class EmailSenderConfigurationFailedException extends Exception { + + private static final long serialVersionUID = -3151279312929070298L; + + public EmailSenderConfigurationFailedException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public EmailSenderConfigurationFailedException(String message, Throwable cause) { + super(message, cause); + } + + public EmailSenderConfigurationFailedException(String msg) { + super(msg); + } + + public EmailSenderConfigurationFailedException() { + super(); + } + + public EmailSenderConfigurationFailedException(Throwable cause) { + super(cause); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderUtil.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderUtil.java new file mode 100644 index 0000000000..2861585306 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSenderUtil.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +import org.w3c.dom.Document; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; + +public class EmailSenderUtil { + + public static Document convertToDocument(File file) throws EmailSenderConfigurationFailedException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + return docBuilder.parse(file); + } catch (Exception e) { + throw new EmailSenderConfigurationFailedException("Error occurred while parsing file, while converting " + + "to a org.w3c.dom.Document", e); + } + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSendingFailedException.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSendingFailedException.java new file mode 100644 index 0000000000..914f30b5f7 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailSendingFailedException.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +public class EmailSendingFailedException extends Exception { + + private static final long serialVersionUID = -3151279311929070294L; + + public EmailSendingFailedException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public EmailSendingFailedException(String message, Throwable cause) { + super(message, cause); + } + + public EmailSendingFailedException(String msg) { + super(msg); + } + + public EmailSendingFailedException() { + super(); + } + + public EmailSendingFailedException(Throwable cause) { + super(cause); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailTransportNotConfiguredException.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailTransportNotConfiguredException.java new file mode 100644 index 0000000000..da23fcbeb1 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/EmailTransportNotConfiguredException.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.dynamic.task.allocation.framework; + +public class EmailTransportNotConfiguredException extends Exception { + + private static final long serialVersionUID = -3151279311929070294L; + + public EmailTransportNotConfiguredException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public EmailTransportNotConfiguredException(String message, Throwable cause) { + super(message, cause); + } + + public EmailTransportNotConfiguredException(String msg) { + super(msg); + } + + public EmailTransportNotConfiguredException() { + super(); + } + + public EmailTransportNotConfiguredException(Throwable cause) { + super(cause); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/InvalidConfigurationStateException.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/InvalidConfigurationStateException.java new file mode 100644 index 0000000000..3b222d4988 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/InvalidConfigurationStateException.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +public class InvalidConfigurationStateException extends RuntimeException { + + private static final long serialVersionUID = -3151279311329070297L; + + private String errorMessage; + private int errorCode; + + public InvalidConfigurationStateException(int errorCode, String message) { + super(message); + this.errorCode = errorCode; + } + + public InvalidConfigurationStateException(int errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + + public int getErrorCode() { + return errorCode; + } + + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public InvalidConfigurationStateException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public InvalidConfigurationStateException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public InvalidConfigurationStateException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public InvalidConfigurationStateException() { + super(); + } + + public InvalidConfigurationStateException(Throwable cause) { + super(cause); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/RegistryBasedResourceLoader.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/RegistryBasedResourceLoader.java new file mode 100644 index 0000000000..fc08058ca8 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/RegistryBasedResourceLoader.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +import org.apache.commons.collections.ExtendedProperties; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.apache.velocity.runtime.resource.Resource; +import org.apache.velocity.runtime.resource.loader.ResourceLoader; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.context.RegistryType; +import org.wso2.carbon.registry.api.Registry; +import org.wso2.carbon.registry.api.RegistryException; + +import java.io.InputStream; + +public class RegistryBasedResourceLoader extends ResourceLoader { + + private static final String EMAIL_CONFIG_BASE_LOCATION = "email-templates"; + + @Override + public void init(ExtendedProperties extendedProperties) { + + } + + @Override + public InputStream getResourceStream(String name) throws ResourceNotFoundException { + try { + Registry registry = + CarbonContext.getThreadLocalCarbonContext().getRegistry(RegistryType.SYSTEM_CONFIGURATION); + if (registry == null) { + throw new IllegalStateException("No valid registry instance is attached to the current carbon context"); + } + if (!registry.resourceExists(EMAIL_CONFIG_BASE_LOCATION + "/" + name)) { + throw new ResourceNotFoundException("Resource '" + name + "' does not exist"); + } + org.wso2.carbon.registry.api.Resource resource = + registry.get(EMAIL_CONFIG_BASE_LOCATION + "/" + name); + resource.setMediaType("text/plain"); + return resource.getContentStream(); + } catch (RegistryException e) { + throw new ResourceNotFoundException("Error occurred while retrieving resource", e); + } + } + + @Override + public boolean isSourceModified(Resource resource) { + return false; + } + + @Override + public long getLastModified(Resource resource) { + return 0; + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/TypedValue.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/TypedValue.java new file mode 100644 index 0000000000..3b95e30fd3 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/TypedValue.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +public class TypedValue { + + private final T type; + private final V value; + + public TypedValue(T type, V value) { + this.type = type; + this.value = value; + } + + public T getType() { + return type; + } + + public V getValue() { + return value; + } + + @Override + public int hashCode() { + return (type.hashCode() ^ value.hashCode()); + } + + @Override + public boolean equals(Object o) { + return o instanceof TypedValue && (this.type == ((TypedValue) o).getType() && + this.value == ((TypedValue) o).getValue()); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/VelocityBasedEmailContentProvider.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/VelocityBasedEmailContentProvider.java new file mode 100644 index 0000000000..d48b1298ea --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/VelocityBasedEmailContentProvider.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.resource.loader.ResourceLoader; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.context.RegistryType; +import org.wso2.carbon.registry.api.Registry; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.util.Map; + +public class VelocityBasedEmailContentProvider implements EmailContentProvider { + + private VelocityEngine engine; + private static final Log log = LogFactory.getLog(VelocityBasedEmailContentProvider.class); + + public VelocityBasedEmailContentProvider() { + engine = new VelocityEngine(); + engine.setProperty("resource.loader", "registry"); + engine.setProperty("velocimacro.library", ""); + engine.setProperty("registry.resource.loader.class", + "org.wso2.carbon.email.sender.core.RegistryBasedResourceLoader"); + engine.init(); + } + + @Override + public EmailData getContent(String name, Map, Object>> params) throws ContentProcessingInterruptedException { + VelocityContext ctx = new VelocityContext(); + for (Map.Entry, Object>> param : params.entrySet()) { + ctx.put(param.getKey(), param.getValue().getValue()); + } + Template template = engine.getTemplate(name); + + StringWriter content = new StringWriter(); + template.merge(ctx, content); + + InputStream is = null; + try { + JAXBContext jaxbCtx = JAXBContext.newInstance(EmailData.class); + Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller(); + + is = new ByteArrayInputStream(content.toString().getBytes()); + return (EmailData) unmarshaller.unmarshal(is); + } catch (JAXBException e) { + throw new ContentProcessingInterruptedException("Error occurred while parsing email data", e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + log.warn("Error occurred while closing input stream used to convert email configuration " + + "to an internal object model", e); + } + } + } + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderAxis2ConfigContextObserver.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderAxis2ConfigContextObserver.java new file mode 100644 index 0000000000..d04fccec1e --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderAxis2ConfigContextObserver.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.dynamic.task.allocation.framework.internal; + +import org.apache.axis2.context.ConfigurationContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import io.entgra.dynamic.task.allocation.framework.EmailSenderConfigurationFailedException; +import org.wso2.carbon.utils.Axis2ConfigurationContextObserver; + +class EmailSenderAxis2ConfigContextObserver implements Axis2ConfigurationContextObserver { + + private static final Log log = LogFactory.getLog(EmailSenderAxis2ConfigContextObserver.class); + + @Override + public void creatingConfigurationContext(int tenantId) { + + } + + @Override + public void createdConfigurationContext(ConfigurationContext configurationContext) { + try { + EmailUtils.setupEmailTemplates(); + } catch (EmailSenderConfigurationFailedException e) { + log.error("Error occurred while setting up email templates", e); + } + } + + @Override + public void terminatingConfigurationContext(ConfigurationContext configurationContext) { + + } + + @Override + public void terminatedConfigurationContext(ConfigurationContext configurationContext) { + + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderDataHolder.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderDataHolder.java new file mode 100644 index 0000000000..e8dded0590 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderDataHolder.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.dynamic.task.allocation.framework.internal; + +import io.entgra.dynamic.task.allocation.framework.service.EmailSenderService; +import org.wso2.carbon.registry.core.service.RegistryService; +import org.wso2.carbon.utils.ConfigurationContextService; + +public class EmailSenderDataHolder { + + private RegistryService registryService; + private ConfigurationContextService configurationContextService; + private EmailSenderService emailServiceProvider; + + private static EmailSenderDataHolder thisInstance = new EmailSenderDataHolder(); + + private EmailSenderDataHolder() {} + + public static EmailSenderDataHolder getInstance() { + return thisInstance; + } + + public RegistryService getRegistryService() { + if (registryService == null) { + throw new IllegalStateException("Registry service is not initialized properly"); + } + return registryService; + } + + public void setRegistryService(RegistryService registryService) { + this.registryService = registryService; + } + + public ConfigurationContextService getConfigurationContextService() { + if (configurationContextService == null) { + throw new IllegalStateException("ConfigurationContext service is not initialized properly"); + } + return configurationContextService; + } + + public void setConfigurationContextService(ConfigurationContextService configurationContextService) { + this.configurationContextService = configurationContextService; + } + + public EmailSenderService getEmailServiceProvider() { + return emailServiceProvider; + } + + public void setEmailServiceProvider(EmailSenderService emailServiceProvider) { + this.emailServiceProvider = emailServiceProvider; + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderServiceComponent.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderServiceComponent.java new file mode 100644 index 0000000000..d9f1167535 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailSenderServiceComponent.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.dynamic.task.allocation.framework.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.service.component.ComponentContext; +import io.entgra.dynamic.task.allocation.framework.EmailSenderConfig; +import io.entgra.dynamic.task.allocation.framework.service.EmailSenderService; +import io.entgra.dynamic.task.allocation.framework.service.EmailSenderServiceImpl; +import org.wso2.carbon.registry.core.service.RegistryService; +import org.wso2.carbon.utils.Axis2ConfigurationContextObserver; +import org.wso2.carbon.utils.ConfigurationContextService; + +/** + * @scr.component name="org.wso2.carbon.email.sender.emailsendereervicecomponent" + * immediate="true" + * @scr.reference name="registry.service" + * interface="org.wso2.carbon.registry.core.service.RegistryService" + * cardinality="1..1" + * policy="dynamic" + * bind="setRegistryService" + * unbind="unsetRegistryService" + * @scr.reference name="config.context.service" + * interface="org.wso2.carbon.utils.ConfigurationContextService" + * cardinality="0..1" + * policy="dynamic" + * bind="setConfigurationContextService" + * unbind="unsetConfigurationContextService" + */ +public class EmailSenderServiceComponent { + + private static Log log = LogFactory.getLog(EmailSenderServiceComponent.class); + + @SuppressWarnings("unused") + protected void activate(ComponentContext componentContext) { + try { + if (log.isDebugEnabled()) { + log.debug("Initializing email sender core bundle"); + } + /* Initializing email sender configuration */ + EmailSenderConfig.init(); + + /* Setting up default email templates */ + EmailUtils.setupEmailTemplates(); + + /* Registering declarative service instances exposed by EmailSenderServiceComponent */ + this.registerServices(componentContext); + + if (log.isDebugEnabled()) { + log.debug("Email sender core bundle has been successfully initialized"); + } + componentContext.getBundleContext().registerService(Axis2ConfigurationContextObserver.class.getName(), + new EmailSenderAxis2ConfigContextObserver(), null); + } catch (Throwable e) { + log.error("Error occurred while initializing email sender core bundle", e); + } + } + + @SuppressWarnings("unused") + protected void deactivate(ComponentContext componentContext) { + //do nothing + } + + private void registerServices(ComponentContext componentContext) { + if (log.isDebugEnabled()) { + log.debug("Registering email sender service"); + } + EmailSenderService emailServiceProvider = new EmailSenderServiceImpl(); + EmailSenderDataHolder.getInstance().setEmailServiceProvider(emailServiceProvider); + componentContext.getBundleContext().registerService(EmailSenderService.class, emailServiceProvider, null); + } + + /** + * Sets Registry Service. + * + * @param registryService An instance of RegistryService + */ + protected void setRegistryService(RegistryService registryService) { + if (log.isDebugEnabled()) { + log.debug("Setting Registry Service"); + } + EmailSenderDataHolder.getInstance().setRegistryService(registryService); + } + + /** + * Unsets Registry Service. + * + * @param registryService An instance of RegistryService + */ + protected void unsetRegistryService(RegistryService registryService) { + if (log.isDebugEnabled()) { + log.debug("Un setting Registry Service"); + } + EmailSenderDataHolder.getInstance().setRegistryService(null); + } + + protected void setConfigurationContextService(ConfigurationContextService configurationContextService) { + if (log.isDebugEnabled()) { + log.debug("Setting ConfigurationContextService"); + } + EmailSenderDataHolder.getInstance().setConfigurationContextService(configurationContextService); + } + + protected void unsetConfigurationContextService(ConfigurationContextService configurationContextService) { + if (log.isDebugEnabled()) { + log.debug("Un-setting ConfigurationContextService"); + } + EmailSenderDataHolder.getInstance().setConfigurationContextService(null); + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailUtils.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailUtils.java new file mode 100644 index 0000000000..20372239bd --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/internal/EmailUtils.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.dynamic.task.allocation.framework.internal; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.CarbonContext; +import io.entgra.dynamic.task.allocation.framework.EmailSenderConfigurationFailedException; +import org.wso2.carbon.registry.api.Collection; +import org.wso2.carbon.registry.api.Registry; +import org.wso2.carbon.registry.api.RegistryException; +import org.wso2.carbon.registry.api.Resource; +import org.wso2.carbon.utils.CarbonUtils; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FilenameFilter; +import java.io.IOException; + +class EmailUtils { + + private static final String EMAIL_TEMPLATE_DIR_RELATIVE_REGISTRY_PATH = "/email-templates"; + private static Log log = LogFactory.getLog(EmailSenderServiceComponent.class); + + static void setupEmailTemplates() throws EmailSenderConfigurationFailedException { + File templateDir = + new File(CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + + "resources" + File.separator + "email-templates"); + if (!templateDir.exists()) { + if (log.isDebugEnabled()) { + log.debug("The directory that is expected to use as the container for all email templates is not " + + "available. Therefore, no template is uploaded to the registry"); + } + } + if (templateDir.canRead()) { + File[] templates = templateDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + name = name.toLowerCase(); + return name.endsWith(".vm"); + } + }); + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + Registry registry = + EmailSenderDataHolder.getInstance().getRegistryService().getConfigSystemRegistry(tenantId); + if (!registry.resourceExists(EMAIL_TEMPLATE_DIR_RELATIVE_REGISTRY_PATH)) { + Collection collection = registry.newCollection(); + registry.put(EMAIL_TEMPLATE_DIR_RELATIVE_REGISTRY_PATH, collection); + for (File template : templates) { + Resource resource = registry.newResource(); + resource.setMediaType("text/plain"); + String contents = FileUtils.readFileToString(template); + resource.setContent(contents); + registry.put(EMAIL_TEMPLATE_DIR_RELATIVE_REGISTRY_PATH + "/" + + template.getName().replace(".vm", ""), resource); + } + } + } catch (RegistryException e) { + throw new EmailSenderConfigurationFailedException("Error occurred while setting up email templates", e); + } catch (FileNotFoundException e) { + throw new EmailSenderConfigurationFailedException("Error occurred while writing template file " + + "contents as an input stream of a resource", e); + } catch (IOException e) { + throw new EmailSenderConfigurationFailedException("Error occurred while serializing file " + + "contents to a string", e); + } + } + } + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/service/EmailSenderService.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/service/EmailSenderService.java new file mode 100644 index 0000000000..fc6b4663a2 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/service/EmailSenderService.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.dynamic.task.allocation.framework.service; + +import io.entgra.dynamic.task.allocation.framework.EmailContext; +import io.entgra.dynamic.task.allocation.framework.EmailSendingFailedException; +import io.entgra.dynamic.task.allocation.framework.EmailTransportNotConfiguredException; + +public interface EmailSenderService { + + void sendEmail(EmailContext emailCtx) throws EmailSendingFailedException, EmailTransportNotConfiguredException; + +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/service/EmailSenderServiceImpl.java b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/service/EmailSenderServiceImpl.java new file mode 100644 index 0000000000..32bb4ebdb6 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/main/java/io/entgra/dynamic/task/allocation/framework/service/EmailSenderServiceImpl.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.dynamic.task.allocation.framework.service; + +import io.entgra.dynamic.task.allocation.framework.ContentProcessingInterruptedException; +import io.entgra.dynamic.task.allocation.framework.ContentProviderInfo; +import io.entgra.dynamic.task.allocation.framework.EmailContentProvider; +import io.entgra.dynamic.task.allocation.framework.EmailContentProviderFactory; +import io.entgra.dynamic.task.allocation.framework.EmailContext; +import io.entgra.dynamic.task.allocation.framework.EmailData; +import io.entgra.dynamic.task.allocation.framework.EmailSenderConfig; +import io.entgra.dynamic.task.allocation.framework.EmailSendingFailedException; +import io.entgra.dynamic.task.allocation.framework.EmailTransportNotConfiguredException; +import io.entgra.dynamic.task.allocation.framework.internal.EmailSenderDataHolder; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.impl.llom.util.AXIOMUtil; +import org.apache.axis2.AxisFault; +import org.apache.axis2.Constants; +import org.apache.axis2.addressing.EndpointReference; +import org.apache.axis2.client.Options; +import org.apache.axis2.client.ServiceClient; +import org.apache.axis2.context.ConfigurationContext; +import org.apache.axis2.context.MessageContext; +import org.apache.axis2.transport.mail.MailConstants; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.email.sender.core.*; +import org.wso2.carbon.utils.ConfigurationContextService; + +import javax.xml.stream.XMLStreamException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class EmailSenderServiceImpl implements EmailSenderService { + + private static ThreadPoolExecutor threadPoolExecutor; + private EmailContentProvider contentProvider; + private static final String TRANSPORT_SENDER_NAME = "mailto"; + + static { + EmailSenderConfig config = EmailSenderConfig.getInstance(); + threadPoolExecutor = new ThreadPoolExecutor(config.getMinThreads(), config.getMaxThreads(), + config.getKeepAliveDuration(), TimeUnit.SECONDS, + new LinkedBlockingQueue(config.getThreadQueueCapacity())); + } + + private static final String EMAIL_URI_SCHEME = "mailto:"; + private static Log log = LogFactory.getLog(EmailSenderServiceImpl.class); + + public EmailSenderServiceImpl() { + this.contentProvider = EmailContentProviderFactory.getContentProvider(); + } + + private boolean isMailServerConfigured() { + return (EmailSenderDataHolder.getInstance().getConfigurationContextService().getServerConfigContext(). + getAxisConfiguration().getTransportOut(TRANSPORT_SENDER_NAME) != null); + } + + @Override + public void sendEmail(EmailContext emailCtx) throws EmailSendingFailedException, + EmailTransportNotConfiguredException { + if (this.isMailServerConfigured()) { + for (String recipient : emailCtx.getRecipients()) { + ContentProviderInfo info = emailCtx.getContentProviderInfo(); + EmailData emailData; + try { + emailData = contentProvider.getContent(info.getTemplate(), info.getParams()); + threadPoolExecutor.submit(new EmailSender(recipient, emailData.getSubject(), emailData.getBody())); + } catch (ContentProcessingInterruptedException e) { + throw new EmailSendingFailedException("Error occurred while retrieving email content to be " + + "sent for recipient '" + recipient + "'", e); + } + } + } else { + String msg = "Email sender transport is not configured. Please configure the 'mailto' sender" + + " transport in axis2.xml."; + log.warn(msg); + throw new EmailTransportNotConfiguredException(msg); + } + } + + public static class EmailSender implements Runnable { + + String to; + String subject; + String body; + + EmailSender(String to, String subject, String body) { + this.to = to; + this.subject = subject; + this.body = body; + } + + public void run() { + OMElement payload = null; + try { + payload = AXIOMUtil.stringToOM(body); + } catch (XMLStreamException e) { + log.error("Error occurred while converting email body contents to an XML", e); + } + try { + ConfigurationContextService configCtxService = + EmailSenderDataHolder.getInstance().getConfigurationContextService(); + if (configCtxService == null) { + throw new IllegalStateException("Configuration Context Service is not available"); + } + ConfigurationContext configCtx = configCtxService.getServerConfigContext(); + ServiceClient serviceClient = new ServiceClient(configCtx, null); + + Map headerMap = new HashMap<>(); + headerMap.put(MailConstants.MAIL_HEADER_SUBJECT, subject); + + Options options = new Options(); + options.setProperty(MessageContext.TRANSPORT_HEADERS, headerMap); + options.setProperty("FORCE_CONTENT_TYPE_BASED_FORMATTER", "true"); + options.setProperty(Constants.Configuration.MESSAGE_TYPE, "application/xml"); + options.setProperty(Constants.Configuration.CONTENT_TYPE, "text/html"); + options.setTo(new EndpointReference(EMAIL_URI_SCHEME + to)); + + serviceClient.setOptions(options); + serviceClient.fireAndForget(payload); + if (log.isDebugEnabled()) { + log.debug("Email has been successfully sent to '" + to + "'"); + } + } catch (AxisFault e) { + log.error("Error occurred while delivering the message, subject: '" + subject + "', to: '" + to + + "'", e); + } + } + } +} diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/test/resources/log4j.properties b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/test/resources/log4j.properties new file mode 100644 index 0000000000..dc3d465fc0 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/test/resources/log4j.properties @@ -0,0 +1,32 @@ +# +# Copyright 2009 WSO2, Inc. (http://wso2.com) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# This is the log4j configuration file used by WSO2 Carbon +# +# IMPORTANT : Please do not remove or change the names of any +# of the Appenders defined here. The layout pattern & log file +# can be changed using the WSO2 Carbon Management Console, and those +# settings will override the settings in this file. +# + +log4j.rootLogger=INFO, STD_OUT + +# Redirect log messages to console +log4j.appender.STD_OUT=org.apache.log4j.ConsoleAppender +log4j.appender.STD_OUT.Target=System.out +log4j.appender.STD_OUT.layout=org.apache.log4j.PatternLayout +log4j.appender.STD_OUT.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n diff --git a/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/test/resources/testng.xml b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/test/resources/testng.xml new file mode 100644 index 0000000000..7b13a25f89 --- /dev/null +++ b/components/task-allocation/io.entgra.dynamic.task.allocation.framework/src/test/resources/testng.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/pom.xml b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/pom.xml new file mode 100644 index 0000000000..818d3f35d7 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/pom.xml @@ -0,0 +1,185 @@ + + + + + + + org.wso2.carbon.devicemgt + task-allocation + 4.1.11-SNAPSHOT + ../pom.xml + + + 4.0.0 + io.entgra.server.bootup.heartbeat.beacon + bundle + Entgra - Heartbeat Beacon + Entgra - Server Startup and Heartbeat Monitoring Component + http://wso2.org + + + + + org.apache.felix + maven-scr-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + ${carbon.device.mgt.version} + Server Startup Heart Beat Beacon Bundle + io.entgra.server.bootup.heartbeat.beacon.internal + + org.apache.axis2.*;version="${axis2.osgi.version.range}", + org.apache.axiom.*; version="${axiom.osgi.version.range}", + org.osgi.framework, + org.osgi.service.component, + org.apache.commons.logging, + javax.xml.parsers;version="${javax.xml.parsers.import.pkg.version}";resolution:=optional, + org.wso2.carbon.context, + org.wso2.carbon.utils.*, + org.wso2.carbon.registry.api, + org.w3c.dom, + org.apache.velocity;version="${velocity.version}", + org.apache.velocity.app;version="${velocity.version}", + org.apache.velocity.context;version="${velocity.version}", + org.apache.velocity.exception;version="${velocity.version}", + org.apache.velocity.runtime.resource;version="${velocity.version}", + org.apache.velocity.runtime.resource.loader;version="${velocity.version}", + org.apache.commons.io, + org.apache.axis2.transport.mail, + org.wso2.carbon.registry.core.service, + org.wso2.carbon.registry.core.session, + org.apache.commons.collections, + org.wso2.carbon.device.mgt.common.* + + + !io.entgra.server.bootup.heartbeat.beacon.internal, + io.entgra.server.bootup.heartbeat.beacon.* + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + file:src/test/resources/log4j.properties + + + src/test/resources/testng.xml + + + + + org.jacoco + jacoco-maven-plugin + + ${basedir}/target/coverage-reports/jacoco-unit.exec + + + + jacoco-initialize + + prepare-agent + + + + jacoco-site + test + + report + + + ${basedir}/target/coverage-reports/jacoco-unit.exec + ${basedir}/target/coverage-reports/site + + + + + + + + + + org.eclipse.osgi + org.eclipse.osgi + + + org.eclipse.osgi + org.eclipse.osgi.services + + + org.wso2.carbon + org.wso2.carbon.logging + + + org.wso2.carbon + org.wso2.carbon.utils + + + org.testng + testng + + + org.wso2.carbon + org.wso2.carbon.registry.api + + + org.wso2.carbon + org.wso2.carbon.base + + + org.apache.axis2.wso2 + axis2 + + + org.wso2.orbit.org.apache.velocity + velocity + + + commons-io.wso2 + commons-io + + + org.apache.axis2.transport + axis2-transport-mail + + + org.wso2.carbon + org.wso2.carbon.registry.core + + + commons-collections.wso2 + commons-collections + + + org.wso2.carbon.devicemgt + org.wso2.carbon.device.mgt.common + + + + + diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/HeartBeatBeaconUtils.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/HeartBeatBeaconUtils.java new file mode 100644 index 0000000000..225438c913 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/HeartBeatBeaconUtils.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.server.bootup.heartbeat.beacon; + +import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; + +import javax.naming.InitialContext; +import javax.sql.DataSource; +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Hashtable; + +public class HeartBeatBeaconUtils { + + private static Log log = LogFactory.getLog(HeartBeatBeaconUtils.class); + + public static Document convertToDocument(File file) + throws HeartBeatBeaconConfigurationException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + DocumentBuilder docBuilder = factory.newDocumentBuilder(); + return docBuilder.parse(file); + } catch (Exception e) { + throw new HeartBeatBeaconConfigurationException("Error occurred while parsing file, while converting " + + "to a org.w3c.dom.Document", e); + } + } + + /** + * Lookup datasource using name and jndi properties + * + * @param dataSourceName Name of datasource to lookup + * @param jndiProperties Hash table of JNDI Properties + * @return datasource looked + */ + public static DataSource lookupDataSource(String dataSourceName, + final Hashtable jndiProperties) { + try { + if (jndiProperties == null || jndiProperties.isEmpty()) { + return (DataSource) InitialContext.doLookup(dataSourceName); + } + final InitialContext context = new InitialContext(jndiProperties); + return (DataSource) context.lookup(dataSourceName); + } catch (Exception e) { + throw new RuntimeException("Error in looking up data source: " + e.getMessage(), e); + } + } + + + public static ServerContext getServerDetails() throws UnknownHostException, SocketException { + InetAddress localHost = InetAddress.getLocalHost(); + NetworkInterface ni = NetworkInterface.getByInetAddress(localHost); + byte[] hardwareAddress = ni.getHardwareAddress(); + String[] hexadecimal = new String[hardwareAddress.length]; + for (int i = 0; i < hardwareAddress.length; i++) { + hexadecimal[i] = String.format("%02X", hardwareAddress[i]); + } + String macAddress = String.join("-", hexadecimal); + + ServerContext ctx = new ServerContext(); + ctx.setHostName(localHost.getHostName()); + ctx.setMacAddress(macAddress); + + return ctx; + } + + + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/config/datasource/DataSourceConfig.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/config/datasource/DataSourceConfig.java new file mode 100644 index 0000000000..d06ee05df6 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/config/datasource/DataSourceConfig.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.config.datasource; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Class for holding data source configuration in cdm-config.xml at parsing with JAXB + */ +@XmlRootElement(name = "DataSourceConfiguration") +public class DataSourceConfig { + + private JNDILookupDefinition jndiLookupDefinition; + + @XmlElement(name = "JndiLookupDefinition", nillable = true) + public JNDILookupDefinition getJndiLookupDefinition() { + return jndiLookupDefinition; + } + + public void setJndiLookupDefinition(JNDILookupDefinition jndiLookupDefinition) { + this.jndiLookupDefinition = jndiLookupDefinition; + } +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/config/datasource/JNDILookupDefinition.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/config/datasource/JNDILookupDefinition.java new file mode 100644 index 0000000000..96ae86fa1a --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/config/datasource/JNDILookupDefinition.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * you may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.config.datasource; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlValue; +import java.util.List; + +/** + * Class for hold JndiLookupDefinition of cdm-config.xml at parsing with JAXB + */ +@XmlRootElement(name = "JndiLookupDefinition") +public class JNDILookupDefinition { + + private String jndiName; + private List jndiProperties; + + @XmlElement(name = "Name", nillable = false) + public String getJndiName() { + return jndiName; + } + + public void setJndiName(String jndiName) { + this.jndiName = jndiName; + } + + @XmlElementWrapper(name = "Environment", nillable = false) + @XmlElement(name = "Property", nillable = false) + public List getJndiProperties() { + return jndiProperties; + } + + public void setJndiProperties(List jndiProperties) { + this.jndiProperties = jndiProperties; + } + + @XmlRootElement(name = "Property") + public static class JNDIProperty { + + private String name; + + private String value; + + @XmlAttribute(name = "Name") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } + +} + diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/HeartBeatBeaconDAOFactory.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/HeartBeatBeaconDAOFactory.java new file mode 100644 index 0000000000..93d6a612b3 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/HeartBeatBeaconDAOFactory.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.dao; + +import io.entgra.server.bootup.heartbeat.beacon.HeartBeatBeaconUtils; +import io.entgra.server.bootup.heartbeat.beacon.config.datasource.DataSourceConfig; +import io.entgra.server.bootup.heartbeat.beacon.config.datasource.JNDILookupDefinition; +import io.entgra.server.bootup.heartbeat.beacon.dao.impl.GenericHeartBeatDAOImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.exceptions.IllegalTransactionStateException; +import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.UnsupportedDatabaseEngineException; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Hashtable; +import java.util.List; + +/** + * This class represents factory for group management data operations + */ +public class HeartBeatBeaconDAOFactory { + + private static final Log log = LogFactory.getLog(HeartBeatBeaconDAOFactory.class); + private static DataSource dataSource; + private static ThreadLocal currentConnection = new ThreadLocal<>(); + + /** + * Get instance of GroupDAO + * + * @return instance of GroupDAO implementation + */ + public static HeartBeatDAO getHeartBeatDAO() { + return new GenericHeartBeatDAOImpl(); + } + + public static void init(DataSourceConfig config) { + dataSource = resolveDataSource(config); + } + + public static void init(DataSource dtSource) { + dataSource = dtSource; + } + + /** + * Begin transaction with datasource for write data + * + * @throws TransactionManagementException + */ + public static void beginTransaction() throws TransactionManagementException { + Connection conn = currentConnection.get(); + if (conn != null) { + throw new IllegalTransactionStateException("A transaction is already active within the context of " + + "this particular thread. Therefore, calling 'beginTransaction/openConnection' while another " + + "transaction is already active is a sign of improper transaction handling"); + } + try { + conn = dataSource.getConnection(); + conn.setAutoCommit(false); + currentConnection.set(conn); + } catch (SQLException e) { + throw new TransactionManagementException("Error occurred while retrieving config.datasource connection", e); + } + } + + /** + * Open connection to the datasource for read data + * + * @throws SQLException + */ + public static void openConnection() throws SQLException { + Connection conn = currentConnection.get(); + if (conn != null) { + throw new IllegalTransactionStateException("A transaction is already active within the context of " + + "this particular thread. Therefore, calling 'beginTransaction/openConnection' while another " + + "transaction is already active is a sign of improper transaction handling"); + } + conn = dataSource.getConnection(); + currentConnection.set(conn); + } + + /** + * Get current connection to datasource + * + * @return current connection + * @throws SQLException + */ + public static Connection getConnection() throws SQLException { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("No connection is associated with the current transaction. " + + "This might have ideally been caused by not properly initiating the transaction via " + + "'beginTransaction'/'openConnection' methods"); + } + return conn; + } + + /** + * Commit current transaction to the datasource + */ + public static void commitTransaction() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("No connection is associated with the current transaction. " + + "This might have ideally been caused by not properly initiating " + + "the transaction via 'beginTransaction'/'openConnection' methods"); + } + try { + conn.commit(); + } catch (SQLException e) { + log.error("Error occurred while committing the transaction", e); + } + } + + /** + * Rollback current transaction on failure + */ + public static void rollbackTransaction() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("No connection is associated with the current transaction. " + + "This might have ideally been caused by not properly initiating " + + "the transaction via 'beginTransaction'/'openConnection' methods"); + } + try { + conn.rollback(); + } catch (SQLException e) { + log.warn("Error occurred while roll-backing the transaction", e); + } + } + + /** + * Close data connection associated with current transaction + */ + public static void closeConnection() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("No connection is associated with the current transaction. " + + "This might have ideally been caused by not properly " + + "initiating the transaction via " + + "'beginTransaction'/'openConnection' methods"); + } + try { + conn.close(); + } catch (SQLException e) { + log.warn("Error occurred while close the connection"); + } + currentConnection.remove(); + } + + + /** + * Resolve data source from the data source definition + * + * @param config data source configuration + * @return data source resolved from the data source definition + */ + private static DataSource resolveDataSource(DataSourceConfig config) { + DataSource dataSource = null; + if (config == null) { + throw new RuntimeException( + "Device Management Repository data source configuration " + "is null and " + + "thus, is not initialized"); + } + JNDILookupDefinition jndiConfig = config.getJndiLookupDefinition(); + if (jndiConfig != null) { + if (log.isDebugEnabled()) { + log.debug("Initializing Device Management Repository data source using the JNDI " + + "Lookup Definition"); + } + List jndiPropertyList = + jndiConfig.getJndiProperties(); + if (jndiPropertyList != null) { + Hashtable jndiProperties = new Hashtable<>(); + for (JNDILookupDefinition.JNDIProperty prop : jndiPropertyList) { + jndiProperties.put(prop.getName(), prop.getValue()); + } + dataSource = HeartBeatBeaconUtils.lookupDataSource(jndiConfig.getJndiName(), jndiProperties); + } else { + dataSource = HeartBeatBeaconUtils.lookupDataSource(jndiConfig.getJndiName(), null); + } + } + return dataSource; + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/HeartBeatDAO.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/HeartBeatDAO.java new file mode 100644 index 0000000000..46412a8916 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/HeartBeatDAO.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.dao; + +import io.entgra.server.bootup.heartbeat.beacon.dao.exception.HeartBeatDAOException; +import io.entgra.server.bootup.heartbeat.beacon.dto.HeartBeatEvent; +import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext; + +import java.util.List; + +/** + * This interface represents the key operations associated with persisting group related information. + */ +public interface HeartBeatDAO { + + String recordServerCtx(ServerContext ctx) throws HeartBeatDAOException; + + boolean recordHeatBeat(HeartBeatEvent event) throws HeartBeatDAOException; + + String retrieveExistingServerCtx(ServerContext ctx) throws HeartBeatDAOException; + + int getActiveServerCount(int elapsedTimeInSeconds) throws HeartBeatDAOException; + + List getActiveServerDetails(int elapsedTimeInSeconds) throws HeartBeatDAOException; + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/exception/HeartBeatDAOException.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/exception/HeartBeatDAOException.java new file mode 100644 index 0000000000..ec6a4d3575 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/exception/HeartBeatDAOException.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.dao.exception; + +/** + * Custom exception class for group management data access related exceptions. + */ +public class HeartBeatDAOException extends Exception { + + private static final long serialVersionUID = 2021891706072918864L; + private String message; + + /** + * Constructs a new exception with the specified detail message and nested exception. + * + * @param message error message + * @param nestedException exception + */ + public HeartBeatDAOException(String message, Exception nestedException) { + super(message, nestedException); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified detail message and cause. + * + * @param message the detail message. + * @param cause the cause of this exception. + */ + public HeartBeatDAOException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified detail message + * + * @param message the detail message. + */ + public HeartBeatDAOException(String message) { + super(message); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified and cause. + * + * @param cause the cause of this exception. + */ + public HeartBeatDAOException(Throwable cause) { + super(cause); + } + + public String getMessage() { + return message; + } + + public void setErrorMessage(String errorMessage) { + this.message = errorMessage; + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/impl/GenericHeartBeatDAOImpl.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/impl/GenericHeartBeatDAOImpl.java new file mode 100644 index 0000000000..20ef8228b2 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/impl/GenericHeartBeatDAOImpl.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.dao.impl; + +import io.entgra.server.bootup.heartbeat.beacon.dao.HeartBeatBeaconDAOFactory; +import io.entgra.server.bootup.heartbeat.beacon.dao.HeartBeatDAO; +import io.entgra.server.bootup.heartbeat.beacon.dao.exception.HeartBeatDAOException; +import io.entgra.server.bootup.heartbeat.beacon.dao.util.HeartBeatBeaconDAOUtil; +import io.entgra.server.bootup.heartbeat.beacon.dto.HeartBeatEvent; +import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * This class represents implementation of HeartBeatDAO + */ +public class GenericHeartBeatDAOImpl implements HeartBeatDAO { + + @Override + public String recordServerCtx(ServerContext ctx) throws HeartBeatDAOException { + PreparedStatement stmt = null; + String uuid = null; + try { + Connection conn = HeartBeatBeaconDAOFactory.getConnection(); + + String sql; + sql = "INSERT INTO SERVER_HEART_BEAT_EVENTS(HOST_NAME, MAC, UUID) VALUES (?, ?, ?)"; + stmt = conn.prepareStatement(sql, new String[]{"UUID"}); + stmt.setString(1, ctx.getHostName()); + stmt.setString(2, ctx.getMacAddress()); + stmt.setString(3, UUID.randomUUID().toString()); + + stmt.executeUpdate(); + ResultSet result = stmt.getGeneratedKeys(); + if (result.next()){ + uuid = result.getString("UUID"); + } + } catch (SQLException e) { + throw new HeartBeatDAOException("Error occurred while persisting server context for : '" + + "mac '" + ctx.getMacAddress() + "' " + + "hostname : '" + ctx.getHostName() + "' ", e); + } finally { + HeartBeatBeaconDAOUtil.cleanupResources(stmt, null); + } + return uuid; + } + + @Override + public boolean recordHeatBeat(HeartBeatEvent event) throws HeartBeatDAOException { + PreparedStatement stmt = null; + try { + Connection conn = HeartBeatBeaconDAOFactory.getConnection(); + String sql; + sql = "UPDATE SERVER_HEART_BEAT_EVENTS SET LAST_UPDATED_TIMESTAMP = ? WHERE UUID = ?"; + stmt = conn.prepareStatement(sql, new String[]{"ID"}); + stmt.setTimestamp(1, event.getTime()); + stmt.setString(2, event.getServerUUID()); + + return stmt.executeUpdate() > 0; + } catch (SQLException e) { + throw new HeartBeatDAOException("Error occurred while updating heartbeat event against server with UUID : '" + + event.getServerUUID() + "' and timestamp " + event.getTime(), e); + } finally { + HeartBeatBeaconDAOUtil.cleanupResources(stmt, null); + } + } + + @Override + public String retrieveExistingServerCtx(ServerContext ctx) throws HeartBeatDAOException { + PreparedStatement stmt = null; + ResultSet resultSet = null; + String uuid = null; + try { + Connection conn = HeartBeatBeaconDAOFactory.getConnection(); + String sql = "SELECT UUID FROM SERVER_HEART_BEAT_EVENTS WHERE HOST_NAME = ? AND MAC = ?"; + stmt = conn.prepareStatement(sql, new String[]{"UUID"}); + stmt.setString(1, ctx.getHostName()); + stmt.setString(2, ctx.getMacAddress()); + + resultSet = stmt.executeQuery(); + if (resultSet.next()){ + uuid = resultSet.getString("UUID"); + } + } catch (SQLException e) { + throw new HeartBeatDAOException("Error occurred while retrieving meta information for heart beat event from " + + "mac '" + ctx.getMacAddress() + "' " + + "hostname : '" + ctx.getHostName() + "' ", e); + } finally { + HeartBeatBeaconDAOUtil.cleanupResources(stmt, resultSet); + } + return uuid; + } + + @Override + public int getActiveServerCount(int elapsedTimeInSeconds) throws HeartBeatDAOException { + PreparedStatement stmt = null; + ResultSet resultSet = null; + int count = -1; + try { + Connection conn = HeartBeatBeaconDAOFactory.getConnection(); + String sql = "SELECT COUNT(ID) AS COUNT from SERVER_HEART_BEAT_EVENTS WHERE " + + "LAST_UPDATED_TIMESTAMP > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL ? SECOND)"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, elapsedTimeInSeconds); + resultSet = stmt.executeQuery(); + if (resultSet.next()) { + count = resultSet.getInt("COUNT"); + } + } catch (SQLException e) { + throw new HeartBeatDAOException("Error occurred while retrieving acting server count with " + + "heartbeat updates within " + elapsedTimeInSeconds + " seconds.", e); + } finally { + HeartBeatBeaconDAOUtil.cleanupResources(stmt, resultSet); + } + return count; + } + + @Override + public List getActiveServerDetails(int elapsedTimeInSeconds) throws HeartBeatDAOException { + PreparedStatement stmt = null; + ResultSet resultSet = null; + List ctxList = new ArrayList<>(); + try { + Connection conn = HeartBeatBeaconDAOFactory.getConnection(); + String sql = "SELECT (@row_number:=@row_number + 1) AS IDX, UUID, HOST_NAME, MAC from " + + "SERVER_HEART_BEAT_EVENTS WHERE LAST_UPDATED_TIMESTAMP > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL ? SECOND) " + + "ORDER BY UUID"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, elapsedTimeInSeconds); + stmt.execute("SET @row_number = 0"); + resultSet = stmt.executeQuery(); + while (resultSet.next()) { + ctxList.add(HeartBeatBeaconDAOUtil.populateContext(resultSet)); + } + } catch (SQLException e) { + throw new HeartBeatDAOException("Error occurred while retrieving acting server count with " + + "heartbeat updates within " + elapsedTimeInSeconds + " seconds.", e); + } finally { + HeartBeatBeaconDAOUtil.cleanupResources(stmt, resultSet); + } + return ctxList; + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/util/HeartBeatBeaconDAOUtil.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/util/HeartBeatBeaconDAOUtil.java new file mode 100644 index 0000000000..46e992f8c3 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dao/util/HeartBeatBeaconDAOUtil.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.dao.util; + +import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.naming.InitialContext; +import javax.sql.DataSource; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Hashtable; + +/** + * This class represents utilities required to work with group management data + */ +public final class HeartBeatBeaconDAOUtil { + + private static final Log log = LogFactory.getLog(HeartBeatBeaconDAOUtil.class); + + /** + * Cleanup resources used to transaction + * + * @param stmt Prepared statement used + * @param rs Obtained results set + */ + public static void cleanupResources(PreparedStatement stmt, ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException e) { + log.warn("Error occurred while closing result set", e); + } + } + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException e) { + log.warn("Error occurred while closing prepared statement", e); + } + } + } + + /** + * Lookup datasource using name and jndi properties + * + * @param dataSourceName Name of datasource to lookup + * @param jndiProperties Hash table of JNDI Properties + * @return datasource looked + */ + public static DataSource lookupDataSource(String dataSourceName, + final Hashtable jndiProperties) { + try { + if (jndiProperties == null || jndiProperties.isEmpty()) { + return (DataSource) InitialContext.doLookup(dataSourceName); + } + final InitialContext context = new InitialContext(jndiProperties); + return (DataSource) context.lookup(dataSourceName); + } catch (Exception e) { + throw new RuntimeException("Error in looking up data source: " + e.getMessage(), e); + } + } + + + public static ServerContext populateContext(ResultSet resultSet) throws SQLException { + ServerContext ctx = new ServerContext(); + ctx.setIndex(resultSet.getInt("IDX")); + ctx.setUuid(resultSet.getString("UUID")); + ctx.setHostName(resultSet.getString("HOST_NAME")); + ctx.setMacAddress(resultSet.getString("MAC")); + return ctx; + } +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dto/HeartBeatEvent.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dto/HeartBeatEvent.java new file mode 100644 index 0000000000..d17ffaf447 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dto/HeartBeatEvent.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.server.bootup.heartbeat.beacon.dto; + +import java.sql.Timestamp; + +public class HeartBeatEvent { + + private String serverUUID; + private Timestamp time; + + public HeartBeatEvent(String serverUUID){ + this.serverUUID = serverUUID; + this.time = new Timestamp(System.currentTimeMillis()); + } + + public String getServerUUID() { + return serverUUID; + } + + public void setServerUUID(String serverUUID) { + this.serverUUID = serverUUID; + } + + public Timestamp getTime() { + return time; + } + + public void setTime(Timestamp time) { + this.time = time; + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dto/ServerContext.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dto/ServerContext.java new file mode 100644 index 0000000000..9facab390f --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/dto/ServerContext.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.server.bootup.heartbeat.beacon.dto; + +public class ServerContext { + + private String hostName; + private String macAddress; + private String serverHash; + private String uuid; + private int index; + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + public String getMacAddress() { + return macAddress; + } + + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + public String getServerHash() { + return serverHash; + } + + public void setServerHash(String serverHash) { + this.serverHash = serverHash; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/HeartBeatManagementException.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/HeartBeatManagementException.java new file mode 100644 index 0000000000..eeb44e6d7a --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/HeartBeatManagementException.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.server.bootup.heartbeat.beacon.exception; + +public class HeartBeatManagementException extends Exception { + + private static final long serialVersionUID = 5304352685379661115L; + + public HeartBeatManagementException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public HeartBeatManagementException(String message, Throwable cause) { + super(message, cause); + } + + public HeartBeatManagementException(String msg) { + super(msg); + } + + public HeartBeatManagementException() { + super(); + } + + public HeartBeatManagementException(Throwable cause) { + super(cause); + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/InvalidConfigurationStateException.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/InvalidConfigurationStateException.java new file mode 100644 index 0000000000..215b6ceb11 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/InvalidConfigurationStateException.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.server.bootup.heartbeat.beacon.exception; + +public class InvalidConfigurationStateException extends RuntimeException { + + private static final long serialVersionUID = -3151279311329070297L; + + private String errorMessage; + private int errorCode; + + public InvalidConfigurationStateException(int errorCode, String message) { + super(message); + this.errorCode = errorCode; + } + + public InvalidConfigurationStateException(int errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + + public int getErrorCode() { + return errorCode; + } + + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public InvalidConfigurationStateException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public InvalidConfigurationStateException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public InvalidConfigurationStateException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public InvalidConfigurationStateException() { + super(); + } + + public InvalidConfigurationStateException(Throwable cause) { + super(cause); + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/ServerStatusUpdationFailedException.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/ServerStatusUpdationFailedException.java new file mode 100644 index 0000000000..a23ccbe7c0 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/exception/ServerStatusUpdationFailedException.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package io.entgra.server.bootup.heartbeat.beacon.exception; + +public class ServerStatusUpdationFailedException extends Exception { + + private static final long serialVersionUID = -2610630531027402610L; + + public ServerStatusUpdationFailedException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + public ServerStatusUpdationFailedException(String message, Throwable cause) { + super(message, cause); + } + + public ServerStatusUpdationFailedException(String msg) { + super(msg); + } + + public ServerStatusUpdationFailedException() { + super(); + } + + public ServerStatusUpdationFailedException(Throwable cause) { + super(cause); + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatBeaconComponent.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatBeaconComponent.java new file mode 100644 index 0000000000..e936ea1593 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatBeaconComponent.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.server.bootup.heartbeat.beacon.internal; + +import io.entgra.server.bootup.heartbeat.beacon.HeartBeatBeaconConfig; +import io.entgra.server.bootup.heartbeat.beacon.HeartBeatBeaconUtils; +import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; +import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementServiceImpl; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.service.component.ComponentContext; + +/** + * @scr.component name="io.entgra.server.bootup.heartbeat.beacon.heartbeatBeaconComponent" + * immediate="true" + */ +public class HeartBeatBeaconComponent { + + private static Log log = LogFactory.getLog(HeartBeatBeaconComponent.class); + + @SuppressWarnings("unused") + protected void activate(ComponentContext componentContext) { + try { + if (log.isDebugEnabled()) { + log.debug("Initializing email sender core bundle"); + } + //heart beat notifier configuration */ + HeartBeatBeaconConfig.init(); + + this.registerHeartBeatServices(componentContext); + + //Setting up executors to notify heart beat status */ + HeartBeatInternalUtils.setUpNotifiers(HeartBeatBeaconUtils.getServerDetails()); + + if (log.isDebugEnabled()) { + log.debug("Email sender core bundle has been successfully initialized"); + } + } catch (Throwable e) { + log.error("Error occurred while initializing email sender core bundle", e); + } + } + + @SuppressWarnings("unused") + protected void deactivate(ComponentContext componentContext) { + //do nothing + } + + private void registerHeartBeatServices(ComponentContext componentContext) { + if (log.isDebugEnabled()) { + log.debug("Registering Heart Beat Management service"); + } + HeartBeatManagementService heartBeatServiceProvider = new HeartBeatManagementServiceImpl(); + HeartBeatBeaconDataHolder.getInstance().setHeartBeatManagementService(heartBeatServiceProvider); + componentContext.getBundleContext().registerService(HeartBeatManagementService.class, heartBeatServiceProvider, null); + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatBeaconDataHolder.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatBeaconDataHolder.java new file mode 100644 index 0000000000..a04ab9508a --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatBeaconDataHolder.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.internal; + +import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext; +import io.entgra.server.bootup.heartbeat.beacon.service.HeartBeatManagementService; + +public class HeartBeatBeaconDataHolder { + + private HeartBeatManagementService heartBeatManagementService; + private String localServerUUID; + + private static HeartBeatBeaconDataHolder thisInstance = new HeartBeatBeaconDataHolder(); + + private HeartBeatBeaconDataHolder() {} + + public static HeartBeatBeaconDataHolder getInstance() { + return thisInstance; + } + + public HeartBeatManagementService getHeartBeatManagementService() { + return heartBeatManagementService; + } + + public void setHeartBeatManagementService(HeartBeatManagementService heartBeatManagementService) { + this.heartBeatManagementService = heartBeatManagementService; + } + + public String getLocalServerUUID() { + return localServerUUID; + } + + public void setLocalServerUUID(String localServerUUID) { + this.localServerUUID = localServerUUID; + } +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatInternalUtils.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatInternalUtils.java new file mode 100644 index 0000000000..4b01bf33b6 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/internal/HeartBeatInternalUtils.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.server.bootup.heartbeat.beacon.internal; + +import com.sun.security.ntlm.Server; +import io.entgra.server.bootup.heartbeat.beacon.HeartBeatBeaconConfig; +import io.entgra.server.bootup.heartbeat.beacon.HeartBeatBeaconConfigurationException; +import io.entgra.server.bootup.heartbeat.beacon.dto.HeartBeatEvent; +import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext; +import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class HeartBeatInternalUtils { + + private static Log log = LogFactory.getLog(HeartBeatInternalUtils.class); + private static final int DEFAULT__NOTIFIER_INTERVAL = 5; + private static final int DEFAULT_NOTIFIER_DELAY = 5; + private static HeartBeatBeaconConfig CONFIG; + + static { + CONFIG = HeartBeatBeaconConfig.getInstance(); + } + + static void setUpNotifiers(ServerContext ctx) throws HeartBeatBeaconConfigurationException { + ScheduledExecutorService executor = + Executors.newSingleThreadScheduledExecutor(); + + if(CONFIG == null){ + throw new HeartBeatBeaconConfigurationException("Error while initiating schedule taks for recording heartbeats."); + } + + try { + String uuid = HeartBeatBeaconDataHolder.getInstance().getHeartBeatManagementService().updateServerContext(ctx); + HeartBeatBeaconDataHolder.getInstance().setLocalServerUUID(uuid); + Runnable periodicTask = new Runnable() { + public void run() { + try { + recordHeartBeat(uuid); + } catch (HeartBeatManagementException e) { + log.error("Error while executing record heart beat task. This will result in schedule operation malfunction.", e); + } + } + }; + executor.scheduleAtFixedRate(periodicTask, + CONFIG.getNotifierDelay() != 0 ? CONFIG.getNotifierDelay() : DEFAULT_NOTIFIER_DELAY, + CONFIG.getNotifierFrequency() != 0 ? CONFIG.getNotifierFrequency() : DEFAULT__NOTIFIER_INTERVAL, + TimeUnit.SECONDS); + } catch (HeartBeatManagementException e) { + throw new HeartBeatBeaconConfigurationException("Error occured while updating initial server context."); + } + } + + static void recordHeartBeat(String uuid) throws HeartBeatManagementException { + HeartBeatBeaconDataHolder.getInstance().getHeartBeatManagementService().recordHeartBeat(new HeartBeatEvent(uuid)); + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/service/HeartBeatManagementService.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/service/HeartBeatManagementService.java new file mode 100644 index 0000000000..65e21da3ca --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/service/HeartBeatManagementService.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.entgra.server.bootup.heartbeat.beacon.service; + +import io.entgra.server.bootup.heartbeat.beacon.dto.HeartBeatEvent; +import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException; +import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext; + +public interface HeartBeatManagementService { + + int getActiveServerCount() throws HeartBeatManagementException; + + int getServerLocalHashIndex() throws HeartBeatManagementException; + + String updateServerContext(ServerContext ctx) throws HeartBeatManagementException; + + boolean recordHeartBeat(HeartBeatEvent event) throws HeartBeatManagementException; + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/service/HeartBeatManagementServiceImpl.java b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/service/HeartBeatManagementServiceImpl.java new file mode 100644 index 0000000000..41fbf1418f --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/main/java/io/entgra/server/bootup/heartbeat/beacon/service/HeartBeatManagementServiceImpl.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.server.bootup.heartbeat.beacon.service; + +import io.entgra.server.bootup.heartbeat.beacon.HeartBeatBeaconConfig; +import io.entgra.server.bootup.heartbeat.beacon.dao.HeartBeatBeaconDAOFactory; +import io.entgra.server.bootup.heartbeat.beacon.dao.HeartBeatDAO; +import io.entgra.server.bootup.heartbeat.beacon.dao.exception.HeartBeatDAOException; +import io.entgra.server.bootup.heartbeat.beacon.dto.HeartBeatEvent; +import io.entgra.server.bootup.heartbeat.beacon.exception.HeartBeatManagementException; +import io.entgra.server.bootup.heartbeat.beacon.dto.ServerContext; +import io.entgra.server.bootup.heartbeat.beacon.internal.HeartBeatBeaconDataHolder; + +import java.sql.SQLException; +import java.util.List; + +public class HeartBeatManagementServiceImpl implements HeartBeatManagementService { + + @Override + public int getActiveServerCount() throws HeartBeatManagementException { + HeartBeatDAO heartBeatDAO; + int activeServerCount = -1; + try { + HeartBeatBeaconDAOFactory.openConnection(); + heartBeatDAO = HeartBeatBeaconDAOFactory.getHeartBeatDAO(); + + int timeOutIntervalInSeconds = HeartBeatBeaconConfig.getInstance().getServerTimeOutIntervalInSeconds(); + activeServerCount = heartBeatDAO.getActiveServerCount(timeOutIntervalInSeconds); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the underlying data source"; + throw new HeartBeatManagementException(msg, e); + } catch (HeartBeatDAOException e) { + String msg = "Error Occured while retrieving active server count."; + throw new HeartBeatManagementException(msg, e); + } finally { + HeartBeatBeaconDAOFactory.closeConnection(); + } + return activeServerCount; + } + + @Override + public int getServerLocalHashIndex() throws HeartBeatManagementException { + HeartBeatDAO heartBeatDAO; + int hashIndex = -1; + ServerContext localServerCtx = null; + try { + HeartBeatBeaconDAOFactory.openConnection(); + heartBeatDAO = HeartBeatBeaconDAOFactory.getHeartBeatDAO(); + + int timeOutIntervalInSeconds = HeartBeatBeaconConfig.getInstance().getServerTimeOutIntervalInSeconds(); + String localServerUUID = HeartBeatBeaconDataHolder.getInstance().getLocalServerUUID(); + List serverCtxList = heartBeatDAO.getActiveServerDetails(timeOutIntervalInSeconds); + for(ServerContext ctx : serverCtxList){ + if(ctx.getUuid() == localServerUUID){ + localServerCtx = ctx; + break; + } + } + if(localServerCtx != null){ + hashIndex = localServerCtx.getIndex(); + } + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the underlying data source"; + throw new HeartBeatManagementException(msg, e); + } catch (HeartBeatDAOException e) { + String msg = "Error Occured while retrieving active server count."; + throw new HeartBeatManagementException(msg, e); + } finally { + HeartBeatBeaconDAOFactory.closeConnection(); + } + return hashIndex; + } + + @Override + public String updateServerContext(ServerContext ctx) throws HeartBeatManagementException { + HeartBeatDAO heartBeatDAO; + String uuid = null; + try { + HeartBeatBeaconDAOFactory.openConnection(); + heartBeatDAO = HeartBeatBeaconDAOFactory.getHeartBeatDAO(); + + uuid = heartBeatDAO.retrieveExistingServerCtx(ctx); + if(uuid == null){ + uuid = heartBeatDAO.recordServerCtx(ctx); + } + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the underlying data source"; + throw new HeartBeatManagementException(msg, e); + } catch (HeartBeatDAOException e) { + String msg = "Error Occured while retrieving active server count."; + throw new HeartBeatManagementException(msg, e); + } finally { + HeartBeatBeaconDAOFactory.closeConnection(); + } + return uuid; + } + + + @Override + public boolean recordHeartBeat(HeartBeatEvent event) throws HeartBeatManagementException { + HeartBeatDAO heartBeatDAO; + boolean operationSuccess = false; + try { + HeartBeatBeaconDAOFactory.openConnection(); + heartBeatDAO = HeartBeatBeaconDAOFactory.getHeartBeatDAO(); + operationSuccess = heartBeatDAO.recordHeatBeat(event); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the underlying data source"; + throw new HeartBeatManagementException(msg, e); + } catch (HeartBeatDAOException e) { + String msg = "Error Occured while retrieving active server count."; + throw new HeartBeatManagementException(msg, e); + } finally { + HeartBeatBeaconDAOFactory.closeConnection(); + } + return operationSuccess; + } + +} diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/test/resources/log4j.properties b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/test/resources/log4j.properties new file mode 100644 index 0000000000..dc3d465fc0 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/test/resources/log4j.properties @@ -0,0 +1,32 @@ +# +# Copyright 2009 WSO2, Inc. (http://wso2.com) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# +# This is the log4j configuration file used by WSO2 Carbon +# +# IMPORTANT : Please do not remove or change the names of any +# of the Appenders defined here. The layout pattern & log file +# can be changed using the WSO2 Carbon Management Console, and those +# settings will override the settings in this file. +# + +log4j.rootLogger=INFO, STD_OUT + +# Redirect log messages to console +log4j.appender.STD_OUT=org.apache.log4j.ConsoleAppender +log4j.appender.STD_OUT.Target=System.out +log4j.appender.STD_OUT.layout=org.apache.log4j.PatternLayout +log4j.appender.STD_OUT.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n diff --git a/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/test/resources/testng.xml b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/test/resources/testng.xml new file mode 100644 index 0000000000..2da3b26042 --- /dev/null +++ b/components/task-allocation/io.entgra.server.bootup.heartbeat.beacon/src/test/resources/testng.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + diff --git a/components/task-allocation/pom.xml b/components/task-allocation/pom.xml new file mode 100644 index 0000000000..d7f3ae778e --- /dev/null +++ b/components/task-allocation/pom.xml @@ -0,0 +1,40 @@ + + + + + + + org.wso2.carbon.devicemgt + carbon-devicemgt + 4.1.11-SNAPSHOT + ../../pom.xml + + + 4.0.0 + task-allocation + pom + Entgra - Task Allocation Framework + http://wso2.org + + + io.entgra.dynamic.task.allocation.framework + io.entgra.server.bootup.heartbeat.beacon + + + diff --git a/pom.xml b/pom.xml index d12b76d9f4..f3f45141cd 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,7 @@ components/webapp-authenticator-framework components/email-sender components/ui-request-interceptor + components/task-allocation features/device-mgt features/apimgt-extensions features/application-mgt