[Major] Strolch agent is now fully realm capable

ResourceMap and OrderMap are kept in a StrolchRealm object for each
realm which is configured. This is transparent for the user. When no
realms are defined then the 'defaultRealm' is configured where all
methods without a realm parameter use this realm.

Once a realm is configured, the defaultRealm must be configured if it 
is still to be used at runtime.

Tests make sure realms work, for both transient, and empty situations.
Cached agent mode is next to be implemented
This commit is contained in:
Robert von Burg 2013-12-23 20:28:49 +01:00
parent 0254a74d16
commit 2686e3d7bf
13 changed files with 313 additions and 42 deletions

View File

@ -0,0 +1,71 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* 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 li.strolch.runtime.agent;
import java.text.MessageFormat;
import java.util.Map;
import li.strolch.exception.StrolchException;
import li.strolch.model.query.StrolchQuery;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public abstract class AbstractElementMapHandler extends StrolchComponent implements ElementMapHandler {
protected Map<String, StrolchRealm> realms;
/**
* @param container
* @param componentName
*/
public AbstractElementMapHandler(ComponentContainerImpl container, String componentName) {
super(container, componentName);
}
@Override
public ResourceMap getResourceMap() {
return getResourceMap(StrolchQuery.DEFAULT_REALM);
}
@Override
public ResourceMap getResourceMap(String realm) {
StrolchRealm strolchRealm = getRealm(realm);
return strolchRealm.getResourceMap();
}
@Override
public OrderMap getOrderMap() {
return getOrderMap(StrolchQuery.DEFAULT_REALM);
}
@Override
public OrderMap getOrderMap(String realm) {
StrolchRealm strolchRealm = getRealm(realm);
return strolchRealm.getOrderMap();
}
private StrolchRealm getRealm(String realm) {
assertContainerStarted();
StrolchRealm strolchRealm = this.realms.get(realm);
if (strolchRealm == null) {
String msg = "No realm is configured with the name {0}"; //$NON-NLS-1$
msg = MessageFormat.format(msg, realm);
throw new StrolchException(msg);
}
return strolchRealm;
}
}

View File

@ -21,6 +21,10 @@ package li.strolch.runtime.agent;
public interface ElementMapHandler {
public ResourceMap getResourceMap();
public ResourceMap getResourceMap(String realm);
public OrderMap getOrderMap();
public OrderMap getOrderMap(String realm);
}

View File

@ -15,8 +15,6 @@
*/
package li.strolch.runtime.agent;
import li.strolch.runtime.configuration.ComponentConfiguration;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -29,11 +27,4 @@ public class EmptyElementMapHandler extends InMemoryElementMapHandler {
public EmptyElementMapHandler(ComponentContainerImpl container, String componentName) {
super(container, componentName);
}
@Override
public void initialize(ComponentConfiguration configuration) {
this.resourceMap = new InMemoryResourceMap();
this.orderMap = new InMemoryOrderMap();
super.initialize(configuration);
}
}

View File

