Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept default value in placeholders for unresolved property values #1

Merged
merged 5 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.codehaus.mojo.properties;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

/**
* ExpansionBuffer implementation that allows processing of default values within property placeholders
*
* @author tdiamantis
*/
public class DefaultValuesAwareExpansionBufferImpl extends ExpansionBuffer {
public DefaultValuesAwareExpansionBufferImpl(String unresolved) {
super(unresolved);
}

public KeyAndDefaultValue extractPropertyKeyAndDefaultValue()
{
advanceToNextPrefix();

discardPrefix();

String key = beforeNextSuffix();

String defaultValue = defaultValue();

discardToAfterNextSuffix();

return new KeyAndDefaultValue(key, defaultValue);
}

protected String beforeNextSuffix()
{
int defValuePos = unresolved.indexOf(":");
int propertySuffixPos = unresolved.indexOf("}");

//check default value separator only if before next suffix
if (defValuePos != -1 && propertySuffixPos != -1 && defValuePos < propertySuffixPos)
{
return unresolved.substring( 0, defValuePos );
}

return unresolved.substring( 0, propertySuffixPos );
}

private String defaultValue()
{
int defValuePos = unresolved.indexOf( ":" );
int propertySuffixPos = unresolved.indexOf( "}" );
if (defValuePos != -1 && propertySuffixPos != -1 && (defValuePos+1) < propertySuffixPos)
{
return unresolved.substring( defValuePos+1, propertySuffixPos );
}

return null;
}
}
29 changes: 7 additions & 22 deletions src/main/java/org/codehaus/mojo/properties/ExpansionBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
* under the License.
*/

class ExpansionBuffer
abstract class ExpansionBuffer
{
private final StringBuilder resolved = new StringBuilder();

private String unresolved;
protected String unresolved;

public ExpansionBuffer( String unresolved )
{
Expand All @@ -37,18 +37,7 @@ public boolean hasMoreLegalPlaceholders()
return prefixPos >= 0 && suffixPos >= 0;
}

public String extractPropertyKey()
{
advanceToNextPrefix();

discardPrefix();

String key = beforeNextSuffix();

discardToAfterNextSuffix();

return key;
}
public abstract KeyAndDefaultValue extractPropertyKeyAndDefaultValue();

public String toString()
{
Expand Down Expand Up @@ -82,18 +71,18 @@ private void skipUnresolvedPlaceholder( String newKey )
resolved.append( "${" ).append( newKey ).append( "}" );
}

private void discardToAfterNextSuffix()
protected void discardToAfterNextSuffix()
{
int propertySuffixPos = unresolved.indexOf( "}" );
unresolved = unresolved.substring( propertySuffixPos + 1 );
}

private void advanceToNextPrefix()
protected void advanceToNextPrefix()
{
resolved.append( beforePrefix() );
}

private void discardPrefix()
protected void discardPrefix()
{
int propertyPrefixPos = unresolved.indexOf( "${" );
unresolved = unresolved.substring( propertyPrefixPos + 2 );
Expand All @@ -105,9 +94,5 @@ private String beforePrefix()
return unresolved.substring( 0, propertyPrefixPos );
}

private String beforeNextSuffix()
{
int propertySuffixPos = unresolved.indexOf( "}" );
return unresolved.substring( 0, propertySuffixPos );
}
protected abstract String beforeNextSuffix();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.codehaus.mojo.properties;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

/**
* Default implementation of the ExpansionBuffer class
*
* @author tdiamantis
*/
public class ExpansionBufferImpl extends ExpansionBuffer {
public ExpansionBufferImpl(String unresolved) {
super(unresolved);
}

public KeyAndDefaultValue extractPropertyKeyAndDefaultValue()
{
advanceToNextPrefix();

discardPrefix();

String key = beforeNextSuffix();

discardToAfterNextSuffix();

return new KeyAndDefaultValue(key, null);
}

protected String beforeNextSuffix()
{
int propertySuffixPos = unresolved.indexOf( "}" );
return unresolved.substring( 0, propertySuffixPos );
}
}
49 changes: 49 additions & 0 deletions src/main/java/org/codehaus/mojo/properties/KeyAndDefaultValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.codehaus.mojo.properties;

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

/**
* @author tdiamantis
*/
public class KeyAndDefaultValue {
private String key;
private String defaultValue;

public KeyAndDefaultValue(String key, String defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
}

public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}

public String getDefaultValue() {
return defaultValue;
}

public void setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
}
}
37 changes: 32 additions & 5 deletions src/main/java/org/codehaus/mojo/properties/PropertyResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,40 @@ class PropertyResolver
* @return resolved property value
* @throws IllegalArgumentException when properties are circularly defined
*/
public String getPropertyValue( String key, Properties properties, Properties environment )
public String getPropertyValue( String key, Properties properties, Properties environment ) {
return getPropertyValue(key, properties, environment, false);
}

