SGF-559 - Configure Geode Integrated Security with annotations.
This commit is contained in:
@@ -32,8 +32,8 @@ description = 'Spring Data Geode'
|
||||
group = 'org.springframework.data'
|
||||
archivesBaseName = project.name
|
||||
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
@@ -115,6 +115,7 @@ dependencies {
|
||||
// Java & 3rd Party Dependencies
|
||||
optional "javax.enterprise:cdi-api:$cdiVersion"
|
||||
compile "org.aspectj:aspectjweaver:$aspectjVersion"
|
||||
optional "org.apache.shiro:shiro-spring:$shiroVersion"
|
||||
compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
|
||||
compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion"
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ mockitoVersion=1.10.19
|
||||
multiThreadedtcVersion=1.01
|
||||
openwebbeansVersion=1.2.8
|
||||
servletApiVersion=2.5
|
||||
shiroVersion=1.3.2
|
||||
slf4jVersion=1.7.21
|
||||
spring.range="[4.0.0, 5.0.0)"
|
||||
springVersion=4.3.3.RELEASE
|
||||
|
||||
8
pom.xml
8
pom.xml
@@ -20,6 +20,7 @@
|
||||
<properties>
|
||||
<dist.key>SGF</dist.key>
|
||||
<antlr.version>2.7.7</antlr.version>
|
||||
<apache-shiro.version>1.3.2</apache-shiro.version>
|
||||
<assertj.version>2.5.0</assertj.version>
|
||||
<gemfire.version>1.1.0-incubating-SNAPSHOT</gemfire.version>
|
||||
<google-code-findbugs.version>2.0.2</google-code-findbugs.version>
|
||||
@@ -28,6 +29,7 @@
|
||||
<spring>4.3.3.RELEASE</spring>
|
||||
<springdata.commons>1.12.4.RELEASE</springdata.commons>
|
||||
<spring-shell.version>1.1.0.RELEASE</spring-shell.version>
|
||||
<source.level>1.8</source.level>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
@@ -124,6 +126,12 @@
|
||||
<version>${aspectj}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-spring</artifactId>
|
||||
<version>${apache-shiro.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
|
||||
@@ -88,8 +88,7 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
private static final AtomicBoolean CUSTOM_EDITORS_REGISTERED = new AtomicBoolean(false);
|
||||
private static final AtomicBoolean DEFINED_INDEXES_APPLICATION_LISTENER_REGISTERED = new AtomicBoolean(false);
|
||||
private static final AtomicBoolean DISK_STORE_DIRECTORY_BEAN_POST_PROCESSOR_REGISTERED = new AtomicBoolean(false);
|
||||
private static final AtomicBoolean PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED =
|
||||
new AtomicBoolean(false);
|
||||
private static final AtomicBoolean PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED = new AtomicBoolean(false);
|
||||
|
||||
protected static final boolean DEFAULT_CLOSE = true;
|
||||
protected static final boolean DEFAULT_COPY_ON_READ = false;
|
||||
@@ -270,7 +269,6 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
registerCustomEditorBeanFactoryPostProcessor(importMetadata);
|
||||
registerDefinedIndexesApplicationListener(importMetadata);
|
||||
registerDiskStoreDirectoryBeanPostProcessor(importMetadata);
|
||||
registerPdxDiskStoreAwareBeanFactoryPostProcessor(importMetadata);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,6 +321,8 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
setPdxPersistent(Boolean.TRUE.equals(enablePdxAttributes.get("persistent")));
|
||||
setPdxReadSerialized(Boolean.TRUE.equals(enablePdxAttributes.get("readSerialized")));
|
||||
setPdxSerializer(resolvePdxSerializer((String) enablePdxAttributes.get("serializerBeanName")));
|
||||
|
||||
registerPdxDiskStoreAwareBeanFactoryPostProcessor(importMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,9 +383,13 @@ public abstract class AbstractCacheConfiguration implements BeanClassLoaderAware
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void registerPdxDiskStoreAwareBeanFactoryPostProcessor(AnnotationMetadata importMetadata) {
|
||||
if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
if (StringUtils.hasText(pdxDiskStoreName())) {
|
||||
if (PDX_DISK_STORE_AWARE_BEAN_FACTORY_POST_PROCESSOR_REGISTERED.compareAndSet(false, true)) {
|
||||
register(BeanDefinitionBuilder.rootBeanDefinition(PdxDiskStoreAwareBeanFactoryPostProcessor.class)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
.addConstructorArgValue(pdxDiskStoreName())
|
||||
.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.internal.security.SecurityService;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.mgt.DefaultSecurityManager;
|
||||
import org.apache.shiro.realm.Realm;
|
||||
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ConfigurationCondition;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* The {@link ApacheShiroSecurityConfiguration} class is a Spring {@link Configuration @Configuration} component
|
||||
* responsible for configuring and initializing the Apache Shiro security framework in order to secure Apache Geode
|
||||
* administrative and data access operations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.internal.security.SecurityService
|
||||
* @see org.apache.shiro.mgt.SecurityManager
|
||||
* @see org.apache.shiro.spring.LifecycleBeanPostProcessor
|
||||
* @see org.springframework.context.annotation.Condition
|
||||
* @see org.springframework.context.annotation.Conditional
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@Conditional(ApacheShiroSecurityConfiguration.ApacheShiroPresentCondition.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class ApacheShiroSecurityConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<Realm> realms = Collections.emptyList();
|
||||
|
||||
@Autowired(required = false)
|
||||
private org.apache.shiro.mgt.SecurityManager shiroSecurityManager;
|
||||
|
||||
/**
|
||||
* {@link Bean} definition to configure and register an Apache Shiro, Spring {@link LifecycleBeanPostProcessor}
|
||||
* used to automatically call lifecycle callback methods on Shiro security components during Spring container
|
||||
* initialization and destruction phases.
|
||||
*
|
||||
* The registration of this {@link Bean} definition is dependent upon whether the user is using Apache Shiro
|
||||
* to secure Apache Geode, which is determined by the presence of Apache Shiro {@link Realm Realms}
|
||||
* declared in the Spring {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* @return an Apache Shiro, Spring {@link LifecycleBeanPostProcessor} bean.
|
||||
* @see org.apache.shiro.spring.LifecycleBeanPostProcessor
|
||||
*/
|
||||
@Bean
|
||||
//@Conditional(ShiroRealmsConfigured.class)
|
||||
public BeanPostProcessor shiroLifecycleBeanPostProcessor() {
|
||||
return new LifecycleBeanPostProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Bean} definition used to configure and register an Apache Shiro
|
||||
* {@link org.apache.shiro.mgt.SecurityManager} implementation to secure Apache Geode.
|
||||
*
|
||||
* The registration of this {@link Bean} definition is dependent upon whether the user is using Apache Shiro
|
||||
* to secure Apache Geode, which is determined by the presence of Apache Shiro {@link Realm Realms}
|
||||
* declared in the Spring {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* This {@link Bean} definition declares a dependency on the Apache Geode {@link GemFireCache} instance
|
||||
* in order to ensure the Geode cache is created and initialized first, thus evaluating any security configuration
|
||||
* logic internally in Apache Geode that may potentially overwrite the Spring configuration.
|
||||
*
|
||||
* @return an Apache Shiro {@link org.apache.shiro.mgt.SecurityManager} implementation used to secure Apache Geode.
|
||||
* @see org.apache.shiro.mgt.SecurityManager
|
||||
* @see #isRealmsPresent()
|
||||
* @see #getRealms()
|
||||
*/
|
||||
@Bean
|
||||
//@Conditional(ShiroRealmsConfigured.class)
|
||||
public org.apache.shiro.mgt.SecurityManager shiroSecurityManager(GemFireCache gemfireCache) {
|
||||
return (isRealmsPresent() ? new DefaultSecurityManager(getRealms()) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post processes the Apache Shiro security components by registering the Apach Shiro
|
||||
* {@link org.apache.shiro.mgt.SecurityManager} if present with the Apache Shiro security framework
|
||||
* and proceeds to enable Apache Geode security.
|
||||
*
|
||||
* @throws IllegalStateException if an Apache Shiro {@link org.apache.shiro.mgt.SecurityManager} is present
|
||||
* and Apache Geode security could not be enabled.
|
||||
* @see #registerSecurityManager(org.apache.shiro.mgt.SecurityManager)
|
||||
* @see #enableApacheGeodeSecurity()
|
||||
*/
|
||||
@PostConstruct
|
||||
public void postProcess() {
|
||||
if (this.shiroSecurityManager != null) {
|
||||
registerSecurityManager(this.shiroSecurityManager);
|
||||
|
||||
if (!enableApacheGeodeSecurity()) {
|
||||
throw new IllegalStateException("Failed to enable security services in Apache Geode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given Apache Shiro {@link org.apache.shiro.mgt.SecurityManager} with the Apache Shiro
|
||||
* security framework.
|
||||
*
|
||||
* @param securityManager {@link org.apache.shiro.mgt.SecurityManager} to register.
|
||||
* @return the given {@link org.apache.shiro.mgt.SecurityManager} reference.
|
||||
* @throws IllegalArgumentException if {@link org.apache.shiro.mgt.SecurityManager} is {@literal null}.
|
||||
* @see org.apache.shiro.SecurityUtils#setSecurityManager(org.apache.shiro.mgt.SecurityManager)
|
||||
* @see org.apache.shiro.mgt.SecurityManager
|
||||
*/
|
||||
protected org.apache.shiro.mgt.SecurityManager registerSecurityManager(
|
||||
org.apache.shiro.mgt.SecurityManager securityManager) {
|
||||
|
||||
Assert.notNull(securityManager, "The Apache Shiro SecurityManager to register must not be null");
|
||||
|
||||
SecurityUtils.setSecurityManager(securityManager);
|
||||
|
||||
return securityManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Apache Geode, Integrated Security {@link SecurityService} property {@literal isIntegratedSecurity}
|
||||
* to {@literal true} to indicate that Apache Geode security is enabled.
|
||||
*
|
||||
* @return a boolean value indicating whether Apache Geode's Integrated Security framework services
|
||||
* were successfully enabled.
|
||||
* @see org.apache.geode.internal.security.SecurityService#getSecurityService()
|
||||
*/
|
||||
protected boolean enableApacheGeodeSecurity() {
|
||||
SecurityService securityService = SecurityService.getSecurityService();
|
||||
|
||||
if (securityService != null) {
|
||||
Field isIntegratedSecurity = ReflectionUtils.findField(securityService.getClass(),
|
||||
"isIntegratedSecurity", Boolean.TYPE);
|
||||
|
||||
if (isIntegratedSecurity != null) {
|
||||
ReflectionUtils.makeAccessible(isIntegratedSecurity);
|
||||
ReflectionUtils.setField(isIntegratedSecurity, securityService, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link List} of Apache Shiro {@link Realm Realms} configured in
|
||||
* this Spring {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* @return a {@link List} of configured/declared Apache Shiro {@link Realm Realms}.
|
||||
* @see org.apache.shiro.realm.Realm
|
||||
*/
|
||||
protected List<Realm> getRealms() {
|
||||
return this.realms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether any Apache Shiro {@link Realm Realms} were configured in
|
||||
* this Spring {@link org.springframework.context.ApplicationContext}.
|
||||
*
|
||||
* @return a boolean value indicating whether any Apache Shiro {@link Realm Realms} were declared and configured
|
||||
* in this Spring {@link org.springframework.context.ApplicationContext}.
|
||||
* @see #getRealms()
|
||||
*/
|
||||
protected boolean isRealmsPresent() {
|
||||
return !CollectionUtils.isEmpty(getRealms());
|
||||
}
|
||||
|
||||
/**
|
||||
* A Spring {@link Condition} to determine whether the user has included (declared) the 'shiro-spring' dependency
|
||||
* on their application's classpath, which is necessary for configuring Apache Shiro to secure Apache Geode
|
||||
* in a Spring context.
|
||||
*
|
||||
* @see org.springframework.context.annotation.Condition
|
||||
*/
|
||||
public static class ApacheShiroPresentCondition implements Condition {
|
||||
|
||||
protected static final String APACHE_SHIRO_LIFECYCLE_BEAN_POST_PROCESOR_CLASS_NAME =
|
||||
"org.apache.shiro.spring.LifecycleBeanPostProcessor";
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
return ClassUtils.isPresent(APACHE_SHIRO_LIFECYCLE_BEAN_POST_PROCESOR_CLASS_NAME,
|
||||
context.getClassLoader());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Spring {@link Condition} implementation that determines whether the user declared and configured
|
||||
* any Apache Shiro {@link Realm Realms}, which are necessary to configure the Apache Shiro security framework
|
||||
* with security meta-data used to secure Apache Geode.
|
||||
*
|
||||
* @see org.springframework.context.annotation.ConfigurationCondition
|
||||
*/
|
||||
public static class ShiroRealmsConfigured implements ConfigurationCondition {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public ConfigurationPhase getConfigurationPhase() {
|
||||
return ConfigurationPhase.REGISTER_BEAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
ListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
|
||||
ApacheShiroSecurityConfiguration securityConfiguration =
|
||||
beanFactory.getBean(ApacheShiroSecurityConfiguration.class);
|
||||
|
||||
return (securityConfiguration.isRealmsPresent() || !beanFactory.getBeansOfType(Realm.class).isEmpty());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,18 @@ public class AuthConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
|
||||
public static final String DEFAULT_SECURITY_LOG_LEVEL = "config";
|
||||
|
||||
protected static final String GEMFIRE_SECURITY_PROPERTY_FILE = "gemfireSecurityPropertyFile";
|
||||
protected static final String SECURITY_CLIENT_ACCESSOR = "security-client-accessor";
|
||||
protected static final String SECURITY_CLIENT_ACCESSOR_POST_PROCESSOR = "security-client-accessor-pp";
|
||||
protected static final String SECURITY_CLIENT_AUTH_INIT = "security-client-auth-init";
|
||||
protected static final String SECURITY_CLIENT_AUTHENTICATOR = "security-client-authenticator";
|
||||
protected static final String SECURITY_CLIENT_DIFFIE_HELLMAN_ALGORITHM = "security-client-dhalgo";
|
||||
protected static final String SECURITY_LOG_FILE = "security-log-file";
|
||||
protected static final String SECURITY_LOG_LEVEL = "security-log-level";
|
||||
protected static final String SECURITY_PEER_AUTH_INIT = "security-peer-auth-init";
|
||||
protected static final String SECURITY_PEER_AUTHENTICATOR = "security-peer-authenticator";
|
||||
protected static final String SECURITY_PEER_VERIFY_MEMBER_TIMEOUT = "security-peer-verifymember-timeout";
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
protected Class getAnnotationType() {
|
||||
@@ -51,32 +63,32 @@ public class AuthConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
PropertiesBuilder gemfireProperties = PropertiesBuilder.create();
|
||||
|
||||
gemfireProperties.setProperty("gemfireSecurityPropertyFile", annotationAttributes.get("securityPropertiesFile"));
|
||||
gemfireProperties.setProperty(GEMFIRE_SECURITY_PROPERTY_FILE, annotationAttributes.get("securityPropertiesFile"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-accessor", annotationAttributes.get("clientAccessor"));
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_ACCESSOR, annotationAttributes.get("clientAccessor"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-accessor-pp",
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_ACCESSOR_POST_PROCESSOR,
|
||||
annotationAttributes.get("clientAccessPostOperation"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-auth-init",
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_AUTH_INIT,
|
||||
annotationAttributes.get("clientAuthenticationInitializer"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-authenticator", annotationAttributes.get("clientAuthenticator"));
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_AUTHENTICATOR, annotationAttributes.get("clientAuthenticator"));
|
||||
|
||||
gemfireProperties.setProperty("security-client-dhalgo",
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_DIFFIE_HELLMAN_ALGORITHM,
|
||||
annotationAttributes.get("clientDiffieHellmanAlgorithm"));
|
||||
|
||||
gemfireProperties.setProperty("security-peer-auth-init",
|
||||
gemfireProperties.setProperty(SECURITY_PEER_AUTH_INIT,
|
||||
annotationAttributes.get("peerAuthenticationInitializer"));
|
||||
|
||||
gemfireProperties.setProperty("security-peer-authenticator", annotationAttributes.get("peerAuthenticator"));
|
||||
gemfireProperties.setProperty(SECURITY_PEER_AUTHENTICATOR, annotationAttributes.get("peerAuthenticator"));
|
||||
|
||||
gemfireProperties.setPropertyIfNotDefault("security-peer-verifymember-timeout",
|
||||
gemfireProperties.setPropertyIfNotDefault(SECURITY_PEER_VERIFY_MEMBER_TIMEOUT,
|
||||
annotationAttributes.get("peerVerifyMemberTimeout"), DEFAULT_PEER_VERIFY_MEMBER_TIMEOUT);
|
||||
|
||||
gemfireProperties.setProperty("security-log-file", annotationAttributes.get("securityLogFile"));
|
||||
gemfireProperties.setProperty(SECURITY_LOG_FILE, annotationAttributes.get("securityLogFile"));
|
||||
|
||||
gemfireProperties.setPropertyIfNotDefault("security-log-level",
|
||||
gemfireProperties.setPropertyIfNotDefault(SECURITY_LOG_LEVEL,
|
||||
annotationAttributes.get("securityLogLevel"), DEFAULT_SECURITY_LOG_LEVEL);
|
||||
|
||||
return gemfireProperties.build();
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.apache.geode.security.AuthInitialize;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The {@link EnableSecurity} annotation marks a Spring {@link org.springframework.context.annotation.Configuration}
|
||||
* annotated class to configure and enable Apache Geode's Security features for authentication, authorization
|
||||
* and post processing.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see GeodeIntegratedSecurityConfiguration
|
||||
* @see org.apache.geode.security.AuthInitialize
|
||||
* @see org.apache.geode.security.SecurityManager
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import({ ApacheShiroSecurityConfiguration.class, GeodeIntegratedSecurityConfiguration.class })
|
||||
@SuppressWarnings("unused")
|
||||
public @interface EnableSecurity {
|
||||
|
||||
/**
|
||||
* Used for authentication. Static creation method returning an {@link AuthInitialize} object,
|
||||
* which obtains credentials for clients.
|
||||
*
|
||||
* Defaults to unset.
|
||||
*/
|
||||
String clientAuthenticationInitializer() default "";
|
||||
|
||||
/**
|
||||
* Used with authentication. Static creation method returning an {@link AuthInitialize} object, which obtains
|
||||
* credentials for peers in a distributed system.
|
||||
*
|
||||
* Defaults to unset.
|
||||
*/
|
||||
String peerAuthenticationInitializer() default "";
|
||||
|
||||
/**
|
||||
* Specifies the application {@link Class} type implementing the Apache Geode
|
||||
* {@link org.apache.geode.security.SecurityManager} interface to enable security in Apache Geode.
|
||||
*
|
||||
* Defaults to {@link Void}.
|
||||
*/
|
||||
Class<?> securityManagerClass() default Void.class;
|
||||
|
||||
/**
|
||||
* Specifies the fully-qualified class name of the application {@link Class} implementing the Apache Geode
|
||||
* {@link org.apache.geode.security.SecurityManager} interface to enable security in Apache Geode.
|
||||
*
|
||||
* Use this Annotation attribute if you are uncertain whether the application class is on the classpath or not.
|
||||
*
|
||||
* Default is unset.
|
||||
*/
|
||||
String securityManagerClassName() default "";
|
||||
|
||||
/**
|
||||
* Specifies the application {@link Class} type implementing the Apache Geode
|
||||
* {@link org.apache.geode.security.PostProcessor} interface, which used to transform sensitive data
|
||||
* returned from secure data access operations.
|
||||
*
|
||||
* Defaults to {@link Void}.
|
||||
*/
|
||||
Class<?> securityPostProcessorClass() default Void.class;
|
||||
|
||||
/**
|
||||
* Specifies the fully-qualified class name of the application {@link Class} implementing the Apache Geode
|
||||
* {@link org.apache.geode.security.PostProcessor} interface, which used to transform sensitive data
|
||||
* returned from secure data access operations.
|
||||
*
|
||||
* Use this Annotation attribute if you are uncertain whether the application class is on the classpath or not.
|
||||
*
|
||||
* Default is unset.
|
||||
*/
|
||||
String securityPostProcessorClassName() default "";
|
||||
|
||||
/**
|
||||
* Sets the Geode System Property referring to the location of an Apache Shiro INI file used to configure
|
||||
* the Apache Shiro Security Framework to secure Apache Geode.
|
||||
*
|
||||
* Default is unset.
|
||||
*/
|
||||
String shiroIniResourcePath() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.data.gemfire.config.annotation;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
|
||||
import org.springframework.data.gemfire.util.PropertiesBuilder;
|
||||
|
||||
/**
|
||||
* The {@link GeodeIntegratedSecurityConfiguration} class is a {@link EmbeddedServiceConfigurationSupport} implementation
|
||||
* that enables Apache Geode's Integrated Security framework and services.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class GeodeIntegratedSecurityConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
|
||||
protected static final String SECURITY_CLIENT_AUTH_INIT = "security-client-auth-init";
|
||||
protected static final String SECURITY_PEER_AUTH_INIT = "security-peer-auth-init";
|
||||
protected static final String SECURITY_MANAGER = "security-manager";
|
||||
protected static final String SECURITY_POST_PROCESSOR = "security-post-processor";
|
||||
protected static final String SECURITY_SHIRO_INIT = "security-shiro-init";
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected Class getAnnotationType() {
|
||||
return EnableSecurity.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isShiroSecurityConfigured() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected boolean isShiroSecurityNotConfigured() {
|
||||
return !isShiroSecurityConfigured();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
PropertiesBuilder gemfireProperties = new PropertiesBuilder();
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_CLIENT_AUTH_INIT,
|
||||
annotationAttributes.get("clientAuthenticationInitializer"));
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_PEER_AUTH_INIT,
|
||||
annotationAttributes.get("peerAuthenticationInitializer"));
|
||||
|
||||
if (isShiroSecurityNotConfigured()) {
|
||||
gemfireProperties.setPropertyIfNotDefault(SECURITY_MANAGER,
|
||||
annotationAttributes.get("securityManagerClass"), Void.class);
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_MANAGER, annotationAttributes.get("securityManagerClassName"));
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_SHIRO_INIT, annotationAttributes.get("shiroIniResourcePath"));
|
||||
}
|
||||
|
||||
gemfireProperties.setPropertyIfNotDefault(SECURITY_POST_PROCESSOR,
|
||||
annotationAttributes.get("securityPostProcessorClass"), Void.class);
|
||||
|
||||
gemfireProperties.setProperty(SECURITY_POST_PROCESSOR,
|
||||
annotationAttributes.get("securityPostProcessorClassName"));
|
||||
|
||||
return gemfireProperties.build();
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,8 @@ public class PdxDiskStoreAwareBeanFactoryPostProcessor implements BeanFactoryPos
|
||||
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanNamesForType(Class)
|
||||
*/
|
||||
private void postProcessPdxDiskStoreDependencies(ConfigurableListableBeanFactory beanFactory,
|
||||
final Class<?>... beanTypes) {
|
||||
Class<?>... beanTypes) {
|
||||
|
||||
for (Class<?> beanType : beanTypes) {
|
||||
for (String beanName : beanFactory.getBeanNamesForType(beanType)) {
|
||||
if (!beanName.equalsIgnoreCase(getPdxDiskStoreName())) {
|
||||
|
||||
@@ -32,6 +32,7 @@ public abstract class ArrayUtils {
|
||||
* @param elements variable list of arguments to return as an array.
|
||||
* @return an arry for the given varargs {@code elements}.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <T> T[] asArray(T... elements) {
|
||||
return elements;
|
||||
}
|
||||
@@ -45,7 +46,7 @@ public abstract class ArrayUtils {
|
||||
* @return the first element in the array or {@literal null} if the array is null or empty.
|
||||
* @see #getFirst(Object[], Object)
|
||||
*/
|
||||
public static <T> T getFirst(T... array) {
|
||||
public static <T> T getFirst(T[] array) {
|
||||
return getFirst(array, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ public class GemfireTemplateIntegrationTests {
|
||||
public void get() {
|
||||
String key = getKey(getUser("imaPigg"));
|
||||
|
||||
assertThat(usersTemplate.get(key)).isEqualTo(users.get(key));
|
||||
assertThat(usersTemplate.<Object, Object>get(key)).isEqualTo(users.get(key));
|
||||
assertNullEquals(users.get("mrT"), usersTemplate.get("mrT"));
|
||||
}
|
||||
|
||||
@@ -233,11 +233,11 @@ public class GemfireTemplateIntegrationTests {
|
||||
User mandyHandy = users.get(getKey(getUser("mandyHandy")));
|
||||
|
||||
assertThat(mandyHandy).isNotNull();
|
||||
assertThat(usersTemplate.remove(getKey(mandyHandy))).isEqualTo(mandyHandy);
|
||||
assertThat(usersTemplate.<Object, Object>remove(getKey(mandyHandy))).isEqualTo(mandyHandy);
|
||||
assertThat(users.containsKey(getKey(mandyHandy))).isFalse();
|
||||
assertThat(users.containsValue(mandyHandy)).isFalse();
|
||||
assertThat(users.containsKey("loisGriffon")).isFalse();
|
||||
assertThat(usersTemplate.remove("loisGriffon")).isNull();
|
||||
assertThat(usersTemplate.<Object, Object>remove("loisGriffon")).isNull();
|
||||
assertThat(users.containsKey("loisGriffon")).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ public class GemfireTemplateUnitTests extends AbstractUnitAndIntegrationTestsWit
|
||||
when(mockQuery.execute(eq(expectedParams))).thenReturn(mockSelectResults);
|
||||
when(mockSelectResults.asList()).thenReturn(Collections.singletonList(1));
|
||||
|
||||
assertThat(template.findUnique(expectedQuery, expectedParams)).isEqualTo(1);
|
||||
assertThat((Object) template.findUnique(expectedQuery, expectedParams)).isEqualTo(1);
|
||||
|
||||
verify(mockRegion, atLeastOnce()).getRegionService();
|
||||
verify(mockRegionService, times(1)).getQueryService();
|
||||
@@ -227,7 +227,7 @@ public class GemfireTemplateUnitTests extends AbstractUnitAndIntegrationTestsWit
|
||||
|
||||
when(mockQuery.execute(eq(expectedParams))).thenReturn("test");
|
||||
|
||||
assertThat(template.findUnique(expectedQuery, expectedParams)).isEqualTo("test");
|
||||
assertThat((Object) template.findUnique(expectedQuery, expectedParams)).isEqualTo("test");
|
||||
|
||||
verify(mockRegion, atLeastOnce()).getRegionService();
|
||||
verify(mockRegionService, times(1)).getQueryService();
|
||||
@@ -246,7 +246,7 @@ public class GemfireTemplateUnitTests extends AbstractUnitAndIntegrationTestsWit
|
||||
when(mockSelectResults.asList()).thenReturn(Arrays.asList(1, 2));
|
||||
|
||||
try {
|
||||
assertThat(template.findUnique(expectedQuery, expectedParams)).isEqualTo(1);
|
||||
assertThat((Object) template.findUnique(expectedQuery, expectedParams)).isEqualTo(1);
|
||||
}
|
||||
finally {
|
||||
verify(mockRegion, atLeastOnce()).getRegionService();
|
||||
|
||||
@@ -201,8 +201,8 @@ public class AbstractCacheConfigurationUnitTests {
|
||||
MappingPdxSerializer pdxSerializer = cacheConfiguration.newPdxSerializer();
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat(invokeMethod(pdxSerializer, "getConversionService")).isEqualTo(mockConversionService);
|
||||
assertThat(invokeMethod(pdxSerializer, "getMappingContext")).isEqualTo(mockMappingContext);
|
||||
assertThat((Object) invokeMethod(pdxSerializer, "getConversionService")).isEqualTo(mockConversionService);
|
||||
assertThat((Object) invokeMethod(pdxSerializer, "getMappingContext")).isEqualTo(mockMappingContext);
|
||||
|
||||
verify(mockBeanFactory, times(1)).getConversionService();
|
||||
verifyZeroInteractions(mockConversionService);
|
||||
@@ -216,8 +216,8 @@ public class AbstractCacheConfigurationUnitTests {
|
||||
MappingPdxSerializer pdxSerializer = cacheConfiguration.newPdxSerializer();
|
||||
|
||||
assertThat(pdxSerializer).isNotNull();
|
||||
assertThat(invokeMethod(pdxSerializer, "getConversionService")).isInstanceOf(ConversionService.class);
|
||||
assertThat(invokeMethod(pdxSerializer, "getMappingContext")).isInstanceOf(GemfireMappingContext.class);
|
||||
assertThat((Object) invokeMethod(pdxSerializer, "getConversionService")).isInstanceOf(ConversionService.class);
|
||||
assertThat((Object) invokeMethod(pdxSerializer, "getMappingContext")).isInstanceOf(GemfireMappingContext.class);
|
||||
}
|
||||
|
||||
protected static class TestCacheConfiguration extends AbstractCacheConfiguration {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.config.xml;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -114,11 +115,11 @@ public class GemfireV7GatewayNamespaceTest extends RecreatingSpringApplicationCo
|
||||
|
||||
assertNotNull(gatewaySenderFactoryBean);
|
||||
assertNotNull(TestUtils.readField("cache", gatewaySenderFactoryBean));
|
||||
assertEquals(2, TestUtils.readField("remoteDistributedSystemId", gatewaySenderFactoryBean));
|
||||
assertEquals(10, TestUtils.readField("alertThreshold", gatewaySenderFactoryBean));
|
||||
assertThat((Object) TestUtils.readField("remoteDistributedSystemId", gatewaySenderFactoryBean)).isEqualTo(2);
|
||||
assertThat((Object) TestUtils.readField("alertThreshold", gatewaySenderFactoryBean)).isEqualTo(10);
|
||||
assertTrue(Boolean.TRUE.equals(TestUtils.readField("batchConflationEnabled", gatewaySenderFactoryBean)));
|
||||
assertEquals(11, TestUtils.readField("batchSize", gatewaySenderFactoryBean));
|
||||
assertEquals(12, TestUtils.readField("dispatcherThreads", gatewaySenderFactoryBean));
|
||||
assertThat((Object) TestUtils.readField("batchSize", gatewaySenderFactoryBean)).isEqualTo(11);
|
||||
assertThat((Object) TestUtils.readField("dispatcherThreads", gatewaySenderFactoryBean)).isEqualTo(12);
|
||||
assertEquals(false, TestUtils.readField("diskSynchronous", gatewaySenderFactoryBean));
|
||||
assertEquals(true, TestUtils.readField("manualStart", gatewaySenderFactoryBean));
|
||||
|
||||
@@ -190,10 +191,10 @@ public class GemfireV7GatewayNamespaceTest extends RecreatingSpringApplicationCo
|
||||
|
||||
assertNotNull(gatewaySenderFactoryBean);
|
||||
assertNotNull(TestUtils.readField("cache", gatewaySenderFactoryBean));
|
||||
assertEquals(3, TestUtils.readField("remoteDistributedSystemId", gatewaySenderFactoryBean));
|
||||
assertThat((Integer) TestUtils.readField("remoteDistributedSystemId", gatewaySenderFactoryBean)).isEqualTo(3);
|
||||
assertTrue(Boolean.TRUE.equals(TestUtils.readField("batchConflationEnabled", gatewaySenderFactoryBean)));
|
||||
assertEquals(50, TestUtils.readField("batchSize", gatewaySenderFactoryBean));
|
||||
assertEquals(10, TestUtils.readField("dispatcherThreads", gatewaySenderFactoryBean));
|
||||
assertThat((Object) TestUtils.readField("batchSize", gatewaySenderFactoryBean)).isEqualTo(50);
|
||||
assertThat((Object) TestUtils.readField("dispatcherThreads", gatewaySenderFactoryBean)).isEqualTo(10);
|
||||
assertEquals(true, TestUtils.readField("manualStart", gatewaySenderFactoryBean));
|
||||
|
||||
List<GatewayEventFilter> eventFilters = TestUtils.readField("eventFilters", gatewaySenderFactoryBean);
|
||||
|
||||
@@ -16,13 +16,9 @@
|
||||
|
||||
package org.springframework.data.gemfire.function.execution;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.isA;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.isA;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -95,8 +91,8 @@ public class AbstractFunctionExecutionTest {
|
||||
Iterable<Object> actualResults = functionExecution.setFunction(mockFunction)
|
||||
.setArgs(args).setTimeout(500).execute();
|
||||
|
||||
assertThat(actualResults, is(notNullValue()));
|
||||
assertThat(actualResults, is(equalTo((Iterable<Object>) results)));
|
||||
assertThat(actualResults).isNotNull();
|
||||
assertThat(actualResults).isEqualTo((Iterable<Object>) results);
|
||||
|
||||
verify(mockExecution, times(1)).withArgs(eq(args));
|
||||
verify(mockExecution, never()).withCollector(any(ResultCollector.class));
|
||||
@@ -122,7 +118,7 @@ public class AbstractFunctionExecutionTest {
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(String.valueOf(functionExecution.executeAndExtract()), is(equalTo("test")));
|
||||
assertThat(functionExecution.<String>executeAndExtract()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -140,7 +136,7 @@ public class AbstractFunctionExecutionTest {
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(String.valueOf(functionExecution.executeAndExtract()), is(equalTo("one")));
|
||||
assertThat(functionExecution.<String>executeAndExtract()).isEqualTo("one");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -156,7 +152,7 @@ public class AbstractFunctionExecutionTest {
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(functionExecution.executeAndExtract(), is(nullValue()));
|
||||
assertThat((Object) functionExecution.executeAndExtract()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -172,7 +168,7 @@ public class AbstractFunctionExecutionTest {
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(functionExecution.executeAndExtract(), is(nullValue()));
|
||||
assertThat((Object) functionExecution.executeAndExtract()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -194,5 +190,4 @@ public class AbstractFunctionExecutionTest {
|
||||
|
||||
functionExecution.setFunctionId("TestFunction").executeAndExtract();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -143,9 +143,9 @@ public class SimpleGemfireRepositoryIntegrationTests {
|
||||
repository.save(Arrays.asList(johnBlum, jonBloom, juanBlume));
|
||||
|
||||
assertThat(template.getRegion().size()).isEqualTo(3);
|
||||
assertThat(template.get(johnBlum.getId())).isEqualTo(johnBlum);
|
||||
assertThat(template.get(jonBloom.getId())).isEqualTo(jonBloom);
|
||||
assertThat(template.get(juanBlume.getId())).isEqualTo(juanBlume);
|
||||
assertThat(template.<Long, Person>get(johnBlum.getId())).isEqualTo(johnBlum);
|
||||
assertThat(template.<Long, Person>get(jonBloom.getId())).isEqualTo(jonBloom);
|
||||
assertThat(template.<Long, Person>get(juanBlume.getId())).isEqualTo(juanBlume);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
||||
@@ -60,13 +60,13 @@ public class ArrayUtilsUnitTests {
|
||||
|
||||
@Test
|
||||
public void getFirstWithNonNullArray() {
|
||||
assertThat(ArrayUtils.getFirst(1, 2, 3)).isEqualTo(1);
|
||||
assertThat(ArrayUtils.getFirst(ArrayUtils.asArray(1, 2, 3))).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFirstWithNullOrEmptyArrayAndNoDefaultReturnsNull() {
|
||||
assertThat(ArrayUtils.getFirst((Object[]) null)).isNull();
|
||||
assertThat(ArrayUtils.getFirst()).isNull();
|
||||
assertThat((Object) ArrayUtils.getFirst(null)).isNull();
|
||||
assertThat((Object) ArrayUtils.getFirst(new Object[0])).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -3,8 +3,10 @@ Bundle-Name: Spring Data Geode
|
||||
Bundle-SymbolicName: org.springframework.data.gemfire
|
||||
Bundle-Vendor: Pivotal Software, Inc.
|
||||
Import-Package: sun.reflect;version="0";resolution:=optional
|
||||
Import-Template: javax.enterprise.*;version="[1.0,2.0)";resolution:=optional,
|
||||
Import-Template: javax.annotation.*;version="[1.0,2.0)";resolution:=optional,
|
||||
javax.enterprise.*;version="[1.0,2.0)";resolution:=optional,
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.apache.shiro.*;version="[1.3.0, 2.0.0)";resolutioin:=optional,
|
||||
org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional,
|
||||
org.aspectj.*;version="[1.8.2, 2.0.0)";resolution:=optional,
|
||||
com.fasterxml.jackson.*;version="[2.4.1,3.0.0)";resolution:=optional,
|
||||
|
||||
Reference in New Issue
Block a user