[英]How do I create multiple configurations for the same class with Configuration Admin?
我正在研究将利用OSGi框架的实体组件系统游戏引擎。 我希望用户/开发人员能够以模块化方式创建自己的组件类型,类似于Bethesda Creation Kit。
我考虑过的方法是创建一个代表组件类型的类,然后使用Configuration Admin创建配置,但是我不确定我的理解是否正确。
我有一个要用作组件类型的类
@Component(
configurationPid = "Species",
configurationPolicy = ConfigurationPolicy.REQUIRE,
service = Species.class
)
public final class Species {
// ...
}
为了测试这一点,我为Apache Gogo创建了一个创建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);
}
}
但是所有发生的事情是它修改了配置,而不是创建一个新的配置。
使用Configuration Admin为同一类创建多个配置时,我需要做什么?
2018-06-19编辑:
进行由Peter Kriens的答案指定的更改:
@Designate
注释添加到Species
类 @Component#name
设置为唯一的@Component#name
@Component#configurationPolicy
设置为ConfigurationPolicy.REQUIRE
@ObjectClassDefinition
添加到Species.Config
类 @Component#name
作为pid的ConfigurationAdmin#getConfiguration
( createConfiguration
不存在,仅此和createFactoryConfiguration
) 导致仅创建一个配置,该配置将通过后续调用进行更新。
OSGi Configuration Admin具有2种不同类型的配置:
因此,在OSGi> = 6中,您可以执行以下操作:
@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函数扩展):
@Component(
property = {
CommandProcessor.COMMAND_SCOPE + "=species",
CommandProcessor.COMMAND_FUNCTION + "=create",
CommandProcessor.COMMAND_FUNCTION + "=list",
CommandProcessor.COMMAND_FUNCTION + "=delete"
},
service = CreateSpeciesCommand.class
)
public class CreateSpeciesCommand {
@Reference
ConfigurationAdmin configurationAdmin;
public Configuration create(String speciesId) throws Exception {
Configuration c = configurationAdmin.createFactoryConfiguration( "species.pid", "?");
Hashtable<String,Object> d = new Hashtable();
d.put("id", speciesId);
c.update( d );
return c;
}
public Configuration[] list() throws Exception {
return configurationAdmin.
listConfigurations( "(service.factoryPid=species.pid)");
}
public boolean delete(String id) throws Exception {
Configuration[] list = configurationAdmin.
listConfigurations( "(&(service.factoryPid=species.pid)(id="+id+"))");
if ( list == null) {
return false;
}
for ( Configuration c : list ) {
c.delete();
}
return true;
}
}
一些注意事项:
为了获得每个呼叫的新配置,我需要更改以下内容:
Species
类的@Component#factory
值设置为唯一的值 ConfigurationAdmin#createFactoryConfiguration
方法而不是getConfiguration
方法 我尝试应用Peter Kriens的答案指定的更改:
@Designate
注释添加到Species
类 @Component#name
设置为唯一的@Component#name
@Component#configurationPolicy
设置为ConfigurationPolicy.REQUIRE
@ObjectClassDefinition
添加到Species.Config
类 @Component#name
作为pid的ConfigurationAdmin#getConfiguration
( createConfiguration
不存在,只有this和createFactoryConfiguration
); createFactoryConfiguration
使用@Component#factory
这不仅可以进行新的配置,还可以同时激活物种成分。 不知道为什么会这样,但我正在调查中。
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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.