Java 如何使用Configuration Admin为同一类创建多个配置?
我正在开发一个实体组件系统游戏引擎,它将利用OSGi框架。 我希望用户/开发人员能够以模块化的方式创建自己的组件类型,类似于Bethesda创建工具包 我考虑的方法是创建一个表示组件类型的类,然后使用Configuration Admin创建配置,但我不确定我的理解是否正确 我有一个类要用作组件类型Java 如何使用Configuration Admin为同一类创建多个配置?,java,osgi,Java,Osgi,我正在开发一个实体组件系统游戏引擎,它将利用OSGi框架。 我希望用户/开发人员能够以模块化的方式创建自己的组件类型,类似于Bethesda创建工具包 我考虑的方法是创建一个表示组件类型的类,然后使用Configuration Admin创建配置,但我不确定我的理解是否正确 我有一个类要用作组件类型 @Component( configurationPid = "Species", configurationPolicy = ConfigurationPolicy.REQUIR
@Component(
configurationPid = "Species",
configurationPolicy = ConfigurationPolicy.REQUIRE,
service = Species.class
)
public final class Species {
// ...
}
为了测试这一点,我为ApacheGogo创建了一个命令来创建一个Species
。我的想法是,我应该能够用这个命令创建多个物种
@Component(
property = {
CommandProcessor.COMMAND_SCOPE + "=species",
CommandProcessor.COMMAND_FUNCTION + "=create"
},
service = CreateSpeciesCommand.class
)
public class CreateSpeciesCommand {
/* L1 */
@Reference(bind = "bindConfigurationAdmin")
private ConfigurationAdmin configurationAdmin;
@Descriptor("creates a species")
public void create(@Descriptor("id of the species") final String speciesId) throws IOException, InvalidSyntaxException {
final String filter = String.format("(%s=%s)", Constants.OBJECTCLASS, Species.class.getSimpleName());
final Configuration[] existingConfigurations = configurationAdmin.listConfigurations(filter);
System.out.println(Arrays.toString(existingConfigurations));
final Configuration speciesConfiguration = configurationAdmin.getConfiguration(Species.class.getSimpleName(), "?");
Dictionary<String, Object> configProperties = new Hashtable<>();
configProperties.put(Constants.SERVICE_PID, "Species");
speciesConfiguration.update(configProperties);
}
}
@组件(
属性={
CommandProcessor.COMMAND_SCOPE+“=物种”,
CommandProcessor.COMMAND_函数+“=创建”
},
服务=CreateSpeciesCommand.class
)
公共类CreateSpeciesCommand{
/*L1*/
@参考(bind=“bindConfigurationAdmin”)
私有配置管理员配置管理员;
@描述符(“创建一个物种”)
public void create(@Descriptor(“物种id”)最终字符串speciesId)抛出IOException,InvalidSyntaxException{
最终字符串筛选器=String.format((%s=%s)”,Constants.OBJECTCLASS,Species.class.getSimpleName();
最终配置[]existingConfigurations=configurationAdmin.listConfigurations(过滤器);
System.out.println(Arrays.toString(现有配置));
最终配置speciesConfiguration=configurationAdmin.getConfiguration(Species.class.getSimpleName(),“?”;
Dictionary configProperties=新哈希表();
configProperties.put(Constants.SERVICE_PID,“Species”);
speciesConfiguration.update(配置属性);
}
}
但所发生的一切是它修改了配置,而不是创建一个新的配置
要使用Configuration Admin为同一类创建多个配置,我需要做什么
2018-06-19编辑:
进行以下指定的更改:
- 添加
注释到@specify
类物种
- 将
设置为唯一的名称@Component#name
- 将
设置为@Component#configurationPolicy
configurationPolicy.REQUIRE
- 将
添加到@ObjectClassDefinition
类Species.Config
- 使用
(ConfigurationAdmin#getConfiguration
不存在,只有此和createConfiguration
)并将createFactoryConfiguration
@组件名称作为pid
结果只创建一个配置,并随后续调用进行更新。OSGi configuration Admin有两种不同类型的配置:
- Singleton–具有PID
- Factory–有一个PID(针对工厂实例)和一个针对实例“组”的工厂PID
@Designate( ocd= Species.Config.class, factory=true )
@Component( name = "species.pid", configurationPolicy=ConfigurationPolicy.REQUIRE )
public class Species {
@ObjectClassDefinition
@interface Config {
String id();
}
@Activate
void activate( Config config) {
System.out.println( config.id() );
}
}
现在,命令(扩展为list+delete函数):
@组件(
属性={
CommandProcessor.COMMAND_SCOPE+“=物种”,
CommandProcessor.COMMAND_函数+“=创建”,
CommandProcessor.COMMAND_函数+“=列表”,
CommandProcessor.COMMAND_函数+“=删除”
},
服务=CreateSpeciesCommand.class
)
公共类CreateSpeciesCommand{
@参考文献
配置管理员配置管理员;
公共配置创建(字符串speciesId)引发异常{
配置c=configurationAdmin.createFactoryConfiguration(“species.pid”,“?”);
Hashtable d=新的Hashtable();
d、 put(“id”,speciesId);
c、 更新(d);
返回c;
}
公共配置[]列表()引发异常{
返回configurationAdmin。
列表配置(((service.factoryPid=species.pid)”;
}
公共布尔删除(字符串id)引发异常{
配置[]列表=配置管理员。
列表配置(&(service.factoryPid=species.pid)(id=“+id+”));
if(list==null){
返回false;
}
用于(配置c:列表){
c、 删除();
}
返回true;
}
}
一些注意事项:
- 未编译而编写,因此可能存在一些编译错误
- WebConsole更适合创建和删除物种
- 为了便于阅读,跳过了Gogo注释
- 显然,对“过滤”注入攻击没有防御
- Singleton–具有PID
- Factory–有一个PID(针对工厂实例)和一个针对实例“组”的工厂PID
@Designate( ocd= Species.Config.class, factory=true )
@Component( name = "species.pid", configurationPolicy=ConfigurationPolicy.REQUIRE )
public class Species {
@ObjectClassDefinition
@interface Config {
String id();
}
@Activate
void activate( Config config) {
System.out.println( config.id() );
}
}
现在,命令(扩展为list+delete函数):
@组件(
属性={
CommandProcessor.COMMAND_SCOPE+“=物种”,
CommandProcessor.COMMAND_函数+“=创建”,
CommandProcessor.COMMAND_函数+“=列表”,
CommandProcessor.COMMAND_函数+“=删除”
},
服务=CreateSpeciesCommand.class
)
公共类CreateSpeciesCommand{
@参考文献
配置管理员配置管理员;
公共配置创建(字符串speciesId)引发异常{
配置c=configurationAdmin.createFactoryConfiguration(“species.pid”,“?”);
Hashtable d=新的Hashtable();
d、 put(“id”,speciesId);
c、 更新(d);
返回c;
}
公共配置[]列表()引发异常{
返回configurationAdmin。
列表配置(((service.factoryPid=species.pid)”;
}
公共布尔删除(字符串id)引发异常{
配置[]列表=配置管理员。
列表配置(&(service.factoryPid=species.pid)(id=“+id+”));
if(list==null){
返回false;
}
对于(配置c:
package net.zephyrion.hummingbird.module.species;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import java.util.Objects;
@Component(
factory = "Species",
configurationPolicy = ConfigurationPolicy.REQUIRE,
service = Species.class
)
public final class Species {
@interface Config {
String id() default "";
}
private Config config;
@Activate
public void configure(final Config config) {
this.config = Objects.requireNonNull(config);
}
private String getId() {
return config.id();
}
}
package net.zephyrion.hummingbird.module.species;
import org.apache.felix.service.command.CommandProcessor;
import org.apache.felix.service.command.Descriptor;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
@Component(
property = {
CommandProcessor.COMMAND_SCOPE + "=species",
CommandProcessor.COMMAND_FUNCTION + "=create"
},
service = CreateSpeciesCommand.class
)
public class CreateSpeciesCommand {
/* L1 */
@Reference(bind = "bindConfigurationAdmin")
private ConfigurationAdmin configurationAdmin;
@Descriptor("creates a species")
public void create(@Descriptor("id of the species") final String speciesId) throws IOException {
try {
final String factoryPid = Species.class.getSimpleName();
final String filter = String.format("(&(id=%s)(service.factoryPid=%s))", speciesId, factoryPid);
final boolean configurationExists = configurationAdmin.listConfigurations(filter) != null;
if (!configurationExists) {
final Configuration speciesConfiguration = configurationAdmin.createFactoryConfiguration(factoryPid, "?");
Dictionary<String, Object> configProperties = new Hashtable<>();
configProperties.put("id", speciesId);
speciesConfiguration.update(configProperties);
}
}
catch (InvalidSyntaxException e) {
e.printStackTrace();
}
}
/* L2 */
private void bindConfigurationAdmin(final ConfigurationAdmin configurationAdmin) {
// TODO Obj.rnn
this.configurationAdmin = configurationAdmin;
}
}