/*
* 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 org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynComponent;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynComponentList;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynConfiguration;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynConfigurationList;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynProperty;
import org.gvnix.dynamic.configuration.roo.addon.entity.DynPropertyList;
import org.springframework.roo.process.manager.FileManager;
import org.springframework.roo.project.LogicalPath;
import org.springframework.roo.project.Path;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.support.util.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Manage POM.
*
* @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 PomManagerImpl implements PomManager {
private static final String RESOURCES_PATH = "src/main/resources";
@Reference
private ProjectOperations projectOperations;
@Reference
private FileManager fileManager;
/**
* {@inheritDoc}
*/
public DynConfigurationList export(DynConfigurationList dynConfs) {
// Pom root element
String pom = projectOperations.getPathResolver().getIdentifier(
LogicalPath.getInstance(Path.ROOT, ""), "pom.xml");
Document doc = XmlUtils.readXml(fileManager.getInputStream(pom));
// Iterate stored dynamic configurations for export to pom
for (DynConfiguration dynConf : dynConfs) {
Element prof = exportConfiguration(doc, dynConf);
// Iterate components of dynamic configuration
DynComponentList dynComps = dynConf.getComponents();
for (DynComponent dynComp : dynComps) {
Element props = exportComponent(doc, prof);
// Iterate properties of dynamic configuration
DynPropertyList dynProps = dynComp.getProperties();
for (DynProperty dynProp : dynProps) {
exportProperty(doc, props, dynProp);
}
}
// Update POM configuration before store vars to avoid overwrite
fileManager.createOrUpdateTextFileIfRequired(pom,
XmlUtils.nodeToString(doc), true);
}
return dynConfs;
}
/**
* Write a configurations into POM profile.
*
* @param doc Pom document
* @param dynConf
* @return New configuration element
*/
protected Element exportConfiguration(Document doc, DynConfiguration dynConf) {
Element root = doc.getDocumentElement();
// <project>
// <profiles>
// <profile>
// <id>test</id>
// <activation>
// <activeByDefault>true</activeByDefault>
// </activation>
// </profile>
// </profiles>
// </project>
// Profiles section: find or create if not exists
Element profs = XmlUtils.findFirstElement("/project/profiles", root);
if (profs == null) {
profs = doc.createElement("profiles");
root.appendChild(profs);
}
// Remove profile if already exists
Element prof = XmlUtils.findFirstElement("profile/id[text()='"
+ dynConf.getName() + "']/..", profs);
if (prof != null) {
profs.removeChild(prof);
}
// Create a profile section for this dynamic configuration
prof = doc.createElement("profile");
profs.appendChild(prof);
// Create an identifier for profile
Element id = doc.createElement("id");
id.setTextContent(dynConf.getName());
prof.appendChild(id);
// If dynamic configuration is active: profile active by default
if (dynConf.isActive()) {
// Create an activation section
Element activation = doc.createElement("activation");
prof.appendChild(activation);
Element active = doc.createElement("activeByDefault");
active.setTextContent("true");
activation.appendChild(active);
}
return prof;
}
/**
* Write a component into POM profile.
*
* @param doc Pom document
* @param prof Profile element
* @return New component element
*/
protected Element exportComponent(Document doc, Element prof) {
Element root = doc.getDocumentElement();
// <resources>
// <resource>
// <directory>src/main/resources</directory>
// <filtering>true</filtering>
// </resource>
// </resources>
// Build section: find or create if not exists
Element build = XmlUtils.findFirstElement("/project/build", root);
if (build == null) {
build = doc.createElement("build");
root.appendChild(build);
}
Element resos;
// Resources section: find or create if not exists
resos = XmlUtils.findFirstElement("resources", build);
if (resos == null) {
resos = doc.createElement("resources");
build.appendChild(resos);
}
// Find resource section with directory and filter
Element reso = XmlUtils.findFirstElement("resource/directory"
+ "[text()='" + RESOURCES_PATH
+ "']/../filtering[text()='true']/..", resos);
// Remove resource if already exists
if (reso != null) {
resos.removeChild(reso);
}
// Create resource section with directory and filter
reso = doc.createElement("resource");
resos.appendChild(reso);
Element dir = doc.createElement("directory");
dir.setTextContent(RESOURCES_PATH);
reso.appendChild(dir);
Element filter = doc.createElement("filtering");
filter.setTextContent("true");
reso.appendChild(filter);
// <properties>
// </properties>
// Properties section: find or create if not exists
Element props = XmlUtils.findFirstElement("properties", prof);
if (props == null) {
props = doc.createElement("properties");
prof.appendChild(props);
}
return props;
}
/**
* Write a property into POM profile.
* <p>
* No write property if null value.
* </p>
*
* @param doc Pom document
* @param props Properties element
* @return New property element
*/
protected void exportProperty(Document doc, Element props,
DynProperty dynProp) {
String key = dynProp.getKey().replace('/', '.').replace('[', '.')
.replace(']', '.').replace('@', '.').replace(':', '.')
.replace('-', '.').replace('%', '.');
while (key.startsWith(".")) {
key = key.substring(1, key.length());
}
while (key.endsWith(".")) {
key = key.substring(0, key.length() - 1);
}
while (key.contains("..")) {
key = key.replace("..", ".");
}
// Create property if not empty (no write property if null value)
if (dynProp.getValue() != null) {
// <log4j.rootLogger>INFO, stdout</log4j.rootLogger>
// Create a property element for this dynamic property
Element prop = doc.createElement(key);
props.appendChild(prop);
// Store this dynamic property value in pom and replace
// dynamic property value with a var
prop.setTextContent(dynProp.getValue());
}
dynProp.setValue("${" + key + "}");
}
}