/**
* Same as the previous method. Accepts an extra flag to indicate whether default values should be
* processed within property placeholders or not.
*
* @param key property key
* @param properties project properties
* @param environment environment variables
* @param useDefaultValues process default values flag
* @return resolved property value
* @throws IllegalArgumentException when properties are circularly defined
*/
public String getPropertyValue( String key, Properties properties, Properties environment, boolean useDefaultValues )
{
String value = properties.getProperty( key );

ExpansionBuffer buffer = new ExpansionBuffer( value );
ExpansionBuffer buffer;
if ( useDefaultValues ) {
buffer = new DefaultValuesAwareExpansionBufferImpl(value);
} else {
buffer = new ExpansionBufferImpl( value );
}

CircularDefinitionPreventer circularDefinitionPreventer =
new CircularDefinitionPreventer().visited( key, value );

while ( buffer.hasMoreLegalPlaceholders() )
{
String newKey = buffer.extractPropertyKey();
String newValue = fromPropertiesThenSystemThenEnvironment( newKey, properties, environment );
KeyAndDefaultValue kv = buffer.extractPropertyKeyAndDefaultValue();
String newKey = kv.getKey();
String newValue = fromPropertiesThenSystemThenEnvironment( newKey, kv.getDefaultValue(), properties, environment );

circularDefinitionPreventer.visited( newKey, newValue );

Expand All @@ -60,7 +81,7 @@ public String getPropertyValue( String key, Properties properties, Properties en
return buffer.toString();
}

private String fromPropertiesThenSystemThenEnvironment( String key, Properties properties, Properties environment )
private String fromPropertiesThenSystemThenEnvironment( String key, String defaultValue, Properties properties, Properties environment )
{
String value = properties.getProperty( key );

Expand All @@ -76,6 +97,12 @@ private String fromPropertiesThenSystemThenEnvironment( String key, Properties p
value = environment.getProperty( key.substring( 4 ) );
}

// try default value
if ( value == null )
{
value = defaultValue;
}

return value;
}
}
34 changes: 29 additions & 5 deletions src/main/java/org/codehaus/mojo/properties/ReadPropertiesMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void setFiles( File[] files )

/**
* Default scope for test access.
*
*
* @param urls The URLs to set for tests.
*/
public void setUrls( String[] urls )
Expand Down Expand Up @@ -122,6 +122,14 @@ public void setKeyPrefix( String keyPrefix )
@Parameter( defaultValue = "false", property = "prop.skipLoadProperties" )
private boolean skipLoadProperties;

/**
* If the plugin should process default values within property placeholders
*
* @parameter default-value="false"
*/
@Parameter( defaultValue = "false" )
private boolean useDefaultValues;

/**
* Used for resolving property placeholders.
*/
Expand Down Expand Up @@ -278,7 +286,7 @@ private String getPropertyValue( String k, Properties p, Properties environment
{
try
{
return resolver.getPropertyValue( k, p, environment );
return resolver.getPropertyValue( k, p, environment , useDefaultValues);
}
catch ( IllegalArgumentException e )
{
Expand All @@ -288,7 +296,7 @@ private String getPropertyValue( String k, Properties p, Properties environment

/**
* Override-able for test purposes.
*
*
* @return The shell environment variables, can be empty but never <code>null</code>.
* @throws IOException If the environment variables could not be queried from the shell.
*/
Expand All @@ -300,7 +308,7 @@ Properties getSystemEnvVars()

/**
* Default scope for test access.
*
*
* @param quiet Set to <code>true</code> if missing files can be skipped.
*/
void setQuiet( boolean quiet )
Expand All @@ -317,16 +325,32 @@ void setSkipLoadProperties( boolean skipLoadProperties )
this.skipLoadProperties = skipLoadProperties;
}

/**
* @param useDefaultValues set to <code>true</code> if default values need to be processed within property placeholders
*/
public void setUseDefaultValues(boolean useDefaultValues)
{
this.useDefaultValues = useDefaultValues;
}

/**
* Default scope for test access.
*
*
* @param project The test project.
*/
void setProject( MavenProject project )
{
this.project = project;
}

/**
* For test access.
* @return The test project
*/
public MavenProject getProject() {
return project;
}

private static abstract class Resource
{
private InputStream stream;
Expand Down