/*
* gvNIX is an open source tool for rapid application development (RAD).
* Copyright (C) 2010 Generalitat Valenciana
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gvnix.dynamic.configuration.roo.addon;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.gvnix.dynamic.configuration.roo.addon.config.DefaultDynamicConfiguration;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynComponent;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynConfiguration;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynProperty;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynPropertyList;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.springframework.roo.support.logging.HandlerUtils;
/**
* Manage components of dynamic configurations.
* <ul>
* <li>TODO Analyze more Roo generated files to be managed</li>
* <li>TODO What happens when two addons manage the same file ?</li>
* <li>TODO Revert managed file changes when modification fails</li>
* </ul>
*
* @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for <a
* href="http://www.dgti.gva.es">General Directorate for Information
* Technologies (DGTI)</a>
*/
@Component
@Service
public class ServicesImpl implements Services {
private static final Logger logger = HandlerUtils
.getLogger(ServicesImpl.class);
// ------------ OSGi component attributes ----------------
private BundleContext context;
protected void activate(ComponentContext context) {
this.context = context.getBundleContext();
}
/**
* {@inheritDoc}
*/
public DynConfiguration getCurrentConfiguration() {
// Variable to store active dynamic configuration
DynConfiguration dynConf = new DynConfiguration();
dynConf.setActive(Boolean.TRUE);
// Iterate all dynamic configurations components registered
for (Object o : getDefaultDynamicConfiguration()) {
try {
// Invoke the read method of all components to get properties
Class<? extends Object> c = o.getClass();
Method m = c.getMethod("read", new Class[0]);
DynPropertyList dynProps = (DynPropertyList) m.invoke(o,
new Object[0]);
// Get dynamic configuration name
m = c.getMethod("getName", new Class[0]);
String name = (String) m.invoke(o, new Object[0]);
// Create a dynamic configuration with component and properties
DynComponent dynComp = new DynComponent(c.getName(), name,
dynProps);
dynConf.addComponent(dynComp);
}
catch (NoSuchMethodException nsme) {
logger.log(Level.SEVERE,
"No read method on dynamic configuration class", nsme);
}
catch (InvocationTargetException ite) {
logger.log(
Level.SEVERE,
"Cannot invoke read method on dynamic configuration class",
ite);
}
catch (IllegalAccessException iae) {
logger.log(
Level.SEVERE,
"Cannot access read method on dynamic configuration class",
iae);
}
}
return dynConf;
}
/**
* {@inheritDoc}
*/
public String getFilePath(DynComponent dynComp) {
String path = "";
// Find required dynamic configuration component
for (Object o : getDefaultDynamicConfiguration()) {
if (o.getClass().getName().equals(dynComp.getId())) {
try {
// Invoke the get file path method of component
Class<? extends Object> c = o.getClass();
Method m = c.getMethod("getFilePath", new Class[0]);
path = (String) m.invoke(o, new Object[0]);
}
catch (NoSuchMethodException nsme) {
logger.log(
Level.SEVERE,
"No get file path method on dynamic configuration class",
nsme);
}
catch (InvocationTargetException ite) {
logger.log(
Level.SEVERE,
"Cannot invoke get file path method on dynamic configuration class",
ite);
}
catch (IllegalAccessException iae) {
logger.log(
Level.SEVERE,
"Cannot access get file path method on dynamic configuration class",
iae);
}
break;
}
}
return path;
}
/**
* {@inheritDoc}
*/
public DynComponent getCurrentComponent(String name) {
// TODO Two properties with same name can exist on different components
// Get current configuration from disk files
DynConfiguration dynConf = getCurrentConfiguration();
for (DynComponent dynComp : dynConf.getComponents()) {
// Search the property on the configuration components
for (DynProperty dynProp : dynComp.getProperties()) {
if (dynProp.getKey().equals(name)) {
return dynComp;
}
}
}
return null;
}
/**
* {@inheritDoc}
*/
public DynProperty getCurrentProperty(String name) {
// Get current component from disk files
DynComponent dynComp = getCurrentComponent(name);
// Search the property on the component
if (dynComp != null) {
for (DynProperty dynProp : dynComp.getProperties()) {
if (dynProp.getKey().equals(name)) {
return dynProp;
}
}
}
return null;
}
/**
* {@inheritDoc}
*/
public void setCurrentConfiguration(DynConfiguration dynConf) {
// Iterate all dynamic configurations components registered
for (Object o : getDefaultDynamicConfiguration()) {
try {
// Invoke the read method of all components to get its
// properties
Class<? extends Object> c = o.getClass();
for (DynComponent dynComp : dynConf.getComponents()) {
if (c.getName().equals(dynComp.getId())) {
@SuppressWarnings("rawtypes")
Class[] t = new Class[1];
t[0] = DynPropertyList.class;
Method m = c.getMethod("write", t);
Object[] args = new Object[1];
args[0] = dynComp.getProperties();
m.invoke(o, args);
}
}
}
catch (NoSuchMethodException nsme) {
logger.log(Level.SEVERE,
"No write method on dynamic configuration class", nsme);
}
catch (InvocationTargetException ite) {
logger.log(
Level.SEVERE,
"Cannot invoke write method on dynamic configuration class",
ite);
}
catch (IllegalAccessException iae) {
logger.log(
Level.SEVERE,
"Cannot access write method on dynamic configuration class",
iae);
}
}
}
public List<Object> getDefaultDynamicConfiguration() {
List<Object> dynConfigurations = new ArrayList<Object>();
// Get all Services implement DefaultDynamicConfiguration interface
try {
ServiceReference[] references = context.getAllServiceReferences(
DefaultDynamicConfiguration.class.getName(), null);
for (ServiceReference ref : references) {
dynConfigurations.add(context.getService(ref));
}
return dynConfigurations;
}
catch (InvalidSyntaxException e) {
logger.warning("Cannot load DefaultDynamicConfiguration on ServicesImpl.");
return null;
}
}
}