diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/pom.xml b/components/registry/org.wso2.carbon.registry.caching.invalidator/pom.xml
new file mode 100644
index 000000000..13b2e8dc5
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/pom.xml
@@ -0,0 +1,69 @@
+
+
+
+
+ org.wso2.carbon.registry
+ registry
+ 4.4.2-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.registry.caching.invalidator
+ bundle
+ WSO2 Carbon - Caching Invalidator
+ OSGi Bundle for the Cache invalidation for Carbon
+ http://wso2.org
+
+
+
+ org.wso2.carbon
+ org.wso2.carbon.core
+
+
+ org.wso2.carbon
+ org.wso2.carbon.utils
+
+
+ org.wso2.carbon
+ javax.cache.wso2
+
+
+ org.wso2.carbon
+ org.wso2.carbon.logging
+
+
+ org.apache.geronimo.specs.wso2
+ geronimo-jms_1.1_spec
+
+
+
+
+
+
+ org.apache.felix
+ maven-scr-plugin
+
+
+ org.apache.felix
+ maven-bundle-plugin
+ true
+
+
+ ${project.artifactId}
+ ${project.artifactId}
+
+ org.wso2.carbon.registry.caching.invalidator.*
+
+
+ !org.wso2.carbon.registry.caching.invalidator.*,
+ javax.jms.*
+
+ *
+
+
+
+
+
+
+
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/CacheInvalidationException.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/CacheInvalidationException.java
new file mode 100644
index 000000000..2aa87294c
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/CacheInvalidationException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.connection;
+
+public class CacheInvalidationException extends Exception {
+ public CacheInvalidationException(String message, Throwable cause) {
+ super(message,cause);
+ }
+
+ public CacheInvalidationException(String message) {
+ super(message);
+ }
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/InvalidNotification.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/InvalidNotification.java
new file mode 100644
index 000000000..d82aed058
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/InvalidNotification.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.connection;
+
+import java.util.Properties;
+
+public interface InvalidNotification {
+
+ public void createConnection(Properties config);
+
+ public void closeConnection();
+
+ public void publish(Object message);
+
+ public void subscribe();
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/InvalidationConnectionFactory.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/InvalidationConnectionFactory.java
new file mode 100644
index 000000000..2b4620e74
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/InvalidationConnectionFactory.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.connection;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.registry.caching.invalidator.impl.ConfigurationManager;
+import org.wso2.carbon.registry.caching.invalidator.internal.CacheInvalidationDataHolder;
+
+import java.util.Properties;
+
+public class InvalidationConnectionFactory {
+ private static final Log log = LogFactory.getLog(InvalidationConnectionFactory.class);
+
+ public static void createMessageBrokerConnection() throws CacheInvalidationException {
+ Properties properties = ConfigurationManager.getCacheConfiguration();
+ if (properties.containsKey("class.CacheInvalidationClass")) {
+ InvalidNotification connection = (InvalidNotification) getObject(properties.getProperty("class.CacheInvalidationClass"));
+ if (connection != null) {
+ connection.createConnection(properties);
+ CacheInvalidationDataHolder.setConnection(connection);
+ } else {
+ log.warn("Error while initializing message, Global cache invalidation will not work");
+ }
+ }
+ }
+
+ private static Object getObject(String className) throws CacheInvalidationException {
+ try {
+ Class factoryClass = Class.forName(className);
+ return factoryClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new CacheInvalidationException("Class " + className + " not found ", e);
+ } catch (IllegalAccessException e) {
+ throw new CacheInvalidationException("Class not be accessed ", e);
+ } catch (InstantiationException e) {
+ throw new CacheInvalidationException("Class not be instantiated ", e);
+ }
+ }
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/JMSNotification.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/JMSNotification.java
new file mode 100644
index 000000000..551f53b5d
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/connection/JMSNotification.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.connection;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.registry.caching.invalidator.impl.ConfigurationManager;
+import org.wso2.carbon.registry.caching.invalidator.impl.GlobalCacheInvalidationEvent;
+import org.wso2.carbon.registry.caching.invalidator.internal.CacheInvalidationDataHolder;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+
+import javax.cache.CacheManager;
+import javax.cache.Caching;
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TopicSession;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.Properties;
+
+public class JMSNotification implements InvalidNotification, MessageListener{
+
+ // Setup the pub/sub connection, session
+ // Send the msg (byte stream)
+ private static Connection connection = null;
+
+ private static Destination destination = null;
+
+ private static final Log log = LogFactory.getLog(JMSNotification.class);
+ @Override
+ public void createConnection(Properties config) {
+ try {
+ Properties props = new Properties();
+ props.put(Context.INITIAL_CONTEXT_FACTORY, config.getProperty("initialContextFactory"));
+ props.put(Context.PROVIDER_URL, config.getProperty("providerUrl"));
+ props.put(Context.SECURITY_PRINCIPAL, config.getProperty("securityPrincipal"));
+ props.put(Context.SECURITY_CREDENTIALS, config.getProperty("securityCredentials"));
+ props.put("topic.cacheInvalidateTopic", config.getProperty("cacheInvalidateTopic"));
+ InitialContext jndi = new InitialContext(props);
+ ConnectionFactory connectionFactory = (ConnectionFactory) jndi.lookup("ConnectionFactory");
+ destination = (Destination)jndi.lookup("cacheInvalidateTopic");
+
+ connection = connectionFactory.createConnection(config.getProperty("securityPrincipal"),
+ config.getProperty("securityCredentials"));
+ connection.start();
+ } catch (NamingException | JMSException e) {
+ log.error("Global cache invalidation: Error message broker initialization", e);
+ }
+ }
+
+ @Override
+ public void closeConnection() {
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (JMSException e) {
+ log.error("Global cache invalidation: Error in closing connection", e);
+ }
+ }
+ }
+
+
+ @Override
+ public void publish(Object message) {
+ Session pubSession = null;
+ try {
+ if (connection != null) {
+ pubSession = connection.createSession(false, TopicSession.AUTO_ACKNOWLEDGE);
+ MessageProducer publisher = pubSession.createProducer(destination);
+ BytesMessage bytesMessage = pubSession.createBytesMessage();
+ bytesMessage.writeBytes((byte[]) message);
+ publisher.send(bytesMessage);
+ }
+ } catch (JMSException e) {
+ log.error("Global cache invalidation: Error in publishing the message", e);
+ } finally {
+ if (pubSession != null) {
+ try {
+ pubSession.close();
+ } catch (JMSException e) {
+ log.error("Global cache invalidation: Error in publishing the message", e); }
+ }
+ }
+ }
+
+ @Override
+ public void subscribe() {
+ try {
+ Session subSession = connection.createSession(false, TopicSession.AUTO_ACKNOWLEDGE);
+ MessageConsumer messageConsumer = subSession.createConsumer(destination);
+ messageConsumer.setMessageListener(this);
+ connection.start();
+ log.info("Global cache invalidation is online");
+ } catch (JMSException e) {
+ log.error("Global cache invalidation: Error in subscribing to topic", e);
+ }
+ }
+
+ @Override
+ public void onMessage(Message message) {
+ BytesMessage bytesMessage = (BytesMessage) message;
+ byte[] data;
+ try {
+ data = new byte[(int) bytesMessage.getBodyLength()];
+ for (int i = 0; i < (int) bytesMessage.getBodyLength(); i++) {
+ data[i] = bytesMessage.readByte();
+ }
+ log.debug("Cache invalidation message received: " + new String(data));
+ } catch (JMSException jmsException) {
+ log.error("Error while reading the received message", jmsException);
+ return;
+ }
+
+ boolean isCoordinator = false;
+ if (CacheInvalidationDataHolder.getConfigContext() != null) {
+ isCoordinator = CacheInvalidationDataHolder.getConfigContext().getAxisConfiguration()
+ .getClusteringAgent().isCoordinator();
+ }
+ if (isCoordinator) {
+ PrivilegedCarbonContext.startTenantFlow();
+ try {
+ log.debug("Global cache invalidation: deserializing data to object");
+ GlobalCacheInvalidationEvent event = (GlobalCacheInvalidationEvent) deserialize(data);
+ log.debug("Global cache invalidation: deserializing complete");
+ if (!ConfigurationManager.getSentMsgBuffer().contains(event.getUuid().trim())) { // Ignore own messages
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(event.getTenantId(), true);
+ CacheManager cacheManager = Caching.getCacheManagerFactory().getCacheManager(event.getCacheManagerName());
+ if (cacheManager != null) {
+ if (cacheManager.getCache(event.getCacheName()) != null) {
+ cacheManager.getCache(event.getCacheName()).remove(event.getCacheKey());
+ log.debug("Global cache invalidated: " + event.getCacheKey());
+ } else {
+ log.error("Global cache invalidation: error cache is null");
+ }
+ } else {
+ log.error("Global cache invalidation: error cache manager is null");
+ }
+ } else {
+ // To resolve future performance issues
+ ConfigurationManager.getSentMsgBuffer().remove(event.getUuid().trim());
+ log.debug("Global cache invalidation: own message ignored");
+ }
+ } catch (Exception e) {
+ log.error("Global cache invalidation: error local cache update", e);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+ }
+
+ private Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
+ ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
+ return objectInputStream.readObject();
+ }
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/CacheInvalidationPublisher.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/CacheInvalidationPublisher.java
new file mode 100644
index 000000000..519c00acb
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/CacheInvalidationPublisher.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.caching.impl.CacheInvalidator;
+import org.wso2.carbon.registry.caching.invalidator.connection.CacheInvalidationException;
+import org.wso2.carbon.registry.caching.invalidator.connection.InvalidationConnectionFactory;
+import org.wso2.carbon.registry.caching.invalidator.internal.CacheInvalidationDataHolder;
+import org.wso2.carbon.registry.core.utils.UUIDGenerator;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * Global cache invalidation publisher implements org.wso2.carbon.caching.impl.CacheInvalidator interface
+ */
+public class CacheInvalidationPublisher implements CacheInvalidator {
+ private static final Log log = LogFactory.getLog(CacheInvalidationPublisher.class);
+
+ @Override
+ public void invalidateCache(int tenantId, String cacheManagerName, String cacheName, Serializable cacheKey) {
+ log.debug("Global cache invalidation: initializing the connection");
+ if (CacheInvalidationDataHolder.getConnection() == null) {
+ ConfigurationManager.init();
+ }
+ //Converting data to json string
+ GlobalCacheInvalidationEvent event = new GlobalCacheInvalidationEvent();
+ event.setTenantId(tenantId);
+ event.setCacheManagerName(cacheManagerName);
+ event.setCacheName(cacheName);
+ event.setCacheKey(cacheKey);
+ String uuid = UUIDGenerator.generateUUID();
+ event.setUuid(uuid);
+ byte data[];
+ try {
+ log.debug("Global cache invalidation: converting serializable object to byte stream.");
+ data = serialize(event);
+ log.debug("Global cache invalidation: converting data to byte stream complete.");
+ } catch (IOException e) {
+ log.error("Global cache invalidation: Error while converting data to byte stream", e);
+ return;
+ }
+
+ if (CacheInvalidationDataHolder.getConnection() != null) {
+ CacheInvalidationDataHolder.getConnection().publish(data);
+ } else {
+ try {
+ InvalidationConnectionFactory.createMessageBrokerConnection();
+ CacheInvalidationDataHolder.getConnection().publish(data);
+ } catch (CacheInvalidationException e) {
+ log.error("Error while publishing data, connection couldn't establish", e);
+ }
+ }
+ }
+
+ private byte[] serialize(Object obj) throws IOException {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
+ objectOutputStream.writeObject(obj);
+ return byteArrayOutputStream.toByteArray();
+ }
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/CacheInvalidationSubscriber.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/CacheInvalidationSubscriber.java
new file mode 100644
index 000000000..58883ff2e
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/CacheInvalidationSubscriber.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.impl;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.core.clustering.api.CoordinatedActivity;
+import org.wso2.carbon.registry.caching.invalidator.connection.CacheInvalidationException;
+import org.wso2.carbon.registry.caching.invalidator.connection.InvalidationConnectionFactory;
+import org.wso2.carbon.registry.caching.invalidator.internal.CacheInvalidationDataHolder;
+
+/**
+ * Global cache invalidation subscriber implements org.wso2.carbon.core.clustering.api.CoordinatedActivity interface
+ */
+public class CacheInvalidationSubscriber implements CoordinatedActivity {
+ private static final Log log = LogFactory.getLog(CacheInvalidationSubscriber.class);
+
+ public CacheInvalidationSubscriber() {
+ if (CacheInvalidationDataHolder.getConfigContext() != null &&
+ CacheInvalidationDataHolder.getConfigContext().getAxisConfiguration().getClusteringAgent() != null) {
+ boolean isCoordinator = CacheInvalidationDataHolder.getConfigContext().getAxisConfiguration()
+ .getClusteringAgent().isCoordinator();
+ if (isCoordinator && !ConfigurationManager.isSubscribed()) {
+ if (CacheInvalidationDataHolder.getConnection() != null) {
+ CacheInvalidationDataHolder.getConnection().subscribe();
+ ConfigurationManager.setSubscribed(true);
+ } else {
+ try {
+ InvalidationConnectionFactory.createMessageBrokerConnection();
+ CacheInvalidationDataHolder.getConnection().subscribe();
+ ConfigurationManager.setSubscribed(true);
+ } catch (CacheInvalidationException e) {
+ log.error("Error while subscribing to the queue, connection couldn't establish", e);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void execute() {
+ if(ConfigurationManager.init() && CacheInvalidationDataHolder.getConfigContext() != null) {
+ boolean isCoordinator = CacheInvalidationDataHolder.getConfigContext().getAxisConfiguration()
+ .getClusteringAgent().isCoordinator();
+ if (isCoordinator && !ConfigurationManager.isSubscribed()) {
+ if (CacheInvalidationDataHolder.getConnection() != null) {
+ CacheInvalidationDataHolder.getConnection().subscribe();
+ } else {
+ try {
+ InvalidationConnectionFactory.createMessageBrokerConnection();
+ CacheInvalidationDataHolder.getConnection().subscribe();
+ } catch (CacheInvalidationException e) {
+ log.error("Error while subscribing to the queue, connection couldn't establish", e);
+ return;
+ }
+ }
+ ConfigurationManager.setSubscribed(true);
+ }
+ if (!isCoordinator && ConfigurationManager.isSubscribed()) {
+ ConfigurationManager.setSubscribed(false);
+ }
+ }
+ }
+
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/ConfigurationManager.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/ConfigurationManager.java
new file mode 100644
index 000000000..e8d676250
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/ConfigurationManager.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Global cache invalidation configuration manager which extract configuration parameters from cache.xml
+ */
+public class ConfigurationManager {
+ private static final Log log = LogFactory.getLog(ConfigurationManager.class);
+
+ private static boolean subscribed = false;
+
+ private static boolean enabled = false;
+
+ private static Properties cacheConfiguration = new Properties();
+
+ private static List sentMsgBuffer;
+
+ public static boolean init(){
+ String configFilePath = CarbonUtils.getCarbonHome() + File.separator + "repository"
+ + File.separator + "conf" + File.separator + "cache.properties";
+ FileInputStream fileInputStream = null;
+ try{
+ fileInputStream = new FileInputStream(configFilePath);
+ cacheConfiguration.load(fileInputStream);
+
+ if(cacheConfiguration.containsKey("enabled")) {
+ enabled = Boolean.parseBoolean(cacheConfiguration.getProperty("enabled"));
+ }
+
+ if(!enabled){
+ log.info("Global cache invalidation is offline according to cache.properties configurations");
+ }
+
+ } catch (IOException ioException) {
+ log.error("Global cache invalidation : Error while reading cache.properties file", ioException);
+ } finally {
+ if (fileInputStream != null) {
+ try {
+ fileInputStream.close();
+ } catch (IOException ioException) {
+ log.error("Global cache invalidation : Error while reading cache.properties file", ioException);
+ }
+ }
+ }
+ return enabled;
+ }
+
+ public static List getSentMsgBuffer() {
+ if(sentMsgBuffer == null){
+ sentMsgBuffer = new ArrayList();
+ }
+ return sentMsgBuffer;
+ }
+
+ public static Properties getCacheConfiguration() {
+ return cacheConfiguration;
+ }
+
+ public static boolean isSubscribed() {
+ return subscribed;
+ }
+
+ public static void setSubscribed(boolean subscribed) {
+ ConfigurationManager.subscribed = subscribed;
+ }
+
+ public static boolean isEnabled() {
+ return enabled;
+ }
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/GlobalCacheInvalidationEvent.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/GlobalCacheInvalidationEvent.java
new file mode 100644
index 000000000..53bc55c66
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/impl/GlobalCacheInvalidationEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.impl;
+
+import java.io.Serializable;
+
+/**
+ * Global cache invalidation event serializable object which used to send the data to message broker
+ */
+public class GlobalCacheInvalidationEvent implements Serializable {
+ private int tenantId;
+ private String cacheManagerName;
+ private String cacheName;
+ private Serializable cacheKey;
+ private String uuid;
+
+ public int getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(int tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getCacheManagerName() {
+ return cacheManagerName;
+ }
+
+ public void setCacheManagerName(String cacheManagerName) {
+ this.cacheManagerName = cacheManagerName;
+ }
+
+ public String getCacheName() {
+ return cacheName;
+ }
+
+ public void setCacheName(String cacheName) {
+ this.cacheName = cacheName;
+ }
+
+ public Serializable getCacheKey() {
+ return cacheKey;
+ }
+
+ public void setCacheKey(Serializable cacheKey) {
+ this.cacheKey = cacheKey;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/internal/CacheInvalidationDataHolder.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/internal/CacheInvalidationDataHolder.java
new file mode 100644
index 000000000..050724823
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/internal/CacheInvalidationDataHolder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.internal;
+
+import org.apache.axis2.context.ConfigurationContext;
+import org.wso2.carbon.registry.caching.invalidator.connection.InvalidNotification;
+
+/**
+ * Cache Invalidation data holder
+ */
+public class CacheInvalidationDataHolder {
+ private static ConfigurationContext configContext;
+ private static InvalidNotification connection;
+
+ public static void setConfigContext(ConfigurationContext configContext) {
+ CacheInvalidationDataHolder.configContext = configContext;
+ }
+
+ public static ConfigurationContext getConfigContext() {
+ return configContext;
+ }
+
+ public static void setConnection(InvalidNotification connection) {
+ CacheInvalidationDataHolder.connection = connection;
+ }
+
+ public static InvalidNotification getConnection() {
+ return connection;
+ }
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/internal/CacheInvalidationServiceComponent.java b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/internal/CacheInvalidationServiceComponent.java
new file mode 100644
index 000000000..65f9bc7c8
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/java/org/wso2/carbon/registry/caching/invalidator/internal/CacheInvalidationServiceComponent.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * 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.
+ */
+package org.wso2.carbon.registry.caching.invalidator.internal;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentContext;
+import org.wso2.carbon.caching.impl.CacheInvalidator;
+import org.wso2.carbon.registry.caching.invalidator.connection.InvalidationConnectionFactory;
+import org.wso2.carbon.registry.caching.invalidator.impl.CacheInvalidationPublisher;
+import org.wso2.carbon.registry.caching.invalidator.impl.CacheInvalidationSubscriber;
+import org.wso2.carbon.registry.caching.invalidator.impl.ConfigurationManager;
+import org.wso2.carbon.core.clustering.api.CoordinatedActivity;
+import org.wso2.carbon.utils.ConfigurationContextService;
+
+/**
+ * @scr.component name="CacheInvalidationServiceComponent" immediate="true"
+ * @scr.reference name="configuration.context.service"
+ * interface="org.wso2.carbon.utils.ConfigurationContextService" cardinality="1..1"
+ * policy="dynamic" bind="setConfigurationContextService" unbind="unsetConfigurationContextService"
+ */
+
+public class CacheInvalidationServiceComponent {
+ private static Log log = LogFactory.getLog(CacheInvalidationServiceComponent.class);
+ ServiceRegistration serviceRegistration;
+ CacheInvalidationSubscriber subscriber;
+ CacheInvalidationPublisher publisher;
+
+ protected void activate(ComponentContext ctxt) {
+ log.debug("Cache Invalidation Service activation started");
+ try {
+ if(ConfigurationManager.init()) {
+ InvalidationConnectionFactory.createMessageBrokerConnection();
+ subscriber = new CacheInvalidationSubscriber();
+ publisher = new CacheInvalidationPublisher();
+ serviceRegistration = ctxt.getBundleContext().registerService(CacheInvalidator.class, publisher, null);
+ serviceRegistration = ctxt.getBundleContext().registerService(CoordinatedActivity.class, subscriber, null);
+ }
+ } catch (Exception e) {
+ String msg = "Failed to initialize the Cache Invalidation Service";
+ log.error(msg, e);
+ }
+ }
+
+ protected void deactivate(ComponentContext ctxt) {
+ log.debug("Cache Invalidation Service stopped");
+ try{
+ if(serviceRegistration != null) {
+ serviceRegistration.unregister();
+ }
+ }catch (Exception e){
+ String msg = "Failed to Stop the Cache Invalidation Service";
+ log.error(msg, e);
+ }
+ }
+
+ protected void setConfigurationContextService(ConfigurationContextService contextService) {
+ CacheInvalidationDataHolder.setConfigContext(contextService.getServerConfigContext());
+ }
+
+ protected void unsetConfigurationContextService(ConfigurationContextService contextService) {
+ CacheInvalidationDataHolder.setConfigContext(null);
+ }
+}
diff --git a/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/resources/cache.properties b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/resources/cache.properties
new file mode 100644
index 000000000..10359da14
--- /dev/null
+++ b/components/registry/org.wso2.carbon.registry.caching.invalidator/src/main/resources/cache.properties
@@ -0,0 +1,22 @@
+
+enabled=false
+class.CacheInvalidationClass=org.wso2.carbon.registry.caching.invalidator.connection.JMSNotification
+initialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory
+providerUrl=tcp://localhost:61616
+securityPrincipal=guest
+securityCredentials=guest
+cacheInvalidateTopic=GlobalCacheInvalidation
\ No newline at end of file
diff --git a/components/registry/org.wso2.carbon.registry.indexing/src/main/java/org/wso2/carbon/registry/indexing/service/ContentBasedSearchService.java b/components/registry/org.wso2.carbon.registry.indexing/src/main/java/org/wso2/carbon/registry/indexing/service/ContentBasedSearchService.java
index a98ff8f3b..5844ff1e1 100755
--- a/components/registry/org.wso2.carbon.registry.indexing/src/main/java/org/wso2/carbon/registry/indexing/service/ContentBasedSearchService.java
+++ b/components/registry/org.wso2.carbon.registry.indexing/src/main/java/org/wso2/carbon/registry/indexing/service/ContentBasedSearchService.java
@@ -27,6 +27,7 @@
import org.wso2.carbon.registry.common.ResourceData;
import org.wso2.carbon.registry.common.services.RegistryAbstractAdmin;
import org.wso2.carbon.registry.common.utils.CommonUtil;
+import org.wso2.carbon.registry.common.utils.UserUtil;
import org.wso2.carbon.registry.core.ActionConstants;
import org.wso2.carbon.registry.core.Collection;
import org.wso2.carbon.registry.core.RegistryConstants;
@@ -322,6 +323,21 @@ private ResourceData loadResourceByPath(UserRegistry registry, String path) thro
resourceData.setCreatedOn(createdDateTime);
CommonUtil.populateAverageStars(resourceData);
+ String user = child.getProperty("registry.user");
+
+ if (registry.getUserName().equals(user)) {
+ resourceData.setPutAllowed(true);
+ resourceData.setDeleteAllowed(true);
+ resourceData.setGetAllowed(true);
+ } else {
+ resourceData.setPutAllowed(
+ UserUtil.isPutAllowed(registry.getUserName(), path, registry));
+ resourceData.setDeleteAllowed(
+ UserUtil.isDeleteAllowed(registry.getUserName(), path, registry));
+ resourceData.setGetAllowed(
+ UserUtil.isGetAllowed(registry.getUserName(), path, registry));
+ }
+
child.discard();
return resourceData;
diff --git a/components/registry/pom.xml b/components/registry/pom.xml
index 098ef2ce7..b407e69f9 100644
--- a/components/registry/pom.xml
+++ b/components/registry/pom.xml
@@ -70,6 +70,7 @@
org.wso2.carbon.registry.cmis
org.wso2.carbon.registry.metadata
org.wso2.carbon.registry.deployment.synchronizer
+ org.wso2.carbon.registry.caching.invalidator
diff --git a/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.feature/pom.xml b/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.feature/pom.xml
new file mode 100644
index 000000000..23e12377e
--- /dev/null
+++ b/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.feature/pom.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+ org.wso2.carbon.registry
+ caching-invalidator-feature
+ 4.4.2-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.registry.caching.invalidator.feature
+ pom
+ WSO2 Carbon - Global Caching Invalidator Feature
+ http://wso2.org
+ This feature contains the bundles required for Global Cache invalidation for Carbon
+
+
+
+ org.wso2.carbon.registry
+ org.wso2.carbon.registry.caching.invalidator.server.feature
+ zip
+ ${carbon.registry.version}
+
+
+
+
+
+
+ org.wso2.maven
+ carbon-p2-plugin
+ ${carbon.p2.plugin.version}
+
+
+ p2-feature-generation
+ package
+
+ p2-feature-gen
+
+
+ org.wso2.carbon.registry.caching.invalidator.server
+ ../feature.properties
+
+
+ org.eclipse.equinox.p2.type.group:true
+
+
+
+ org.wso2.carbon.registry:org.wso2.carbon.registry.caching.invalidator.server.feature
+
+
+
+
+
+
+
+
+
diff --git a/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.server.feature/pom.xml b/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.server.feature/pom.xml
new file mode 100644
index 000000000..a248134a0
--- /dev/null
+++ b/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.server.feature/pom.xml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+ org.wso2.carbon.registry
+ caching-invalidator-feature
+ 4.4.2-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.registry.caching.invalidator.server.feature
+ pom
+ WSO2 Carbon - Global Caching Invalidator Server Feature
+ http://wso2.org
+ This feature contains the core bundles required for Global Cache invalidation for Carbon
+
+
+
+ org.wso2.carbon.registry
+ org.wso2.carbon.registry.caching.invalidator
+
+
+ org.apache.geronimo.specs.wso2
+ geronimo-jms_1.1_spec
+
+
+
+
+
+
+ maven-resources-plugin
+
+
+ copy-resources
+ generate-resources
+
+ copy-resources
+
+
+ src/main/resources
+
+
+ resources
+
+ conf/cache.properties
+ p2.inf
+
+
+
+
+
+
+
+
+ org.wso2.maven
+ carbon-p2-plugin
+ ${carbon.p2.plugin.version}
+
+
+ 4-p2-feature-generation
+ package
+
+ p2-feature-gen
+
+
+ org.wso2.carbon.registry.caching.invalidator.server
+ ../../etc/feature.properties
+
+
+ org.wso2.carbon.p2.category.type:server
+ org.eclipse.equinox.p2.type.group:false
+
+
+
+ org.wso2.carbon.registry:org.wso2.carbon.registry.caching.invalidator
+
+
+ org.apache.geronimo.specs.wso2:geronimo-jms_1.1_spec
+
+
+
+
+
+
+
+
+
diff --git a/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.server.feature/src/main/resources/conf/cache.properties b/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.server.feature/src/main/resources/conf/cache.properties
new file mode 100644
index 000000000..10359da14
--- /dev/null
+++ b/features/caching-invalidator/org.wso2.carbon.registry.caching.invalidator.server.feature/src/main/resources/conf/cache.properties
@@ -0,0 +1,22 @@
+
+enabled=false
+class.CacheInvalidationClass=org.wso2.carbon.registry.caching.invalidator.connection.JMSNotification
+initialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory
+providerUrl=tcp://localhost:61616
+securityPrincipal=guest
+securityCredentials=guest
+cacheInvalidateTopic=GlobalCacheInvalidation
\ No newline at end of file
diff --git a/features/caching-invalidator/pom.xml b/features/caching-invalidator/pom.xml
new file mode 100644
index 000000000..af0413307
--- /dev/null
+++ b/features/caching-invalidator/pom.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ org.wso2.carbon.registry
+ carbon-registry
+ 4.4.2-SNAPSHOT
+ ../../pom.xml
+
+
+ 4.0.0
+ caching-invalidator-feature
+ pom
+ WSO2 Carbon - Global cache invalidation feature module
+ http://wso2.org
+
+
+ org.wso2.carbon.registry.caching.invalidator.server.feature
+ org.wso2.carbon.registry.caching.invalidator.feature
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 0d004cdc0..7cdbd69ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,6 +39,7 @@
features/jcr
features/uddi
features/deployment-synchronizer
+ features/caching-invalidator
@@ -354,6 +355,11 @@
+
+ org.wso2.carbon
+ javax.cache.wso2
+ ${carbon.kernel.version}
+
org.wso2.carbon.commons
org.wso2.carbon.user.mgt
@@ -761,6 +767,11 @@
org.wso2.carbon.registry.deployment.synchronizer
${carbon.registry.version}
+
+ org.wso2.carbon.registry
+ org.wso2.carbon.registry.caching.invalidator
+ ${carbon.registry.version}
+
@@ -1258,7 +1269,11 @@
oauth2-client
${amber.version}
-
+
+ org.apache.geronimo.specs.wso2
+ geronimo-jms_1.1_spec
+ ${orbit.version.geronimo-jms_1.1_spec}
+
junit
@@ -1442,6 +1457,9 @@
4.4.0
[4.4.0, 4.5.0)
+
+ 1.1.0.wso2v1
+
4.4.2-SNAPSHOT
1.0.1