@ -15,15 +15,16 @@
*/
package li.strolch.runtime.agent;
import java.util.HashMap;
import li.strolch.model.query.StrolchQuery;
import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.configuration.RuntimeConfiguration;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*
*/
public abstract class InMemoryElementMapHandler extends StrolchComponent implements ElementMapHandler {
protected ResourceMap resourceMap;
protected OrderMap orderMap;
public class InMemoryElementMapHandler extends AbstractElementMapHandler {
/**
* @param container
@ -33,21 +34,20 @@ public abstract class InMemoryElementMapHandler extends StrolchComponent impleme
super(container, componentName);
}
/**
* @return the resourceMap
*/
@Override
public ResourceMap getResourceMap() {
assertContainerStarted();
return this.resourceMap;
}
public void initialize(ComponentConfiguration configuration) {
/**
* @return the orderMap
*/
@Override
public OrderMap getOrderMap() {
assertContainerStarted();
return this.orderMap;
RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration();
String[] realms = runtimeConfiguration.getStringArray(StrolchAgent.PROP_REALMS, StrolchQuery.DEFAULT_REALM);
this.realms = new HashMap<>();
for (String realm : realms) {
InMemoryResourceMap resourceMap = new InMemoryResourceMap();
InMemoryOrderMap orderMap = new InMemoryOrderMap();
StrolchRealm strolchRealm = new StrolchRealm(realm, resourceMap, orderMap);
this.realms.put(realm, strolchRealm);
}
super.initialize(configuration);
}
}

View File

@ -33,6 +33,7 @@ public class StrolchAgent {
public static final String PROP_DATA_STORE_MODE = "dataStoreMode"; //$NON-NLS-1$
public static final String PROP_DATA_STORE_FILE = "dataStoreFile"; //$NON-NLS-1$
public static final String PROP_REALMS = "realms"; //$NON-NLS-1$
private static final Logger logger = LoggerFactory.getLogger(StrolchAgent.class);
private ComponentContainerImpl container;

View File

@ -0,0 +1,57 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* 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 li.strolch.runtime.agent;
import li.strolch.model.query.StrolchQuery;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class StrolchRealm {
public static final String DEFAULT_REALM = StrolchQuery.DEFAULT_REALM;
private String realm;
private ResourceMap resourceMap;
private OrderMap orderMap;
public StrolchRealm(String realm, ResourceMap resourceMap, OrderMap orderMap) {
this.realm = realm;
this.resourceMap = resourceMap;
this.orderMap = orderMap;
}
/**
* @return the realm
*/
public String getRealm() {
return this.realm;
}
/**
* @return the resourceMap
*/
public ResourceMap getResourceMap() {
return this.resourceMap;
}
/**
* @return the orderMap
*/
public OrderMap getOrderMap() {
return this.orderMap;
}
}

View File

@ -17,11 +17,14 @@ package li.strolch.runtime.agent;
import java.io.File;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import li.strolch.model.xml.XmlModelDefaultHandler.XmlModelStatistics;
import li.strolch.model.xml.XmlModelFileHandler;
import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.configuration.RuntimeConfiguration;
import li.strolch.runtime.configuration.StrolchConfigurationException;
import ch.eitchnet.utils.helper.StringHelper;
/**
@ -29,7 +32,7 @@ import ch.eitchnet.utils.helper.StringHelper;
*/
public class TransientElementMapHandler extends InMemoryElementMapHandler {
private File modelFile;
private Map<String, File> realmModelFiles;
/**
* @param container
@ -41,29 +44,52 @@ public class TransientElementMapHandler extends InMemoryElementMapHandler {
@Override
public void initialize(ComponentConfiguration configuration) {
super.initialize(configuration);
this.realmModelFiles = new HashMap<>();
RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration();
File modelFile = runtimeConfiguration.getDataFile(StrolchAgent.PROP_DATA_STORE_FILE, null,
runtimeConfiguration, true);
this.modelFile = modelFile;
for (String realm : this.realms.keySet()) {
String key = getDataStoreFilePropKey(realm);
this.resourceMap = new InMemoryResourceMap();
this.orderMap = new InMemoryOrderMap();
if (!runtimeConfiguration.hasProperty(key)) {
String msg = "There is no data store file for realm {0}. Set a property with key {1}"; //$NON-NLS-1$
msg = MessageFormat.format(msg, realm, key);
throw new StrolchConfigurationException(msg);
}
File modelFile = runtimeConfiguration.getDataFile(key, null, runtimeConfiguration, true);
this.realmModelFiles.put(realm, modelFile);
}
super.initialize(configuration);
}
private String getDataStoreFilePropKey(String realm) {
if (realm.equals(StrolchRealm.DEFAULT_REALM))
return StrolchAgent.PROP_DATA_STORE_FILE;
return StrolchAgent.PROP_DATA_STORE_FILE + "." + realm; //$NON-NLS-1$
}
@Override
public void start() {
InMemoryElementListener elementListener = new InMemoryElementListener(this.resourceMap, this.orderMap);
XmlModelFileHandler handler = new XmlModelFileHandler(elementListener, this.modelFile);
handler.parseFile();
XmlModelStatistics statistics = handler.getStatistics();
String durationS = StringHelper.formatNanoDuration(statistics.durationNanos);
logger.info(MessageFormat.format("Loading XML Model file {0} took {1}.", this.modelFile.getName(), durationS)); //$NON-NLS-1$
logger.info(MessageFormat.format("Loaded {0} Orders", statistics.nrOfOrders)); //$NON-NLS-1$
logger.info(MessageFormat.format("Loaded {0} Resources", statistics.nrOfResources)); //$NON-NLS-1$
for (String realm : this.realms.keySet()) {
StrolchRealm strolchRealm = this.realms.get(realm);
ResourceMap resourceMap = strolchRealm.getResourceMap();
OrderMap orderMap = strolchRealm.getOrderMap();
File modelFile = this.realmModelFiles.get(realm);
InMemoryElementListener elementListener = new InMemoryElementListener(resourceMap, orderMap);
XmlModelFileHandler handler = new XmlModelFileHandler(elementListener, modelFile);
handler.parseFile();
XmlModelStatistics statistics = handler.getStatistics();
String durationS = StringHelper.formatNanoDuration(statistics.durationNanos);
logger.info(MessageFormat.format(
"Loading XML Model file {0} for realm {1} took {2}.", modelFile.getName(), realm, durationS)); //$NON-NLS-1$
logger.info(MessageFormat.format("Loaded {0} Orders", statistics.nrOfOrders)); //$NON-NLS-1$
logger.info(MessageFormat.format("Loaded {0} Resources", statistics.nrOfResources)); //$NON-NLS-1$
}
super.start();
}

View File

@ -42,10 +42,24 @@ public abstract class AbstractionConfiguration {
return this.name;
}
public boolean hasProperty(String key) {
return this.configurationValues.containsKey(key);
}
public Set<String> getPropertyKeys() {
return new HashSet<>(this.configurationValues.keySet());
}
public String[] getStringArray(String key, String defValue) {
String value = getValue(key, defValue);
String[] values = value.split(","); //$NON-NLS-1$
for (int i = 0; i < values.length; i++) {
values[i] = values[i].trim();
}
return values;
}
public String getString(String key, String defValue) {
return getValue(key, defValue);
}

View File

@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory;
@SuppressWarnings("nls")
public class ComponentContainerTest {
public static final String PATH_REALM_CONTAINER = "src/test/resources/realmtest";
public static final String PATH_TRANSIENT_CONTAINER = "src/test/resources/transienttest";
public static final String PATH_EMPTY_CONTAINER = "src/test/resources/emptytest";
@ -62,6 +63,19 @@ public class ComponentContainerTest {
}
}
@Test
public void shouldStartRealmTestContainer() {
try {
StrolchAgent agent = startContainer(PATH_REALM_CONTAINER);
testContainer(agent);
destroyContainer(agent);
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw e;
}
}
public static StrolchAgent startContainer(String rootPath) {
File rootPathF = new File(rootPath);
return startContainer(rootPathF);

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<StrolchConfiguration>
<Runtime>
<applicationName>StrolchRuntimeTest</applicationName>
<Properties>
<dataStoreMode>TRANSIENT</dataStoreMode>
<realms>myRealm</realms>
<dataStoreFile.myRealm>StrolchModel.xml</dataStoreFile.myRealm>
<verbose>true</verbose>
</Properties>
</Runtime>
<Component>
<name>ServiceHandler</name>
<api>li.strolch.runtime.test.component.ServiceHandlerTest</api>
<impl>li.strolch.runtime.test.component.ServiceHandlerTestImpl</impl>
<depends>PersistenceHandler</depends>
<Properties>
</Properties>
</Component>
<Component>
<name>PostInitializer</name>
<api>li.strolch.runtime.test.component.PostInitializerTest</api>
<impl>li.strolch.runtime.test.component.PostInitializerTestImpl</impl>
<depends>ServiceHandler</depends>
<Properties>
</Properties>
</Component>
<Component>
<name>PersistenceHandler</name>
<api>li.strolch.runtime.test.component.PersistenceHandlerTest</api>
<impl>li.strolch.runtime.test.component.PersistenceHandlerTestImpl</impl>
<Properties>
<verbose>true</verbose>
</Properties>
</Component>
</StrolchConfiguration>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<StrolchModel>
<Order Id="MyTestOrder" Name="Test Name" Type="TestType" Date="2013-11-20T07:42:57.699+01:00" State="CREATED">
<ParameterBag Id="@bag01" Name="Test Bag" Type="TestBag">
<Parameter Id="@param7" Name="StringList Param" Type="StringList" Value="Hello;World" />
<Parameter Id="@param6" Name="Date Param" Type="Date" Value="2012-11-30T18:12:05.628+01:00" />
<Parameter Id="@param5" Name="String Param" Type="String" Value="Strolch" />
<Parameter Id="@param4" Name="Long Param" Type="Long" Value="4453234566" />
<Parameter Id="@param3" Name="Integer Param" Type="Integer" Value="77" />
<Parameter Id="@param2" Name="Float Param" Type="Float" Value="44.3" />
<Parameter Id="@param1" Name="Boolean Param" Type="Boolean" Value="true" />
</ParameterBag>
</Order>
</StrolchModel>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<StrolchModel>
<Resource Id="MyTestResource" Name="Test Name" Type="TestType">
<ParameterBag Id="@bag01" Name="Test Bag" Type="TestBag">
<Parameter Id="@param7" Name="StringList Param" Type="StringList" Value="Hello;World" />
<Parameter Id="@param6" Name="Date Param" Type="Date" Value="2012-11-30T18:12:05.628+01:00" />
<Parameter Id="@param5" Name="String Param" Type="String" Value="Strolch" />
<Parameter Id="@param4" Name="Long Param" Type="Long" Value="4453234566" />
<Parameter Id="@param3" Name="Integer Param" Type="Integer" Value="77" />
<Parameter Id="@param2" Name="Float Param" Type="Float" Value="44.3" />
<Parameter Id="@param1" Name="Boolean Param" Type="Boolean" Value="true" />
</ParameterBag>
</Resource>
</StrolchModel>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<StrolchModel>
<Resource Id="TestType" Name="TestType Template" Type="Template">
<ParameterBag Id="@bag01" Name="Test Bag" Type="TestBag">
<Parameter Id="@param7" Name="StringList Param" Type="StringList" Value="Hello;World" />
<Parameter Id="@param6" Name="Date Param" Type="Date" Value="2012-11-30T18:12:05.628+01:00" />
<Parameter Id="@param5" Name="String Param" Type="String" Value="Strolch" />
<Parameter Id="@param4" Name="Long Param" Type="Long" Value="4453234566" />
<Parameter Id="@param3" Name="Integer Param" Type="Integer" Value="77" />
<Parameter Id="@param2" Name="Float Param" Type="Float" Value="44.3" />
<Parameter Id="@param1" Name="Boolean Param" Type="Boolean" Value="true" />
</ParameterBag>
</Resource>
<Order Id="Template" Name="MyTestOrder Template" Type="MyTestOrder">
<ParameterBag Id="@bag01" Name="Test Bag" Type="TestBag">
<Parameter Id="@param7" Name="StringList Param" Type="StringList" Value="Hello;World" />
<Parameter Id="@param6" Name="Date Param" Type="Date" Value="2012-11-30T18:12:05.628+01:00" />
<Parameter Id="@param5" Name="String Param" Type="String" Value="Strolch" />
<Parameter Id="@param4" Name="Long Param" Type="Long" Value="4453234566" />
<Parameter Id="@param3" Name="Integer Param" Type="Integer" Value="77" />
<Parameter Id="@param2" Name="Float Param" Type="Float" Value="44.3" />
<Parameter Id="@param1" Name="Boolean Param" Type="Boolean" Value="true" />
</ParameterBag>
</Order>
<IncludeFile file="Resources.xml" />
<IncludeFile file="Orders.xml" />
</StrolchModel>