diff --git a/README.adoc b/README.adoc index 95550de..7e3085a 100644 --- a/README.adoc +++ b/README.adoc @@ -116,3 +116,9 @@ A resource plugin is a generic concept that can be implemented by each product. The Gravitee Plugin Service Discovery module allows for loading service discovery plugin by providing a specific plugin handler. Service discovery plugins are useful to dynamically register or deregister endpoints. There is currently one implementation supporting Consul. + +=== Datasources + +The Gravitee Plugin Datasource module provides a datasource plugin handler in charge of detecting and loading all the datasource plugins. + +Datasource plugins are useful to provide a common connection pool or client to a data storage. There is currently one implementation supporting Redis. diff --git a/gravitee-plugin-core/src/main/java/io/gravitee/plugin/core/internal/AbstractPluginEventListener.java b/gravitee-plugin-core/src/main/java/io/gravitee/plugin/core/internal/AbstractPluginEventListener.java index 23e36e2..12e74a9 100644 --- a/gravitee-plugin-core/src/main/java/io/gravitee/plugin/core/internal/AbstractPluginEventListener.java +++ b/gravitee-plugin-core/src/main/java/io/gravitee/plugin/core/internal/AbstractPluginEventListener.java @@ -21,7 +21,14 @@ import io.gravitee.plugin.core.api.Plugin; import io.gravitee.plugin.core.api.PluginEvent; import io.gravitee.plugin.core.api.PluginHandler; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import lombok.AccessLevel; import lombok.Getter; @@ -40,10 +47,24 @@ public abstract class AbstractPluginEventListener implements EventListener { public static final String SECRET_PROVIDER = "secret-provider"; + public static final String DATASOURCE = "datasource"; + public static final String CLUSTER = "cluster"; + public static final String CACHE = "cache"; + public static final String REPOSITORY = "repository"; + public static final String ALERT = "alert"; + public static final String COCKPIT = "cockpit"; /** * Allows to define priority between the different plugin types. */ - private static final List pluginPriority = Arrays.asList(SECRET_PROVIDER, "cluster", "cache", "repository", "alert", "cockpit"); + private static final List pluginPriority = Arrays.asList( + SECRET_PROVIDER, + CLUSTER, + DATASOURCE, + CACHE, + REPOSITORY, + ALERT, + COCKPIT + ); private final Collection pluginHandlers; diff --git a/gravitee-plugin-datasource/pom.xml b/gravitee-plugin-datasource/pom.xml new file mode 100644 index 0000000..8c96d8c --- /dev/null +++ b/gravitee-plugin-datasource/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + io.gravitee.plugin + gravitee-plugin + 4.1.0 + + + gravitee-plugin-datasource + jar + + Gravitee.io - Plugin - Datasource + + + UTF-8 + + + + + io.gravitee.datasource + gravitee-datasource-api + ${gravitee-datasource-api.version} + + + + io.gravitee.plugin + gravitee-plugin-core + + + + diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePlugin.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePlugin.java new file mode 100644 index 0000000..ccc550f --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePlugin.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource; + +import io.gravitee.datasource.api.Datasource; +import io.gravitee.datasource.api.DatasourceConfiguration; +import io.gravitee.datasource.api.DatasourceConfigurationMapper; +import io.gravitee.plugin.core.api.ConfigurablePlugin; +import io.gravitee.plugin.core.api.Plugin; + +public interface DatasourcePlugin + extends ConfigurablePlugin { + String PLUGIN_TYPE = "datasource"; + + Plugin pluginDefinition(); + + Class datasource(); + + Class configurationMapper(); + + @Override + default String type() { + return PLUGIN_TYPE; + } +} diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginHandler.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginHandler.java new file mode 100644 index 0000000..0cca8c8 --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginHandler.java @@ -0,0 +1,135 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource; + +import static org.springframework.util.StringUtils.hasText; + +import io.gravitee.datasource.api.Datasource; +import io.gravitee.datasource.api.DatasourceConfiguration; +import io.gravitee.plugin.core.api.AbstractPluginHandler; +import io.gravitee.plugin.core.api.Plugin; +import io.gravitee.plugin.core.api.PluginContextFactory; +import io.gravitee.plugin.datasource.internal.DatasourceConfigurationClassFinder; +import io.gravitee.plugin.datasource.internal.DatasourceConfigurationFactory; +import io.gravitee.plugin.datasource.internal.DatasourceConfigurationMapperClassFinder; +import io.gravitee.plugin.datasource.spring.DatasourcePluginConfiguration; +import java.net.URLClassLoader; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +@Import(DatasourcePluginConfiguration.class) +public class DatasourcePluginHandler extends AbstractPluginHandler { + + private static final String CONF_DATASOURCES = "datasources"; + public static final String DATASOURCE_ID = "id"; + public static final String DATASOURCE_ENABLED = "enabled"; + public static final String DATASOURCE_SETTINGS = "settings"; + + @Autowired + private DatasourcePluginManager datasourcePluginManager; + + @Autowired + private Environment environment; + + @Autowired + private PluginContextFactory pluginContextFactory; + + @Autowired + private DatasourceConfigurationFactory configurationFactory; + + @Override + protected String type() { + return DatasourcePlugin.PLUGIN_TYPE; + } + + @Override + protected ClassLoader getClassLoader(Plugin plugin) throws Exception { + return new URLClassLoader(plugin.dependencies(), this.getClass().getClassLoader()); + } + + @Override + protected void handle(Plugin plugin, Class pluginClass) { + // register plugin definition to make DS available + // through UI not only through gravitee.yaml + DatasourcePlugin datasourcePlugin = create(plugin, pluginClass); + register(datasourcePlugin); + + // instantiate plugin form gravitee.yaml + if (plugin.deployed()) { + var pluginIndex = 0; + while (environment.containsProperty(datasourceConfigEntries(plugin, pluginIndex, DATASOURCE_ID))) { + instantiate(datasourcePlugin, pluginIndex++); + } + } + } + + private void instantiate(DatasourcePlugin datasourcePlugin, int pluginIndex) { + final var plugin = datasourcePlugin.pluginDefinition(); + if (environment.getProperty(datasourceConfigEntries(plugin, pluginIndex, DATASOURCE_ENABLED), boolean.class, true)) { + final var instanceName = environment.getProperty(datasourceConfigEntries(plugin, pluginIndex, DATASOURCE_ID), String.class); + if (!hasText(instanceName)) { + logger.warn("name is missing for datasource plugin {}, skip the instance creation", plugin.id()); + return; + } + + logger.info("Loading datasource plugin {} with name {}", plugin.id(), instanceName); + try { + DatasourceConfiguration configuration = configurationFactory.build( + datasourcePlugin.configurationMapper(), + datasourceConfigEntries(plugin, pluginIndex, DATASOURCE_SETTINGS) + ); + final var ds = createInstance(datasourcePlugin, configuration); + ds.start(); + + this.datasourcePluginManager.addDatasource(plugin, instanceName, ds); + } catch (Exception e) { + logger.error("Unable to instantiate datasource plugin of type {}", plugin.type(), e); + } + } + } + + private static String datasourceConfigEntries(Plugin plugin, int pluginIndex, String key) { + return CONF_DATASOURCES + "." + plugin.id() + "[" + pluginIndex + "]." + key; + } + + public Datasource createInstance(DatasourcePlugin datasourcePlugin, DatasourceConfiguration config) { + var pluginContext = pluginContextFactory.create(datasourcePlugin); + var ds = (Datasource) pluginContext.getAutowireCapableBeanFactory().createBean(datasourcePlugin.datasource()); + ds.setConfiguration(config); + return ds; + } + + protected DatasourcePlugin create(Plugin plugin, Class pluginClass) { + DatasourcePluginImpl resourcePlugin = new DatasourcePluginImpl(plugin, pluginClass); + resourcePlugin.setConfiguration(new DatasourceConfigurationClassFinder().lookupFirst(pluginClass)); + resourcePlugin.setConfigurationMapper(new DatasourceConfigurationMapperClassFinder().lookupFirst(pluginClass)); + return resourcePlugin; + } + + protected void register(DatasourcePlugin plugin) { + datasourcePluginManager.register(plugin); + } + + @Override + public boolean canHandle(Plugin plugin) { + return type().equalsIgnoreCase(plugin.type()); + } +} diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginImpl.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginImpl.java new file mode 100644 index 0000000..7c5f243 --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginImpl.java @@ -0,0 +1,98 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource; + +import io.gravitee.datasource.api.DatasourceConfiguration; +import io.gravitee.datasource.api.DatasourceConfigurationMapper; +import io.gravitee.plugin.core.api.Plugin; +import io.gravitee.plugin.core.api.PluginManifest; +import java.net.URL; +import java.nio.file.Path; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +public class DatasourcePluginImpl implements DatasourcePlugin { + + private final Plugin plugin; + private final Class datasourceClass; + private Class configuration; + private Class configurationMapper; + + public DatasourcePluginImpl(final Plugin plugin, final Class datasourceClass) { + this.plugin = plugin; + this.datasourceClass = datasourceClass; + } + + @Override + public Class datasource() { + return datasourceClass; + } + + @Override + public Plugin pluginDefinition() { + return plugin; + } + + @Override + public String clazz() { + return plugin.clazz(); + } + + @Override + public URL[] dependencies() { + return plugin.dependencies(); + } + + @Override + public String id() { + return plugin.id(); + } + + @Override + public PluginManifest manifest() { + return plugin.manifest(); + } + + @Override + public Path path() { + return plugin.path(); + } + + @Override + public boolean deployed() { + return plugin.deployed(); + } + + @Override + public Class configuration() { + return configuration; + } + + public void setConfiguration(Class datasourceConfigurationClass) { + this.configuration = datasourceConfigurationClass; + } + + @Override + public Class configurationMapper() { + return configurationMapper; + } + + public void setConfigurationMapper(Class datasourceConfigurationMapperClass) { + this.configurationMapper = datasourceConfigurationMapperClass; + } +} diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginManager.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginManager.java new file mode 100644 index 0000000..b95b69a --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/DatasourcePluginManager.java @@ -0,0 +1,41 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource; + +import io.gravitee.datasource.api.Datasource; +import io.gravitee.plugin.core.api.AbstractConfigurablePluginManager; +import io.gravitee.plugin.core.api.Plugin; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +public class DatasourcePluginManager extends AbstractConfigurablePluginManager { + + private Map> datasources = new ConcurrentHashMap<>(); + + public void addDatasource(Plugin plugin, String instanceName, Datasource datasource) { + this.datasources.putIfAbsent(plugin.id(), new ConcurrentHashMap<>()); + this.datasources.get(plugin.id()).putIfAbsent(instanceName, datasource); + } + + public Optional lookup(String pluginId, String instanceName) { + return Optional.ofNullable(this.datasources.get(pluginId)).map(instances -> instances.get(instanceName)); + } +} diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceClassLoaderFactory.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceClassLoaderFactory.java new file mode 100644 index 0000000..67f56eb --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceClassLoaderFactory.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource.internal; + +import io.gravitee.plugin.core.internal.CachedPluginClassLoaderFactory; +import io.gravitee.plugin.datasource.DatasourcePlugin; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +public class DatasourceClassLoaderFactory extends CachedPluginClassLoaderFactory {} diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationClassFinder.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationClassFinder.java new file mode 100644 index 0000000..f34961b --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationClassFinder.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource.internal; + +import io.gravitee.datasource.api.DatasourceConfiguration; +import io.gravitee.plugin.core.api.AbstractSingleSubTypesFinder; +import java.util.Collection; +import lombok.extern.slf4j.Slf4j; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +@Slf4j +public class DatasourceConfigurationClassFinder extends AbstractSingleSubTypesFinder { + + public DatasourceConfigurationClassFinder() { + super(DatasourceConfiguration.class); + } + + @Override + public Collection> lookup(Class clazz, ClassLoader classLoader) { + log.debug("Looking for a configuration class for datasource {} in package {}", clazz.getName(), clazz.getPackage().getName()); + Collection> configurations = super.lookup(clazz, classLoader); + + if (configurations.isEmpty()) { + log.info("No configuration class defined for datasource {}", clazz.getName()); + } + + return configurations; + } +} diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationFactory.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationFactory.java new file mode 100644 index 0000000..a01d1d4 --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource.internal; + +import io.gravitee.datasource.api.DatasourceConfiguration; +import io.gravitee.datasource.api.DatasourceConfigurationMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +public class DatasourceConfigurationFactory { + + @Autowired + private Environment environment; + + public DatasourceConfiguration build(Class configMapperClass, String propertiesPrefix) + throws Exception { + DatasourceConfigurationMapper confMapper = configMapperClass.getDeclaredConstructor().newInstance(); + return confMapper.from(environment, propertiesPrefix); + } +} diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationMapperClassFinder.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationMapperClassFinder.java new file mode 100644 index 0000000..9c6019f --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/internal/DatasourceConfigurationMapperClassFinder.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource.internal; + +import io.gravitee.datasource.api.DatasourceConfigurationMapper; +import io.gravitee.plugin.core.api.AbstractSingleSubTypesFinder; +import java.util.Collection; +import lombok.extern.slf4j.Slf4j; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +@Slf4j +public class DatasourceConfigurationMapperClassFinder extends AbstractSingleSubTypesFinder { + + public DatasourceConfigurationMapperClassFinder() { + super(DatasourceConfigurationMapper.class); + } + + @Override + public Collection> lookup(Class clazz, ClassLoader classLoader) { + log.debug("Looking for a configurationMapper class for datasource {} in package {}", clazz.getName(), clazz.getPackage().getName()); + Collection> configurations = super.lookup(clazz, classLoader); + + if (configurations.isEmpty()) { + log.info("No configurationMapper class defined for datasource {}", clazz.getName()); + } + + return configurations; + } +} diff --git a/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/spring/DatasourcePluginConfiguration.java b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/spring/DatasourcePluginConfiguration.java new file mode 100644 index 0000000..4581943 --- /dev/null +++ b/gravitee-plugin-datasource/src/main/java/io/gravitee/plugin/datasource/spring/DatasourcePluginConfiguration.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.plugin.datasource.spring; + +import io.gravitee.plugin.datasource.DatasourcePluginManager; +import io.gravitee.plugin.datasource.internal.DatasourceClassLoaderFactory; +import io.gravitee.plugin.datasource.internal.DatasourceConfigurationFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Eric LELEU (eric.leleu at graviteesource.com) + * @author GraviteeSource Team + */ +@Configuration +public class DatasourcePluginConfiguration { + + @Bean + public DatasourcePluginManager datasourcePluginManager() { + return new DatasourcePluginManager(); + } + + @Bean + public DatasourceClassLoaderFactory datasourceClassLoaderFactory() { + return new DatasourceClassLoaderFactory(); + } + + @Bean + public DatasourceConfigurationFactory datasourceConfigurationFactory() { + return new DatasourceConfigurationFactory(); + } +} diff --git a/gravitee-plugin-datasource/src/main/resources/META-INF/spring.factories b/gravitee-plugin-datasource/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..1a27d04 --- /dev/null +++ b/gravitee-plugin-datasource/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +io.gravitee.plugin.core.api.PluginHandler=\ + io.gravitee.plugin.datasource.DatasourcePluginHandler diff --git a/pom.xml b/pom.xml index 5118ccd..8fe7169 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ 3.0.8 1.1.4 1.0.0 + 1.0.0 @@ -66,6 +67,7 @@ gravitee-plugin-connector gravitee-plugin-annotation-processors gravitee-plugin-integrationprovider + gravitee-plugin-datasource