From 2020dcd290301dd9b14ef5cc945bea2c316927a4 Mon Sep 17 00:00:00 2001 From: Benjamin Graf Date: Tue, 11 Oct 2016 21:27:52 +0200 Subject: [PATCH 1/2] ARTEMIS-793 Improvement to OSGi integration --- .../artemis/jdbc/store/JDBCUtils.java | 18 +++ .../artemis/osgi/DataSourceTracker.java | 79 +++++++++++ .../activemq/artemis/osgi/OsgiBroker.java | 123 +++++++++++++----- .../artemis/osgi/ServerTrackerCallBack.java | 22 ++++ .../storage/FileStorageConfiguration.java | 2 +- 5 files changed, 209 insertions(+), 35 deletions(-) create mode 100644 artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/DataSourceTracker.java create mode 100644 artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ServerTrackerCallBack.java diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/JDBCUtils.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/JDBCUtils.java index 0098328741..a0eba57b06 100644 --- a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/JDBCUtils.java +++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/JDBCUtils.java @@ -81,6 +81,24 @@ public class JDBCUtils { } + public static SQLProvider.Factory getSQLProviderFactory(String url) { + SQLProvider.Factory factory; + if (url.contains("derby")) { + logger.tracef("getSQLProvider Returning Derby SQL provider for url::%s", url); + factory = new DerbySQLProvider.Factory(); + } else if (url.contains("postgres")) { + logger.tracef("getSQLProvider Returning postgres SQL provider for url::%s", url); + factory = new PostgresSQLProvider.Factory(); + } else if (url.contains("mysql")) { + logger.tracef("getSQLProvider Returning mysql SQL provider for url::%s", url); + factory = new MySQLSQLProvider.Factory(); + } else { + logger.tracef("getSQLProvider Returning generic SQL provider for url::%s", url); + factory = new GenericSQLProvider.Factory(); + } + return factory; + } + public static SQLProvider getSQLProvider(String driverClass, String tableName) { SQLProvider.Factory factory; if (driverClass.contains("derby")) { diff --git a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/DataSourceTracker.java b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/DataSourceTracker.java new file mode 100644 index 0000000000..69c54b355e --- /dev/null +++ b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/DataSourceTracker.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 org.apache.activemq.artemis.osgi; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.activemq.artemis.core.config.storage.DatabaseStorageConfiguration; +import org.apache.activemq.artemis.jdbc.store.JDBCUtils; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTrackerCustomizer; + +public class DataSourceTracker implements ServiceTrackerCustomizer { + + private static final Logger LOG = Logger.getLogger(ProtocolTracker.class.getName()); + private final String name; + private final BundleContext context; + private final DatabaseStorageConfiguration dsc; + private final ServerTrackerCallBack callback; + + public DataSourceTracker(String name, BundleContext context, DatabaseStorageConfiguration dsc, + ServerTrackerCallBack callback) { + this.name = name; + this.context = context; + this.dsc = dsc; + this.callback = callback; + } + + @Override + public DataSource addingService(ServiceReference reference) { + DataSource dataSource = context.getService(reference); + dsc.setDataSource(dataSource); + try (Connection conn = dataSource.getConnection()) { + dsc.setSqlProvider(JDBCUtils.getSQLProviderFactory(conn.getMetaData().getURL())); + } catch (SQLException ex) { + LOG.log(Level.WARNING, "Error getting dataSource provider infos", ex); + } + callback.setDataSourceDependency(false); + try { + callback.start(); + } catch (Exception ex) { + LOG.log(Level.WARNING, "Error starting broker " + name, ex); + } + return dataSource; + } + + @Override + public void modifiedService(ServiceReference reference, DataSource service) { + // not supported + } + + @Override + public void removedService(ServiceReference reference, DataSource service) { + callback.setDataSourceDependency(true); + try { + callback.stop(); + } catch (Exception ex) { + LOG.log(Level.WARNING, "Error stopping broker " + name, ex); + } + } +} diff --git a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/OsgiBroker.java b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/OsgiBroker.java index c478096c47..58c21096a0 100644 --- a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/OsgiBroker.java +++ b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/OsgiBroker.java @@ -31,7 +31,10 @@ import java.util.Set; import org.apache.activemq.artemis.api.core.Interceptor; import org.apache.activemq.artemis.api.core.TransportConfiguration; import org.apache.activemq.artemis.core.config.FileDeploymentManager; +import org.apache.activemq.artemis.core.config.StoreConfiguration; +import org.apache.activemq.artemis.core.config.StoreConfiguration.StoreType; import org.apache.activemq.artemis.core.config.impl.FileConfiguration; +import org.apache.activemq.artemis.core.config.storage.DatabaseStorageConfiguration; import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants; import org.apache.activemq.artemis.core.server.ActiveMQComponent; import org.apache.activemq.artemis.core.server.ActiveMQServer; @@ -57,6 +60,7 @@ public class OsgiBroker { private Map components; private Map> registrations; private ServiceTracker tracker; + private ServiceTracker dataSourceTracker; @Activate public void activate(ComponentContext cctx) throws Exception { @@ -92,42 +96,21 @@ public class OsgiBroker { final ActiveMQServer server = (ActiveMQServer) components.get("core"); String[] requiredProtocols = getRequiredProtocols(server.getConfiguration().getAcceptorConfigurations()); - ProtocolTrackerCallBack callback = new ProtocolTrackerCallBack() { + ProtocolTrackerCallBack callback = new ProtocolTrackerCallBackImpl(server, context, properties); - @Override - public void addFactory(ProtocolManagerFactory pmf) { - server.addProtocolManagerFactory(pmf); - } + StoreConfiguration storeConfiguration = server.getConfiguration().getStoreConfiguration(); + String dataSourceName = String.class.cast(properties.get("dataSourceName")); + if (storeConfiguration.getStoreType() == StoreType.DATABASE && dataSourceName != null && + !dataSourceName.isEmpty()) { + callback = new ServerTrackerCallBackImpl(server, context, properties); + String filter = "(&(objectClass=javax.sql.DataSource)(osgi.jndi.service.name=" + dataSourceName + "))"; + DataSourceTracker trackerCust = + new DataSourceTracker(name, context, DatabaseStorageConfiguration.class.cast(storeConfiguration), + (ServerTrackerCallBack) callback); + dataSourceTracker = new ServiceTracker(context, context.createFilter(filter), trackerCust); + dataSourceTracker.open(); + } - @Override - public void removeFactory(ProtocolManagerFactory pmf) { - server.removeProtocolManagerFactory(pmf); - } - - @Override - public void stop() throws Exception { - ActiveMQComponent[] mqComponents = new ActiveMQComponent[components.size()]; - components.values().toArray(mqComponents); - for (int i = mqComponents.length - 1; i >= 0; i--) { - mqComponents[i].stop(); - } - unregister(); - } - - @Override - public void start() throws Exception { - List componentsByStartOrder = getComponentsByStartOrder(components); - for (ActiveMQComponent component : componentsByStartOrder) { - component.start(); - } - register(context, properties); - } - - @Override - public boolean isStarted() { - return server.isStarted(); - } - }; ProtocolTracker trackerCust = new ProtocolTracker(name, context, requiredProtocols, callback); tracker = new ServiceTracker(context, ProtocolManagerFactory.class, trackerCust); tracker.open(); @@ -160,6 +143,9 @@ public class OsgiBroker { @Deactivate public void stop() throws Exception { tracker.close(); + if (dataSourceTracker != null) { + dataSourceTracker.close(); + } } public Map getComponents() { @@ -220,4 +206,73 @@ public class OsgiBroker { } } } + + private class ProtocolTrackerCallBackImpl implements ProtocolTrackerCallBack { + + private final ActiveMQServer server; + private final BundleContext context; + private final Dictionary properties; + + ProtocolTrackerCallBackImpl(ActiveMQServer server, BundleContext context, + Dictionary properties) { + this.server = server; + this.context = context; + this.properties = properties; + } + + @Override + public void addFactory(ProtocolManagerFactory pmf) { + server.addProtocolManagerFactory(pmf); + } + + @Override + public void removeFactory(ProtocolManagerFactory pmf) { + server.removeProtocolManagerFactory(pmf); + } + + @Override + public void stop() throws Exception { + ActiveMQComponent[] mqComponents = new ActiveMQComponent[components.size()]; + components.values().toArray(mqComponents); + for (int i = mqComponents.length - 1; i >= 0; i--) { + mqComponents[i].stop(); + } + unregister(); + } + + @Override + public void start() throws Exception { + List componentsByStartOrder = getComponentsByStartOrder(components); + for (ActiveMQComponent component : componentsByStartOrder) { + component.start(); + } + register(context, properties); + } + + @Override + public boolean isStarted() { + return server.isStarted(); + } + } + + private class ServerTrackerCallBackImpl extends ProtocolTrackerCallBackImpl implements ServerTrackerCallBack { + + private volatile boolean dataSourceDependency = true; + + ServerTrackerCallBackImpl(ActiveMQServer server, BundleContext context, Dictionary properties) { + super(server, context, properties); + } + + @Override + public void setDataSourceDependency(boolean dataSourceDependency) { + this.dataSourceDependency = dataSourceDependency; + } + + @Override + public void start() throws Exception { + if (!dataSourceDependency) { + super.start(); + } + } + } } diff --git a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ServerTrackerCallBack.java b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ServerTrackerCallBack.java new file mode 100644 index 0000000000..1ef4c9edc2 --- /dev/null +++ b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ServerTrackerCallBack.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 org.apache.activemq.artemis.osgi; + +public interface ServerTrackerCallBack extends ProtocolTrackerCallBack { + + void setDataSourceDependency(boolean dataSourceDependency); +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/storage/FileStorageConfiguration.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/storage/FileStorageConfiguration.java index 05888b7992..4dd08f5a2d 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/storage/FileStorageConfiguration.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/storage/FileStorageConfiguration.java @@ -29,7 +29,7 @@ public class FileStorageConfiguration implements StoreConfiguration { @Override public StoreType getStoreType() { - return StoreType.DATABASE; + return StoreType.FILE; } public String getMessageTableName() { From 128a5058914e3da0ee42fb0a4e944fa8ceab2de7 Mon Sep 17 00:00:00 2001 From: Clebert Suconic Date: Wed, 19 Oct 2016 16:51:03 -0400 Subject: [PATCH 2/2] ARTEMIS-793 Improvements to OSGi Integration --- .../activemq/artemis/osgi/OsgiBroker.java | 39 ++++++++----------- .../artemis/osgi/ProtocolTracker.java | 4 +- .../artemis/osgi/ProtocolTrackerCallBack.java | 28 ------------- .../artemis/osgi/ServerTrackerCallBack.java | 11 +++++- .../artemis/osgi/ProtocolTrackerTest.java | 2 +- 5 files changed, 30 insertions(+), 54 deletions(-) delete mode 100644 artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ProtocolTrackerCallBack.java diff --git a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/OsgiBroker.java b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/OsgiBroker.java index 58c21096a0..9fb5e11073 100644 --- a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/OsgiBroker.java +++ b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/OsgiBroker.java @@ -96,13 +96,15 @@ public class OsgiBroker { final ActiveMQServer server = (ActiveMQServer) components.get("core"); String[] requiredProtocols = getRequiredProtocols(server.getConfiguration().getAcceptorConfigurations()); - ProtocolTrackerCallBack callback = new ProtocolTrackerCallBackImpl(server, context, properties); + ServerTrackerCallBack callback = new ServerTrackerCallBackImpl(server, context, properties); StoreConfiguration storeConfiguration = server.getConfiguration().getStoreConfiguration(); String dataSourceName = String.class.cast(properties.get("dataSourceName")); - if (storeConfiguration.getStoreType() == StoreType.DATABASE && dataSourceName != null && + + if (storeConfiguration != null && + storeConfiguration.getStoreType() == StoreType.DATABASE && dataSourceName != null && !dataSourceName.isEmpty()) { - callback = new ServerTrackerCallBackImpl(server, context, properties); + callback.setDataSourceDependency(true); String filter = "(&(objectClass=javax.sql.DataSource)(osgi.jndi.service.name=" + dataSourceName + "))"; DataSourceTracker trackerCust = new DataSourceTracker(name, context, DatabaseStorageConfiguration.class.cast(storeConfiguration), @@ -207,13 +209,15 @@ public class OsgiBroker { } } - private class ProtocolTrackerCallBackImpl implements ProtocolTrackerCallBack { + private class ServerTrackerCallBackImpl implements ServerTrackerCallBack { + + private volatile boolean dataSourceDependency = false; private final ActiveMQServer server; private final BundleContext context; private final Dictionary properties; - ProtocolTrackerCallBackImpl(ActiveMQServer server, BundleContext context, + ServerTrackerCallBackImpl(ActiveMQServer server, BundleContext context, Dictionary properties) { this.server = server; this.context = context; @@ -242,37 +246,28 @@ public class OsgiBroker { @Override public void start() throws Exception { - List componentsByStartOrder = getComponentsByStartOrder(components); - for (ActiveMQComponent component : componentsByStartOrder) { - component.start(); + if (!dataSourceDependency) { + List componentsByStartOrder = getComponentsByStartOrder(components); + for (ActiveMQComponent component : componentsByStartOrder) { + component.start(); + } + register(context, properties); } - register(context, properties); } @Override public boolean isStarted() { return server.isStarted(); } - } - private class ServerTrackerCallBackImpl extends ProtocolTrackerCallBackImpl implements ServerTrackerCallBack { - private volatile boolean dataSourceDependency = true; - - ServerTrackerCallBackImpl(ActiveMQServer server, BundleContext context, Dictionary properties) { - super(server, context, properties); - } @Override public void setDataSourceDependency(boolean dataSourceDependency) { this.dataSourceDependency = dataSourceDependency; } - @Override - public void start() throws Exception { - if (!dataSourceDependency) { - super.start(); - } - } + } + } diff --git a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ProtocolTracker.java b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ProtocolTracker.java index 545e8970f2..e01f6296f1 100644 --- a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ProtocolTracker.java +++ b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ProtocolTracker.java @@ -43,12 +43,12 @@ public class ProtocolTracker implements ServiceTrackerCustomizer protocols; - private ProtocolTrackerCallBack callback; + private ServerTrackerCallBack callback; public ProtocolTracker(String name, BundleContext context, String[] requiredProtocols, - ProtocolTrackerCallBack callback) { + ServerTrackerCallBack callback) { this.name = name; this.context = context; this.callback = callback; diff --git a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ProtocolTrackerCallBack.java b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ProtocolTrackerCallBack.java deleted file mode 100644 index 44cc5908aa..0000000000 --- a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ProtocolTrackerCallBack.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF 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 org.apache.activemq.artemis.osgi; - -import org.apache.activemq.artemis.api.core.Interceptor; -import org.apache.activemq.artemis.core.server.ActiveMQComponent; -import org.apache.activemq.artemis.spi.core.protocol.ProtocolManagerFactory; - -public interface ProtocolTrackerCallBack extends ActiveMQComponent { - - void addFactory(ProtocolManagerFactory pmf); - - void removeFactory(ProtocolManagerFactory pmf); -} diff --git a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ServerTrackerCallBack.java b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ServerTrackerCallBack.java index 1ef4c9edc2..5087a77c98 100644 --- a/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ServerTrackerCallBack.java +++ b/artemis-server-osgi/src/main/java/org/apache/activemq/artemis/osgi/ServerTrackerCallBack.java @@ -16,7 +16,16 @@ */ package org.apache.activemq.artemis.osgi; -public interface ServerTrackerCallBack extends ProtocolTrackerCallBack { +import org.apache.activemq.artemis.api.core.Interceptor; +import org.apache.activemq.artemis.core.server.ActiveMQComponent; +import org.apache.activemq.artemis.spi.core.protocol.ProtocolManagerFactory; + +public interface ServerTrackerCallBack extends ActiveMQComponent { + + void addFactory(ProtocolManagerFactory pmf); + + void removeFactory(ProtocolManagerFactory pmf); void setDataSourceDependency(boolean dataSourceDependency); + } diff --git a/artemis-server-osgi/src/test/java/org/apache/activemq/artemis/osgi/ProtocolTrackerTest.java b/artemis-server-osgi/src/test/java/org/apache/activemq/artemis/osgi/ProtocolTrackerTest.java index 744d45bd3d..97ee3ad910 100644 --- a/artemis-server-osgi/src/test/java/org/apache/activemq/artemis/osgi/ProtocolTrackerTest.java +++ b/artemis-server-osgi/src/test/java/org/apache/activemq/artemis/osgi/ProtocolTrackerTest.java @@ -34,7 +34,7 @@ public class ProtocolTrackerTest { IMocksControl c = EasyMock.createControl(); BundleContext context = c.createMock(BundleContext.class); String[] requiredProtocols = {"a", "b"}; - ProtocolTrackerCallBack callback = c.createMock(ProtocolTrackerCallBack.class); + ServerTrackerCallBack callback = c.createMock(ServerTrackerCallBack.class); RefFact protA = new RefFact(c, context, new String[]{"a"}); RefFact protB = new RefFact(c, context, new String[]{"b"});