簡體   English   中英

如何使用Configuration Admin為同一類創建多個配置?

[英]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#getConfigurationcreateConfiguration不存在,僅此和createFactoryConfiguration

導致僅創建一個配置,該配置將通過后續調用進行更新。

OSGi Configuration Admin具有2種不同類型的配置:

  • 單例–具有PID
  • 工廠–有一個PID(用於工廠實例)和一個工廠PID用於“實例”組。

因此,在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;
   }
}

一些注意事項:

  • 編寫時未進行編譯,因此可能存在一些編譯錯誤
  • WebConsole可以更好地創建和刪除種類
  • 跳過Gogo注釋以提高可讀性
  • 顯然沒有對“過濾器”注入攻擊的防御

為了獲得每個呼叫的新配置,我需要更改以下內容:

  • 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#getConfigurationcreateConfiguration不存在,只有this和createFactoryConfiguration ); createFactoryConfiguration使用@Component#factory

這不僅可以進行新的配置,還可以同時激活物種成分。 不知道為什么會這樣,但我正在調查中。

更新的代碼

Species.java

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();
    }
}

CreateSpeciesCommand.java

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM