blob: 931344ea72e9188756c4db37b25cdfc75f38da5d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2019 IBM Corporation and others.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wtp.releng.tools;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
public class WritePropertiesAsPHP extends Task {
private String buildlabel;
private String propFileName;
private String outPHPFileName;
private static final String EOL = System.getProperty("line.separator");
// simplified view of pattern of property value with nexted property:
// (any text)${propertyName}{anyText)
private static String START_GROUP = "(";
private static String END_GROUP = ")";
private static String PROPSTART = "\\$\\{";
private static String PROPEND = "}";
private static String ANY = ".*";
// private static String ZERO_OR_ONE = "?";
private static Pattern nestPropertypattern = Pattern.compile(START_GROUP + ANY + END_GROUP + // can start with any text
START_GROUP + PROPSTART + ANY + PROPEND + END_GROUP + // ant property expression and ant property name is one groups
START_GROUP + ANY + END_GROUP); // can end with any text
private static Pattern antPropertyExpression = Pattern.compile(PROPSTART + START_GROUP + ANY + END_GROUP + PROPEND);
private DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
public static void main(String[] args) {
// boolean m = Pattern.matches(PROPSTART + START_GROUP + ANY + END_GROUP + PROPEND, "${teststring}");
// System.out.println(m);
WritePropertiesAsPHP testcase = new WritePropertiesAsPHP();
testcase.propFileName = "C:\\builds\\workspaces\\workspaceWTPHead\\releng\\helios\\dependencies.properties";
testcase.outPHPFileName = "C:\\builds\\workspaces\\workspaceWTPHead\\releng\\helios\\dependencies.properties.php";
testcase.execute();
}
@Override
public void execute() throws BuildException {
try {
convertPropertiesToVariables();
}
catch (FileNotFoundException e) {
throw new BuildException(e);
}
catch (IOException e) {
throw new BuildException(e);
}
}
private void convertPropertiesToVariables() throws FileNotFoundException, IOException {
File propFile = new File(getPropFileName());
Properties allProps = new Properties();
allProps.load(new FileInputStream(propFile));
File phpFile = new File(getOutPHPFileName());
Writer writer = new FileWriter(phpFile);
Set<Object> allPropsKeys = allProps.keySet();
ArrayList<String> sortableKeysList = new ArrayList(allPropsKeys);
Collections.sort(sortableKeysList);
try {
writer.write("<?php" + EOL);
writer.write("// This file was created on " + dateFormat.format(new Date()) + EOL);
writer.write("// Build Label: " + getBuildlabel() + EOL);
writer.write("// Based on input from: " + getPropFileName() + EOL);
for (Object key : sortableKeysList) {
String keyString = (String) key;
String keyValue = allProps.getProperty(keyString);
keyValue = expandVariableValues(keyValue, allProps);
keyString = toValidPHPVariable(keyString);
writer.write("$" + keyString + "=\"" + keyValue + "\";" + EOL);
}
writer.write("?>" + EOL);
}
finally {
if (writer != null) {
writer.close();
}
}
}
private String toValidPHPVariable(String keyString) {
// TODO: could also see if starts with digit, and if so, prefix
String result = keyString.replace('.', '_');
result = result.replace('-', '_');
return result;
}
private String expandVariableValues(String keyValue, Properties allProps) {
String result = null;
Matcher matcher = nestPropertypattern.matcher(keyValue);
if (matcher.matches()) {
StringBuffer sb = new StringBuffer();
int nGroups = matcher.groupCount();
// we avoid '0', since that's just "everything"
for (int i = 1; i <= nGroups; i++) {
String part = matcher.group(i);
//debug
//System.out.println(part);
if (part != null) {
if (part.startsWith("${")) {
// expanedValue can be called recursively to handle cases such as where
// ${A} and A=${B}, so expandedValue should be "B", not "${B}
String nestedPropValue = expandValue(part, allProps);
matcher.appendReplacement(sb, nestedPropValue);
}
else {
// call ourselves recursively to handle properties embedded in
// other surrounding text.
Matcher nestedmatcher = nestPropertypattern.matcher(part);
if (nestedmatcher.matches()) {
return expandVariableValues(part, allProps);
}
else {
sb.append(part);
}
}
}
}
result = sb.toString();
}
else {
// no nested property.
result = keyValue;
}
return result;
}
private String expandValue(String part, Properties allProps) {
// if part starts with '$', strip it off, get value call recursively
if (part.startsWith("${")) {
String propName = stripBrackets(part);
String value = allProps.getProperty(propName);
// if no property for presumed name, just return the part, even though still bracketed. Let caller decide what to do.
if (value == null) {
return part;
}
else {
return expandVariableValues(value, allProps);
}
}
// if does not start with '$', we are at end of recursion, and can assume previous call arrived at some
// terminal value.
// debug
//System.out.println("Terminal: " + part);
return part;
}
private String stripBrackets(String part) {
String result = null;
// check input if of form '${anytext}' and if not, just return string
Matcher matcher = antPropertyExpression.matcher(part);
if (matcher.matches()) {
result = matcher.group(1);
}
else {
result = part;
}
return result;
}
public String getPropFileName() {
return propFileName;
}
public String getOutPHPFileName() {
return outPHPFileName;
}
public String getBuildlabel() {
return buildlabel;
}
public void setBuildlabel(String buildlabel) {
this.buildlabel = buildlabel;
}
public void setPropFileName(String propFileName) {
this.propFileName = propFileName;
}
public void setOutPHPFileName(String outPHPFileName) {
this.outPHPFileName = outPHPFileName;
}
}