pax_global_header00006660000000000000000000000064124202666010014511gustar00rootroot0000000000000052 comment=7724d3b62d6baf411f84869d4cfacb2af5705674 plexus-interpolation-plexus-interpolation-1.21/000077500000000000000000000000001242026660100220445ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/.gitignore000066400000000000000000000000771242026660100240400ustar00rootroot00000000000000target/ .project .classpath .settings/ bin *.iml .idea/ plexus-interpolation-plexus-interpolation-1.21/pom.xml000066400000000000000000000030041242026660100233560ustar00rootroot00000000000000 4.0.0 org.codehaus.plexus plexus-components 1.3.1 plexus-interpolation 1.21 Plexus Interpolation API scm:git:git@github.com:sonatype/plexus-interpolation.git scm:git:git@github.com:sonatype/plexus-interpolation.git http://github.com/sonatype/plexus-interpolation plexus-interpolation-1.21 org.apache.maven.plugins maven-release-plugin 2.5.1 **/src/test/resources/utf8/** junit junit 3.8.2 test plexus-interpolation-plexus-interpolation-1.21/release.properties000066400000000000000000000006651242026660100256110ustar00rootroot00000000000000#release configuration #Fri Oct 17 21:02:39 CEST 2014 scm.tagNameFormat=@{project.artifactId}-@{project.version} pushChanges=true scm.url=scm\:git\:git@github.com\:sonatype/plexus-interpolation.git preparationGoals=clean verify remoteTagging=true projectVersionPolicyId=default scm.commentPrefix=[maven-release-plugin] exec.additionalArguments=-Pplexus-release -P nexus exec.snapshotReleasePluginAllowed=false completedPhase=check-poms plexus-interpolation-plexus-interpolation-1.21/src/000077500000000000000000000000001242026660100226335ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/000077500000000000000000000000001242026660100235575ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/000077500000000000000000000000001242026660100245005ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/000077500000000000000000000000001242026660100252675ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/000077500000000000000000000000001242026660100270625ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/000077500000000000000000000000001242026660100304025ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/000077500000000000000000000000001242026660100332715ustar00rootroot00000000000000AbstractDelegatingValueSource.java000066400000000000000000000026331242026660100417660ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.List; public abstract class AbstractDelegatingValueSource implements ValueSource { private final ValueSource delegate; protected AbstractDelegatingValueSource( ValueSource delegate ) { if ( delegate == null ) { throw new NullPointerException( "Delegate ValueSource cannot be null." ); } this.delegate = delegate; } protected ValueSource getDelegate() { return delegate; } public Object getValue( String expression ) { return getDelegate().getValue( expression ); } public void clearFeedback() { delegate.clearFeedback(); } public List getFeedback() { return delegate.getFeedback(); } } AbstractFunctionValueSourceWrapper.java000066400000000000000000000066101242026660100430500ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ /** * {@link ValueSource} abstract implementation that wraps another value source. * When an expression is resolved, this wrapped source is first used to retrieve * the expression's actual value; then, the last expression processed by this * source is retrieved, and the two are passed into the abstract method * {@link AbstractFunctionValueSourceWrapper#executeFunction(String, Object)} * together. The result of this is returned as the resolved value for the second * expression. *
* This allows the first expression to be a function name that modifies the * value of the second expression, which is resolved from the wrapped value * source. * @version $Id$ */ public abstract class AbstractFunctionValueSourceWrapper implements ValueSource { private final ValueSource valueSource; /** * Construct a new function value source instance, using the supplied {@link ValueSource} * to retrieve the input values for the function(s) this class implements. * * @param valueSource The value source to wrap */ protected AbstractFunctionValueSourceWrapper( ValueSource valueSource ) { this.valueSource = valueSource; } /** *
    *
  1. Resolve the current expression using the embedded {@link ValueSource}
  2. *
  3. Retrieve the last expression processed by this value source
  4. *
  5. Pass the last expression (which should be the function name), along * with the value for the current expression, into the * executeFunction(..) method
  6. *
  7. Return the result of the executeFunction(..) as the resolved value * for the current expression.
  8. *
*/ public Object getValue( String expression ) { Object value = valueSource.getValue( expression ); String expr = expression; if ( valueSource instanceof QueryEnabledValueSource ) { expr = ((QueryEnabledValueSource) valueSource).getLastExpression(); } return executeFunction( expr, value ); } /** * Retrieve the embedded value source. */ protected ValueSource getValueSource() { return valueSource; } /** * Execute the function referenced in the last-processed expression using the * value resolved from the current expression (using the embedded {@link ValueSource}). * * @param expression The last expression to be processed by this value source. * @param value The value for the current expression, resolved by the embedded {@link ValueSource} * @return The result of modifying the current expression's value using the function named by the last expression. */ protected abstract Object executeFunction( String expression, Object value ); } AbstractValueSource.java000066400000000000000000000027101242026660100377760ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.ArrayList; import java.util.List; public abstract class AbstractValueSource implements ValueSource { private final List feedback; protected AbstractValueSource( boolean usesFeedback ) { if ( usesFeedback ) { feedback = new ArrayList(); } else { feedback = null; } } public void clearFeedback() { if ( feedback != null ) { feedback.clear(); } } public List getFeedback() { return feedback; } protected void addFeedback( String message ) { feedback.add( message ); } protected void addFeedback( String message, Throwable cause ) { feedback.add( message ); feedback.add( cause ); } } EnvarBasedValueSource.java000066400000000000000000000070421242026660100402500ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2007 The Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; import java.io.IOException; import java.util.Properties; /** * {@link ValueSource} which resolves expressions against the environment variables * available from the underlying operating system (and possibly, the shell environment * that created the present Java process). If the expression starts with 'env.', * this prefix is trimmed before resolving the rest as an environment variable name. * * @version $Id$ */ public class EnvarBasedValueSource extends AbstractValueSource { private static Properties envarsCaseSensitive; private static Properties envarsCaseInsensitive; private final Properties envars; private final boolean caseSensitive; /** * Create a new value source for interpolation based on shell environment variables. In this * case, envar keys ARE CASE SENSITIVE. * * @throws IOException */ public EnvarBasedValueSource() throws IOException { this( true ); } /** * Create a new value source for interpolation based on shell environment variables. * * @param caseSensitive Whether the environment variable key should be treated in a * case-sensitive manner for lookups * @throws IOException */ public EnvarBasedValueSource( boolean caseSensitive ) throws IOException { super( false ); this.caseSensitive = caseSensitive; this.envars = getEnvars( caseSensitive ); } private static synchronized Properties getEnvars( boolean caseSensitive ) throws IOException { if ( caseSensitive ) { if ( envarsCaseSensitive == null ) { envarsCaseSensitive = OperatingSystemUtils.getSystemEnvVars( caseSensitive ); } return envarsCaseSensitive; } else { if ( envarsCaseInsensitive == null ) { envarsCaseInsensitive = OperatingSystemUtils.getSystemEnvVars( caseSensitive ); } return envarsCaseInsensitive; } } /** * If the expression starts with 'env.' then trim this prefix. Next, resolve * the (possibly trimmed) expression as an environment variable name against * the collection of environment variables that were read from the operating * system when this {@link ValueSource} instance was created. * * @param expression envar expression, like 'HOME' or 'env.HOME' * @return the environment variable value for the given expression */ public Object getValue( String expression ) { String expr = expression; if ( expr.startsWith( "env." ) ) { expr = expr.substring( "env.".length() ); } if ( !caseSensitive ) { expr = expr.toUpperCase(); } return envars.getProperty( expr ); } } FeedbackEnabledValueSource.java000066400000000000000000000017371242026660100412020ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ /** * Represents a {@link ValueSource} which provides information back to the caller * about what may have gone wrong while resolving the value for an expression. * * @author jdcasey * @version $Id$ * * @deprecated Rolled into {@link ValueSource} now. */ public interface FeedbackEnabledValueSource extends ValueSource { } InterpolationCycleException.java000066400000000000000000000021361242026660100415450ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ public class InterpolationCycleException extends InterpolationException { private static final long serialVersionUID = 1L; public InterpolationCycleException( RecursionInterceptor recursionInterceptor, String realExpr, String wholeExpr ) { super( "Detected the following recursive expression cycle in '" + realExpr + "': " + recursionInterceptor.getExpressionCycle( realExpr ), wholeExpr ); } } InterpolationException.java000066400000000000000000000047551242026660100405760ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ /** * Signals an unrecoverable error in the process of interpolating a string, such * as the detection of an expression cycle. Errors resolving individual values * from expressions, such as those that happen when an object wrapped in an * {@link ObjectBasedValueSource} doesn't have the property represented by a * particular expression part, should NOT result in InterpolationExceptions * being thrown. Instead, they should be reported in the feedback from the {@link ValueSource}, * which is propagated out through {@link Interpolator#getFeedback()}. * * @version $Id$ */ public class InterpolationException extends Exception { private static final long serialVersionUID = 1L; private final String expression; /** * @param message The general description of the problem * @param expression The expression that triggered the problem * @param cause The wrapped exception */ public InterpolationException( String message, String expression, Throwable cause ) { super( buildMessage( message, expression ), cause ); this.expression = expression; } /** * @param message The general description of the problem * @param expression The expression that triggered the problem */ public InterpolationException( String message, String expression ) { super( buildMessage( message, expression ) ); this.expression = expression; } private static String buildMessage( String message, String expression ) { return "Resolving expression: '" + expression + "': " + message; } /** * @return The expression that triggered this exception. */ public String getExpression() { return expression; } } InterpolationPostProcessor.java000066400000000000000000000024741242026660100414610ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ /** * Used to allow full recursion of value interpolation before applying some rule * to the result. * @version $Id$ */ public interface InterpolationPostProcessor { /** * Given the starting expression and the fully-recursively-interpolated value, * perform some post-processing step and return the resulting [possibly different] * value, or null if no change was made.. * * @param expression the original expression * @param value the original value after fully recursive interpolation of expression * @return the processed value if a change was made; else return null */ Object execute( String expression, Object value ); } Interpolator.java000066400000000000000000000120761242026660100365450ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.List; /** * Interpolator interface. Based on existing RegexBasedInterpolator interface. * * @author cstamas * @version $Id$ */ public interface Interpolator { /** * Add a new {@link ValueSource} to the stack used to resolve expressions * in this interpolator instance. */ void addValueSource( ValueSource valueSource ); /** * Remove the specified {@link ValueSource} from the stack used to resolve * expressions in this interpolator instance. */ void removeValuesSource( ValueSource valueSource ); /** * Add a new post-processor to handle final processing after * recursively-interpolated value is determined. */ void addPostProcessor( InterpolationPostProcessor postProcessor ); /** * Remove the given post-processor. */ void removePostProcessor( InterpolationPostProcessor postProcessor ); /** * See {@link Interpolator#interpolate(String, String, RecursionInterceptor)}. *
* This method triggers the use of a {@link SimpleRecursionInterceptor} * instance for protection against expression cycles. * * @param input The input string to interpolate * * @param thisPrefixPattern An optional pattern that should be trimmed from * the start of any expressions found in the input. */ String interpolate( String input, String thisPrefixPattern ) throws InterpolationException; /** * Attempt to resolve all expressions in the given input string, using the * given pattern to first trim an optional prefix from each expression. The * supplied recursion interceptor will provide protection from expression * cycles, ensuring that the input can be resolved or an exception is * thrown. * return an empty String if input is null * @param input The input string to interpolate * * @param thisPrefixPattern An optional pattern that should be trimmed from * the start of any expressions found in the input. * * @param recursionInterceptor Used to protect the interpolation process * from expression cycles, and throw an * exception if one is detected. */ String interpolate( String input, String thisPrefixPattern, RecursionInterceptor recursionInterceptor ) throws InterpolationException; /** * See {@link Interpolator#interpolate(String, String, RecursionInterceptor)}. *
* This method triggers the use of a {@link SimpleRecursionInterceptor} * instance for protection against expression cycles. It also leaves empty the * expression prefix which would otherwise be trimmed from expressions. The * result is that any detected expression will be resolved as-is. * * @param input The input string to interpolate */ String interpolate( String input ) throws InterpolationException; /** * See {@link Interpolator#interpolate(String, String, RecursionInterceptor)}. *
* This method leaves empty the expression prefix which would otherwise be * trimmed from expressions. The result is that any detected expression will * be resolved as-is. * * @param input The input string to interpolate * * @param recursionInterceptor Used to protect the interpolation process * from expression cycles, and throw an * exception if one is detected. */ String interpolate( String input, RecursionInterceptor recursionInterceptor ) throws InterpolationException; /** * Return any feedback messages and errors that were generated - but * suppressed - during the interpolation process. Since unresolvable * expressions will be left in the source string as-is, this feedback is * optional, and will only be useful for debugging interpolation problems. * * @return a {@link List} that may be interspersed with {@link String} and * {@link Throwable} instances. */ List getFeedback(); /** * Clear the feedback messages from previous interpolate(..) calls. */ void clearFeedback(); boolean isCacheAnswers(); void setCacheAnswers( boolean cacheAnswers ); void clearAnswers(); } InterpolatorFilterReader.java000066400000000000000000000357621242026660100410450ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/* * The Apache Software License, Version 1.1 * * Copyright (c) 2002-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.codehaus.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "Ant" and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact codehaus@codehaus.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.codehaus.plexus.interpolation; import java.io.FilterReader; import java.io.IOException; import java.io.Reader; /** * A FilterReader implementation, that works with Interpolator interface instead of it's own interpolation * implementation. This implementation is heavily based on org.codehaus.plexus.util.InterpolationFilterReader. * * @author cstamas * @version $Id$ */ public class InterpolatorFilterReader extends FilterReader { /** Interpolator used to interpolate */ private Interpolator interpolator; /** * @since 1.12 */ private RecursionInterceptor recursionInterceptor; /** replacement text from a token */ private String replaceData = null; /** Index into replacement data */ private int replaceIndex = -1; /** Index into previous data */ private int previousIndex = -1; /** Default begin token. */ public static final String DEFAULT_BEGIN_TOKEN = "${"; /** Default end token. */ public static final String DEFAULT_END_TOKEN = "}"; private String beginToken; private String orginalBeginToken; private String endToken; /** true by default to preserve backward comp */ private boolean interpolateWithPrefixPattern = true; private String escapeString; private boolean useEscape = false; /** if true escapeString will be preserved \{foo} -> \{foo} */ private boolean preserveEscapeString = false; /** * this constructor use default begin token ${ and default end token } * @param in reader to use * @param interpolator interpolator instance to use */ public InterpolatorFilterReader( Reader in, Interpolator interpolator ) { this( in, interpolator, DEFAULT_BEGIN_TOKEN, DEFAULT_END_TOKEN ); } /** * @param in reader to use * @param interpolator interpolator instance to use * @param beginToken start token to use * @param endToken end token to use */ public InterpolatorFilterReader( Reader in, Interpolator interpolator, String beginToken, String endToken ) { this( in, interpolator, beginToken, endToken, new SimpleRecursionInterceptor() ); } /** * this constructor use default begin token ${ and default end token } * @param in reader to use * @param interpolator interpolator instance to use * @param ri The {@link RecursionInterceptor} to use to prevent recursive expressions. * @since 1.12 */ public InterpolatorFilterReader( Reader in, Interpolator interpolator, RecursionInterceptor ri ) { this( in, interpolator, DEFAULT_BEGIN_TOKEN, DEFAULT_END_TOKEN, new SimpleRecursionInterceptor() ); } /** * @param in reader to use * @param interpolator interpolator instance to use * @param beginToken start token to use * @param endToken end token to use * @param ri The {@link RecursionInterceptor} to use to prevent recursive expressions. * @since 1.12 */ public InterpolatorFilterReader( Reader in, Interpolator interpolator, String beginToken, String endToken, RecursionInterceptor ri ) { super( in ); this.interpolator = interpolator; this.beginToken = beginToken; this.endToken = endToken; recursionInterceptor = ri; this.orginalBeginToken = this.beginToken; } /** * Skips characters. This method will block until some characters are available, an I/O error occurs, or the end of * the stream is reached. * * @param n The number of characters to skip * @return the number of characters actually skipped * @exception IllegalArgumentException If n is negative. * @exception IOException If an I/O error occurs */ public long skip( long n ) throws IOException { if ( n < 0L ) { throw new IllegalArgumentException( "skip value is negative" ); } for ( long i = 0; i < n; i++ ) { if ( read() == -1 ) { return i; } } return n; } /** * Reads characters into a portion of an array. This method will block until some input is available, an I/O error * occurs, or the end of the stream is reached. * * @param cbuf Destination buffer to write characters to. Must not be null. * @param off Offset at which to start storing characters. * @param len Maximum number of characters to read. * @return the number of characters read, or -1 if the end of the stream has been reached * @exception IOException If an I/O error occurs */ public int read( char cbuf[], int off, int len ) throws IOException { for ( int i = 0; i < len; i++ ) { int ch = read(); if ( ch == -1 ) { if ( i == 0 ) { return -1; } else { return i; } } cbuf[off + i] = (char) ch; } return len; } /** * Returns the next character in the filtered stream, replacing tokens from the original stream. * * @return the next character in the resulting stream, or -1 if the end of the resulting stream has been reached * @exception IOException if the underlying stream throws an IOException during reading */ public int read() throws IOException { if ( replaceIndex != -1 && replaceIndex < replaceData.length() ) { int ch = replaceData.charAt( replaceIndex++ ); if ( replaceIndex >= replaceData.length() ) { replaceIndex = -1; } return ch; } int ch = -1; if ( previousIndex != -1 && previousIndex < this.endToken.length() ) { ch = this.endToken.charAt( previousIndex++ ); } else { ch = in.read(); } if ( ch == this.beginToken.charAt( 0 ) || ( useEscape && ch == this.orginalBeginToken.charAt( 0 ) ) ) { StringBuilder key = new StringBuilder( ); key.append( (char) ch ); int beginTokenMatchPos = 1; do { if ( previousIndex != -1 && previousIndex < this.endToken.length() ) { ch = this.endToken.charAt( previousIndex++ ); } else { ch = in.read(); } if ( ch != -1 ) { key.append( (char) ch ); if ( ( beginTokenMatchPos < this.beginToken.length() ) && ( ch != this.beginToken.charAt( beginTokenMatchPos++ ) ) && ( useEscape && this.orginalBeginToken.length() > ( beginTokenMatchPos - 1 ) && ch != this.orginalBeginToken .charAt( beginTokenMatchPos - 1 ) ) ) { ch = -1; // not really EOF but to trigger code below break; } } else { break; } // MSHARED-81 olamy : we must take care of token with length 1, escaping and same char : \@foo@ // here ch == endToken == beginToken -> not going to next char : bad :-) if ( useEscape && this.orginalBeginToken == this.endToken && key.toString().startsWith( this.beginToken ) ) { ch = in.read(); key.append( (char) ch ); } } while ( ch != this.endToken.charAt( 0 ) ); // now test endToken if ( ch != -1 && this.endToken.length() > 1 ) { int endTokenMatchPos = 1; do { if ( previousIndex != -1 && previousIndex < this.endToken.length() ) { ch = this.endToken.charAt( previousIndex++ ); } else { ch = in.read(); } if ( ch != -1 ) { key.append( (char) ch ); if ( ch != this.endToken.charAt( endTokenMatchPos++ ) ) { ch = -1; // not really EOF but to trigger code below break; } } else { break; } } while ( endTokenMatchPos < this.endToken.length() ); } // There is nothing left to read so we have the situation where the begin/end token // are in fact the same and as there is nothing left to read we have got ourselves // end of a token boundary so let it pass through. if ( ch == -1 ) { replaceData = key.toString(); replaceIndex = 1; return replaceData.charAt( 0 ); } String value = null; try { boolean escapeFound = false; if ( useEscape ) { if ( key.toString().startsWith( escapeString + orginalBeginToken ) ) { String keyStr = key.toString(); if ( !preserveEscapeString ) { value = keyStr.substring( escapeString.length(), keyStr.length() ); } else { value = keyStr; } escapeFound = true; } } if ( !escapeFound ) { if ( interpolateWithPrefixPattern ) { value = interpolator.interpolate( key.toString(), "", recursionInterceptor ); } else { value = interpolator.interpolate( key.toString(), recursionInterceptor ); } } } catch ( InterpolationException e ) { IllegalArgumentException error = new IllegalArgumentException( e.getMessage() ); error.initCause( e ); throw error; } if ( value != null ) { if ( value.length() != 0 ) { replaceData = value; replaceIndex = 0; } return read(); } else { previousIndex = 0; replaceData = key.substring( 0, key.length() - this.endToken.length() ); replaceIndex = 0; return this.beginToken.charAt( 0 ); } } return ch; } public boolean isInterpolateWithPrefixPattern() { return interpolateWithPrefixPattern; } public void setInterpolateWithPrefixPattern( boolean interpolateWithPrefixPattern ) { this.interpolateWithPrefixPattern = interpolateWithPrefixPattern; } public String getEscapeString() { return escapeString; } public void setEscapeString( String escapeString ) { // TODO NPE if escapeString is null ? if ( escapeString != null && escapeString.length() >= 1 ) { this.escapeString = escapeString; this.orginalBeginToken = beginToken; this.beginToken = escapeString + beginToken; this.useEscape = escapeString != null && escapeString.length() >= 1; } } public boolean isPreserveEscapeString() { return preserveEscapeString; } public void setPreserveEscapeString( boolean preserveEscapeString ) { this.preserveEscapeString = preserveEscapeString; } public RecursionInterceptor getRecursionInterceptor() { return recursionInterceptor; } public InterpolatorFilterReader setRecursionInterceptor( RecursionInterceptor recursionInterceptor ) { this.recursionInterceptor = recursionInterceptor; return this; } } MapBasedValueSource.java000066400000000000000000000024671242026660100377200ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2007 The Codehaus Foundation. * * 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. */ import java.util.Map; /** * Wraps a Map, and looks up the whole expression as a single key, returning the * value mapped to it. * @version $Id$ */ public class MapBasedValueSource extends AbstractValueSource { private final Map values; /** * Construct a new value source to wrap the supplied map. */ public MapBasedValueSource( Map values ) { super( false ); this.values = values; } /** * Lookup the supplied expression as a key in the wrapped Map, and return * its value. */ public Object getValue( String expression ) { return values == null ? null : values.get( expression ); } } ObjectBasedValueSource.java000066400000000000000000000047021242026660100404030ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2007 The Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.reflection.ReflectionValueExtractor; /** * Wraps an object, providing reflective access to the object graph of which the * supplied object is the root. Expressions like 'child.name' will translate into * 'rootObject.getChild().getName()' for non-boolean properties, and * 'rootObject.getChild().isName()' for boolean properties. * @version $Id$ */ public class ObjectBasedValueSource extends AbstractValueSource { private final Object root; /** * Construct a new value source, using the supplied object as the root from * which to start, and using expressions split at the dot ('.') to navigate * the object graph beneath this root. */ public ObjectBasedValueSource( Object root ) { super( true ); this.root = root; } /** * Split the expression into parts, tokenized on the dot ('.') character. Then, * starting at the root object contained in this value source, apply each part * to the object graph below this root, using either 'getXXX()' or 'isXXX()' * accessor types to resolve the value for each successive expression part. * Finally, return the result of the last expression part's resolution. *
* NOTE: The object-graph nagivation actually takes place via the * {@link ReflectionValueExtractor} class. */ public Object getValue( String expression ) { if ( expression == null || expression.trim().length() < 1 ) { return null; } try { return ReflectionValueExtractor.evaluate( expression, root, false ); } catch ( Exception e ) { addFeedback( "Failed to extract \'" + expression + "\' from: " + root, e ); } return null; } } PrefixAwareRecursionInterceptor.java000066400000000000000000000100541242026660100424030ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.util.ValueSourceUtils; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Stack; /** * {@link RecursionInterceptor} implementation that provides support for expressions * with multiple synonyms, such as project.build.directory == pom.build.directory == * build.directory in Maven's POM. * * @author jdcasey * @version $Id$ */ public class PrefixAwareRecursionInterceptor implements RecursionInterceptor { public static final String DEFAULT_START_TOKEN = "\\$\\{"; public static final String DEFAULT_END_TOKEN = "\\}"; private Stack nakedExpressions = new Stack(); private final String[] possiblePrefixes; private boolean watchUnprefixedExpressions = true; /** * Use the specified expression prefixes to detect synonyms, and specify whether * unprefixed expressions can be considered synonyms. * * @param possiblePrefixes The collection of expression prefixes supported * @param watchUnprefixedExpressions Whether to consider unprefixed expressions as synonyms */ public PrefixAwareRecursionInterceptor( Collection possiblePrefixes, boolean watchUnprefixedExpressions ) { this.possiblePrefixes = possiblePrefixes.toArray( new String[possiblePrefixes.size()]) ; this.watchUnprefixedExpressions = watchUnprefixedExpressions; } /** * Use the specified expression prefixes to detect synonyms. Consider * unprefixed expressions synonyms as well. * * @param possiblePrefixes The collection of expression prefixes supported */ public PrefixAwareRecursionInterceptor( Collection possiblePrefixes ) { this.possiblePrefixes = possiblePrefixes.toArray( new String[possiblePrefixes.size()]) ; } public boolean hasRecursiveExpression( String expression ) { String realExpr = ValueSourceUtils.trimPrefix( expression, possiblePrefixes, watchUnprefixedExpressions ); return realExpr != null && nakedExpressions.contains( realExpr ); } public void expressionResolutionFinished( String expression ) { nakedExpressions.pop(); } public void expressionResolutionStarted( String expression ) { String realExpr = ValueSourceUtils.trimPrefix( expression, possiblePrefixes, watchUnprefixedExpressions ); nakedExpressions.push( realExpr ); } /** * When an expression is determined to be a recursive reference, this method * returns the sublist of tracked expressions that participate in this cycle. * Otherwise, if the expression isn't present in the in-process stack, return * {@link Collections#EMPTY_LIST}. Also, if the expression doesn't have a matched * prefix from this interceptor's list, and unprefixed expressions aren't allowed * then return {@link Collections#EMPTY_LIST}. */ public List getExpressionCycle( String expression ) { String expr = ValueSourceUtils.trimPrefix( expression, possiblePrefixes, watchUnprefixedExpressions ); if ( expr == null ) { return Collections.EMPTY_LIST; } int idx = nakedExpressions.indexOf( expr ); if ( idx < 0 ) { return Collections.EMPTY_LIST; } else { return nakedExpressions.subList( idx, nakedExpressions.size() ); } } } PrefixedObjectValueSource.java000066400000000000000000000043031242026660100411300ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * 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. */ import java.util.List; /** * Wraps an arbitrary object with an {@link ObjectBasedValueSource} instance, then * wraps that source with a {@link PrefixedValueSourceWrapper} instance, to which * this class delegates all of its calls. * * @version $Id$ */ public class PrefixedObjectValueSource extends AbstractDelegatingValueSource implements QueryEnabledValueSource { /** * Wrap the specified root object, allowing the specified expression prefix. */ @SuppressWarnings( "UnusedDeclaration" ) public PrefixedObjectValueSource( String prefix, Object root ) { super( new PrefixedValueSourceWrapper( new ObjectBasedValueSource( root ), prefix ) ); } /** * Wrap the specified root object, allowing the specified list of expression * prefixes and setting whether the {@link PrefixedValueSourceWrapper} allows * unprefixed expressions. */ public PrefixedObjectValueSource( List possiblePrefixes, Object root, boolean allowUnprefixedExpressions ) { super( new PrefixedValueSourceWrapper( new ObjectBasedValueSource( root ), possiblePrefixes, allowUnprefixedExpressions ) ); } /** * {@inheritDoc} */ public String getLastExpression() { return ( (QueryEnabledValueSource) getDelegate() ).getLastExpression(); } } PrefixedPropertiesValueSource.java000066400000000000000000000057351242026660100420700ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * 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. */ import java.util.List; import java.util.Properties; /** * Legacy support. Allow trimming one of a set of expression prefixes, the lookup * the remaining expression as a literal key from the wrapped properties instance. *
* This is just a convenience implementation to provide a shorthand for constructing * the properties value source and then wrapping it with a prefixed value-source wrapper. * * @version $Id$ */ public class PrefixedPropertiesValueSource extends AbstractDelegatingValueSource implements QueryEnabledValueSource { /** * Wrap the specified properties file with a new {@link PropertiesBasedValueSource}, then * wrap that source with a new {@link PrefixedValueSourceWrapper} that uses the specified * expression prefix. Finally, set this wrapper source as a delegate for this * instance to use. * * @param prefix The expression prefix to trim * @param properties The properties instance to wrap */ public PrefixedPropertiesValueSource( String prefix, Properties properties ) { super( new PrefixedValueSourceWrapper( new PropertiesBasedValueSource( properties ), prefix ) ); } /** * Wrap the specified properties file with a new {@link PropertiesBasedValueSource}, then * wrap that source with a new {@link PrefixedValueSourceWrapper} that uses the specified * expression-prefix list. Finally, set this wrapper source as a delegate for this * instance to use. * * @param possiblePrefixes The expression-prefix list to trim * @param properties The properties instance to wrap */ public PrefixedPropertiesValueSource( List possiblePrefixes, Properties properties, boolean allowUnprefixedExpressions ) { super( new PrefixedValueSourceWrapper( new PropertiesBasedValueSource( properties ), possiblePrefixes, allowUnprefixedExpressions ) ); } /** * {@inheritDoc} */ public String getLastExpression() { return ( (QueryEnabledValueSource) getDelegate() ).getLastExpression(); } } PrefixedValueSourceWrapper.java000066400000000000000000000150251242026660100413450ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.util.ValueSourceUtils; import java.util.Collections; import java.util.List; /** * {@link ValueSource} implementation which simply wraps another value source, * and trims any of a set of possible expression prefixes before delegating the * modified expression to be resolved by the real value source. * * @author jdcasey * @version $Id$ */ public class PrefixedValueSourceWrapper implements FeedbackEnabledValueSource, QueryEnabledValueSource { private final ValueSource valueSource; private final String[] possiblePrefixes; private boolean allowUnprefixedExpressions; private String lastExpression; /** * Wrap the given value source, but first trim the given prefix from any * expressions before they are passed along for resolution. If an expression * doesn't start with the given prefix, do not resolve it. * * @param valueSource The {@link ValueSource} to wrap. * @param prefix The expression prefix to trim. */ public PrefixedValueSourceWrapper( ValueSource valueSource, String prefix ) { this.valueSource = valueSource; possiblePrefixes = new String[]{ prefix }; } /** * Wrap the given value source, but first trim the given prefix from any * expressions before they are passed along for resolution. If an expression * doesn't start with the given prefix and the allowUnprefixedExpressions flag * is set to true, simply pass the expression through to the nested value source * unchanged. If this flag is false, only allow resolution of those expressions * that start with the specified prefix. * * @param valueSource The {@link ValueSource} to wrap. * @param prefix The expression prefix to trim. * @param allowUnprefixedExpressions Flag telling the wrapper whether to * continue resolving expressions that don't start with the prefix it tracks. */ public PrefixedValueSourceWrapper( ValueSource valueSource, String prefix, boolean allowUnprefixedExpressions ) { this.valueSource = valueSource; possiblePrefixes = new String[]{ prefix }; this.allowUnprefixedExpressions = allowUnprefixedExpressions; } /** * Wrap the given value source, but first trim one of the given prefixes from any * expressions before they are passed along for resolution. If an expression * doesn't start with one of the given prefixes, do not resolve it. * * @param valueSource The {@link ValueSource} to wrap. * @param possiblePrefixes The List of expression prefixes to trim. */ public PrefixedValueSourceWrapper( ValueSource valueSource, List possiblePrefixes ) { this.valueSource = valueSource; this.possiblePrefixes = possiblePrefixes.toArray( new String[possiblePrefixes.size()] ); } /** * Wrap the given value source, but first trim one of the given prefixes from any * expressions before they are passed along for resolution. If an expression * doesn't start with the given prefix and the allowUnprefixedExpressions flag * is set to true, simply pass the expression through to the nested value source * unchanged. If this flag is false, only allow resolution of those expressions * that start with the specified prefix. * * @param valueSource The {@link ValueSource} to wrap. * @param possiblePrefixes The List of expression prefixes to trim. * @param allowUnprefixedExpressions Flag telling the wrapper whether to * continue resolving expressions that don't start with one of the prefixes it tracks. */ public PrefixedValueSourceWrapper( ValueSource valueSource, List possiblePrefixes, boolean allowUnprefixedExpressions ) { this.valueSource = valueSource; this.possiblePrefixes = possiblePrefixes.toArray( new String[possiblePrefixes.size()] ); this.allowUnprefixedExpressions = allowUnprefixedExpressions; } /** * Uses {@link ValueSourceUtils#trimPrefix(String, java.util.Collection, boolean)} to * get the trimmed expression. If this expression is null (because the original * expression was null, or because the expression is unprefixed and unprefixed * expressions are not allowed here), then return null; otherwise, return the * nested {@link ValueSource#getValue(String)} result. */ public Object getValue( String expression ) { lastExpression = ValueSourceUtils.trimPrefix( expression, possiblePrefixes, allowUnprefixedExpressions ); if ( lastExpression == null ) { return null; } return valueSource.getValue( lastExpression ); } /** * If the nested {@link ValueSource} implements {@link FeedbackEnabledValueSource}, * then return that source's feedback list. Otherwise, return {@link Collections#EMPTY_LIST}. */ public List getFeedback() { return ( valueSource instanceof FeedbackEnabledValueSource ) ? valueSource.getFeedback() : Collections.EMPTY_LIST; } /** * If the nested {@link ValueSource} implements {@link QueryEnabledValueSource}, * then return that source's last expression. Otherwise, return the last expression * that was processed by the wrapper itself. */ public String getLastExpression() { return ( valueSource instanceof QueryEnabledValueSource ) ? ( (QueryEnabledValueSource) valueSource ).getLastExpression() : lastExpression; } /** * If the nested {@link ValueSource} implements {@link FeedbackEnabledValueSource}, * then clear that source's feedback list. */ public void clearFeedback() { valueSource.clearFeedback(); } } PropertiesBasedValueSource.java000066400000000000000000000033651242026660100413350ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.Properties; /** * {@link ValueSource} implementation that wraps a {@link Properties} instance, * and does a simple lookup of the entire expression string as the parameter for * {@link Properties#getProperty(String)}, returning the result as the resolved * value. * * @author jdcasey * @version $Id$ */ public class PropertiesBasedValueSource extends AbstractValueSource { private final Properties properties; /** * Wrap the specified {@link Properties} object for use as a value source. * Nulls are allowed. * * @param properties The properties instance to wrap. */ public PropertiesBasedValueSource( Properties properties ) { super( false ); this.properties = properties; } /** * @return the result of {@link Properties#getProperty(String)}, using the * entire expression as the key to lookup. If the wrapped properties instance * is null, simply return null. */ public Object getValue( String expression ) { return properties == null ? null : properties.getProperty( expression ); } } QueryEnabledValueSource.java000066400000000000000000000020411242026660100406100ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ /** * Tracks the most recent expression processed by this value source implementation. * This can be useful if the most recent expression is meant to modify the current * one. * @version $Id$ */ public interface QueryEnabledValueSource extends ValueSource { /** * @return the most recent expression processed by this value source, or null. */ String getLastExpression(); } RecursionInterceptor.java000066400000000000000000000050241242026660100402460ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; import java.util.List; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ /** * Logs expressions before resolution is attempted, and clears them * after resolution is complete (or, fails all strategies). In between, * if the value of an expression contains more expressions, RecursionInterceptor * implementations ensure that those expressions don't reference an expression * which is in the process of being resolved. If that happens, the expression * references are cyclical, and would othewise result in an infinite loop. * @version $Id$ */ public interface RecursionInterceptor { /** * Log the intention to start resolving the given expression. This signals * the interceptor to start tracking that expression to make sure it doesn't * come up again until after it has been resolved (or, fails to resolve). * * @param expression The expression to be resolved. */ void expressionResolutionStarted( String expression ); /** * Signal to the interceptor that the all efforts to resolve the given * expression have completed - whether successfully or not is irrelevant - * and that the expression should not be tracked for recursion any longer. * * @param expression The expression to stop tracking. */ void expressionResolutionFinished( String expression ); /** * Check whether the given value contains an expression that is currently * being tracked by this interceptor. If so, that expression is still in * the process of being resolved, and this constitutes an expression cycle. * * @param value The value to check for expression cycles. * @return True if the value contains tracked expressions; false otherwise. */ boolean hasRecursiveExpression( String value ); /** * @return The list of expressions that participate in the cycle caused by * the given expression. */ List getExpressionCycle( String expression ); } RegexBasedInterpolator.java000066400000000000000000000341031242026660100404720ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.codehaus.plexus.interpolation.util.StringUtils; /** * Expansion of the original RegexBasedInterpolator, found in plexus-utils, this * interpolator provides options for setting custom prefix/suffix regex parts, * and includes a {@link RecursionInterceptor} parameter in its interpolate(..) * call, to allow the detection of cyclical expression references. * * @version $Id$ */ public class RegexBasedInterpolator implements Interpolator { private String startRegex; private String endRegex; private Map existingAnswers = new HashMap(); private List valueSources = new ArrayList(); private List postProcessors = new ArrayList(); private boolean reusePatterns = false; private boolean cacheAnswers = false; public static final String DEFAULT_REGEXP = "\\$\\{(.+?)\\}"; /** * the key is the regex the value is the Pattern * At the class construction time the Map will contains the default Pattern */ private Map compiledPatterns = new WeakHashMap(); /** * Setup a basic interpolator. *
* NOTE: You will have to call * {@link RegexBasedInterpolator#addValueSource(ValueSource)} at least once * if you use this constructor! */ public RegexBasedInterpolator() { compiledPatterns.put( DEFAULT_REGEXP, Pattern.compile( DEFAULT_REGEXP ) ); } /** * @param reusePatterns already compiled patterns will be reused */ public RegexBasedInterpolator( boolean reusePatterns ) { this(); this.reusePatterns = reusePatterns; } /** * Setup an interpolator with no value sources, and the specified regex pattern * prefix and suffix in place of the default one. *
* NOTE: You will have to call * {@link RegexBasedInterpolator#addValueSource(ValueSource)} at least once * if you use this constructor! * * @param startRegex start of the regular expression to use * @param endRegex end of the regular expression to use */ public RegexBasedInterpolator (String startRegex, String endRegex) { this(); this.startRegex = startRegex; this.endRegex = endRegex; } /** * Setup a basic interpolator with the specified list of value sources. * * @param valueSources The list of value sources to use */ public RegexBasedInterpolator( List valueSources ) { this(); this.valueSources.addAll( valueSources ); } /** * Setup an interpolator with the specified value sources, and the specified * regex pattern prefix and suffix in place of the default one. * * @param startRegex start of the regular expression to use * @param endRegex end of the regular expression to use * @param valueSources The list of value sources to use */ public RegexBasedInterpolator (String startRegex, String endRegex, List valueSources ) { this(); this.startRegex = startRegex; this.endRegex = endRegex; this.valueSources.addAll( valueSources ); } /** * {@inheritDoc} */ public void addValueSource( ValueSource valueSource ) { valueSources.add( valueSource ); } /** * {@inheritDoc} */ public void removeValuesSource( ValueSource valueSource ) { valueSources.remove( valueSource ); } /** * {@inheritDoc} */ public void addPostProcessor( InterpolationPostProcessor postProcessor ) { postProcessors.add( postProcessor ); } /** * {@inheritDoc} */ public void removePostProcessor( InterpolationPostProcessor postProcessor ) { postProcessors.remove( postProcessor ); } /** * Attempt to resolve all expressions in the given input string, using the * given pattern to first trim an optional prefix from each expression. The * supplied recursion interceptor will provide protection from expression * cycles, ensuring that the input can be resolved or an exception is * thrown. * * @param input The input string to interpolate * * @param thisPrefixPattern An optional pattern that should be trimmed from * the start of any expressions found in the input. * * @param recursionInterceptor Used to protect the interpolation process * from expression cycles, and throw an * exception if one is detected. */ public String interpolate( String input, String thisPrefixPattern, RecursionInterceptor recursionInterceptor ) throws InterpolationException { if (input == null ) { // return empty String to prevent NPE too return ""; } if ( recursionInterceptor == null ) { recursionInterceptor = new SimpleRecursionInterceptor(); } if ( thisPrefixPattern != null && thisPrefixPattern.length() == 0 ) { thisPrefixPattern = null; } int realExprGroup = 2; Pattern expressionPattern; if ( startRegex != null || endRegex != null ) { if ( thisPrefixPattern == null ) { expressionPattern = getPattern( startRegex + endRegex ); realExprGroup = 1; } else { expressionPattern = getPattern( startRegex + thisPrefixPattern + endRegex ); } } else if ( thisPrefixPattern != null ) { expressionPattern = getPattern( "\\$\\{(" + thisPrefixPattern + ")?(.+?)\\}" ); } else { expressionPattern = getPattern( DEFAULT_REGEXP ); realExprGroup = 1; } try { return interpolate( input, recursionInterceptor, expressionPattern, realExprGroup ); } finally { if ( !cacheAnswers ) { clearAnswers(); } } } private Pattern getPattern( String regExp ) { if ( !reusePatterns ) { return Pattern.compile( regExp ); } Pattern pattern; synchronized( this ) { pattern = compiledPatterns.get( regExp ); if ( pattern != null ) { return pattern; } pattern = Pattern.compile( regExp ); compiledPatterns.put( regExp, pattern ); } return pattern; } /** * Entry point for recursive resolution of an expression and all of its * nested expressions. * * @todo Ensure unresolvable expressions don't trigger infinite recursion. */ private String interpolate( String input, RecursionInterceptor recursionInterceptor, Pattern expressionPattern, int realExprGroup ) throws InterpolationException { if (input == null ) { // return empty String to prevent NPE too return ""; } String result = input; Matcher matcher = expressionPattern.matcher( result ); while ( matcher.find() ) { String wholeExpr = matcher.group( 0 ); String realExpr = matcher.group( realExprGroup ); if ( realExpr.startsWith( "." ) ) { realExpr = realExpr.substring( 1 ); } if ( recursionInterceptor.hasRecursiveExpression( realExpr ) ) { throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr ); } recursionInterceptor.expressionResolutionStarted( realExpr ); try { Object value = existingAnswers.get( realExpr ); for ( ValueSource vs : valueSources ) { if (value != null) break; value = vs.getValue( realExpr ); } if ( value != null ) { value = interpolate( String.valueOf( value ), recursionInterceptor, expressionPattern, realExprGroup ); if ( postProcessors != null && !postProcessors.isEmpty() ) { for ( InterpolationPostProcessor postProcessor : postProcessors ) { Object newVal = postProcessor.execute( realExpr, value ); if ( newVal != null ) { value = newVal; break; } } } // could use: // result = matcher.replaceFirst( stringValue ); // but this could result in multiple lookups of stringValue, and replaceAll is not correct behaviour result = StringUtils.replace( result, wholeExpr, String.valueOf( value ) ); matcher.reset( result ); } } finally { recursionInterceptor.expressionResolutionFinished( realExpr ); } } return result; } /** * Return any feedback messages and errors that were generated - but * suppressed - during the interpolation process. Since unresolvable * expressions will be left in the source string as-is, this feedback is * optional, and will only be useful for debugging interpolation problems. * * @return a {@link List} that may be interspersed with {@link String} and * {@link Throwable} instances. */ public List getFeedback() { List messages = new ArrayList(); for ( Object valueSource : valueSources ) { ValueSource vs = (ValueSource) valueSource; List feedback = vs.getFeedback(); if ( feedback != null && !feedback.isEmpty() ) { messages.addAll( feedback ); } } return messages; } /** * Clear the feedback messages from previous interpolate(..) calls. */ public void clearFeedback() { for ( Object valueSource : valueSources ) { ValueSource vs = (ValueSource) valueSource; vs.clearFeedback(); } } /** * See {@link RegexBasedInterpolator#interpolate(String, String, RecursionInterceptor)}. *
* This method triggers the use of a {@link SimpleRecursionInterceptor} * instance for protection against expression cycles. * * @param input The input string to interpolate * * @param thisPrefixPattern An optional pattern that should be trimmed from * the start of any expressions found in the input. */ public String interpolate( String input, String thisPrefixPattern ) throws InterpolationException { return interpolate( input, thisPrefixPattern, null ); } /** * See {@link RegexBasedInterpolator#interpolate(String, String, RecursionInterceptor)}. *
* This method triggers the use of a {@link SimpleRecursionInterceptor} * instance for protection against expression cycles. It also leaves empty the * expression prefix which would otherwise be trimmed from expressions. The * result is that any detected expression will be resolved as-is. * * @param input The input string to interpolate */ public String interpolate( String input ) throws InterpolationException { return interpolate( input, null, null ); } /** * See {@link RegexBasedInterpolator#interpolate(String, String, RecursionInterceptor)}. *
* This method leaves empty the expression prefix which would otherwise be * trimmed from expressions. The result is that any detected expression will * be resolved as-is. * * @param input The input string to interpolate * * @param recursionInterceptor Used to protect the interpolation process * from expression cycles, and throw an * exception if one is detected. */ public String interpolate( String input, RecursionInterceptor recursionInterceptor ) throws InterpolationException { return interpolate( input, null, recursionInterceptor ); } public boolean isReusePatterns() { return reusePatterns; } public void setReusePatterns( boolean reusePatterns ) { this.reusePatterns = reusePatterns; } public boolean isCacheAnswers() { return cacheAnswers; } public void setCacheAnswers( boolean cacheAnswers ) { this.cacheAnswers = cacheAnswers; } public void clearAnswers() { existingAnswers.clear(); } } SimpleRecursionInterceptor.java000066400000000000000000000045521242026660100414250ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.Collections; import java.util.List; import java.util.Stack; /** * Simplest implementation of a {@link RecursionInterceptor}, which checks whether * the existing interpolation effort is already attempting to resolve an exact * expression, but has not finished. This will not catch synonym expressions, as * are found in Maven (${project.build.directory}, ${pom.build.directory}, and * ${build.directory} are synonyms). * * @author jdcasey * @version $Id$ */ public class SimpleRecursionInterceptor implements RecursionInterceptor { private Stack expressions = new Stack(); /** * {@inheritDoc} */ public void expressionResolutionFinished( String expression ) { expressions.pop(); } /** * {@inheritDoc} */ public void expressionResolutionStarted( String expression ) { expressions.push( expression ); } /** * Check whether the current expression is already present in the in-process * stack. */ public boolean hasRecursiveExpression( String expression ) { return expressions.contains( expression ); } /** * When an expression is determined to be a recursive reference, this method * returns the sublist of tracked expressions that participate in this cycle. * Otherwise, if the expression isn't present in the in-process stack, return * {@link Collections#EMPTY_LIST}. */ public List getExpressionCycle( String expression ) { int idx = expressions.indexOf( expression ); if ( idx < 0 ) { return Collections.EMPTY_LIST; } else { return expressions.subList( idx, expressions.size() ); } } } SingleResponseValueSource.java000066400000000000000000000026201242026660100411730ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2009 Codehaus Foundation. * * 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. */ import java.util.Collections; import java.util.List; /** * If the expression matches, simply return the response object. * @since 1.12 */ public class SingleResponseValueSource implements ValueSource { private final String expression; private final Object response; public SingleResponseValueSource( String expression, Object response ) { this.expression = expression; this.response = response; } public void clearFeedback() { } public List getFeedback() { return Collections.EMPTY_LIST; } public Object getValue( String expression ) { if ( this.expression.equals( expression ) ) { return response; } return null; } } StringSearchInterpolator.java000066400000000000000000000237171242026660100410660ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; public class StringSearchInterpolator implements Interpolator { private Map existingAnswers = new HashMap(); private List valueSources = new ArrayList(); private List postProcessors = new ArrayList(); private boolean cacheAnswers = false; public static final String DEFAULT_START_EXPR = "${"; public static final String DEFAULT_END_EXPR = "}"; private String startExpr; private String endExpr; private String escapeString; public StringSearchInterpolator() { this.startExpr = DEFAULT_START_EXPR; this.endExpr = DEFAULT_END_EXPR; } public StringSearchInterpolator( String startExpr, String endExpr ) { this.startExpr = startExpr; this.endExpr = endExpr; } /** * {@inheritDoc} */ public void addValueSource( ValueSource valueSource ) { valueSources.add( valueSource ); } /** * {@inheritDoc} */ public void removeValuesSource( ValueSource valueSource ) { valueSources.remove( valueSource ); } /** * {@inheritDoc} */ public void addPostProcessor( InterpolationPostProcessor postProcessor ) { postProcessors.add( postProcessor ); } /** * {@inheritDoc} */ public void removePostProcessor( InterpolationPostProcessor postProcessor ) { postProcessors.remove( postProcessor ); } public String interpolate( String input, String thisPrefixPattern ) throws InterpolationException { return interpolate( input, new SimpleRecursionInterceptor() ); } public String interpolate( String input, String thisPrefixPattern, RecursionInterceptor recursionInterceptor ) throws InterpolationException { return interpolate( input, recursionInterceptor ); } public String interpolate( String input ) throws InterpolationException { return interpolate( input, new SimpleRecursionInterceptor() ); } /** * Entry point for recursive resolution of an expression and all of its * nested expressions. * * @todo Ensure unresolvable expressions don't trigger infinite recursion. */ public String interpolate( String input, RecursionInterceptor recursionInterceptor ) throws InterpolationException { try { return interpolate( input, recursionInterceptor, new HashSet() ); } finally { if ( !cacheAnswers ) { existingAnswers.clear(); } } } private String interpolate( String input, RecursionInterceptor recursionInterceptor, Set unresolvable ) throws InterpolationException { if ( input == null ) { // return empty String to prevent NPE too return ""; } StringBuilder result = new StringBuilder( input.length() * 2 ); int startIdx; int endIdx = -1; while ( ( startIdx = input.indexOf( startExpr, endIdx + 1 ) ) > -1 ) { result.append( input, endIdx + 1, startIdx ); endIdx = input.indexOf( endExpr, startIdx + 1 ); if ( endIdx < 0 ) { break; } final String wholeExpr = input.substring( startIdx, endIdx + endExpr.length() ); String realExpr = wholeExpr.substring( startExpr.length(), wholeExpr.length() - endExpr.length() ); if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 ) { int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length(); if ( startEscapeIdx >= 0 ) { String escape = input.substring( startEscapeIdx, startIdx ); if ( escape != null && escapeString.equals( escape ) ) { result.append( wholeExpr ); result.replace( startEscapeIdx, startEscapeIdx + escapeString.length(), "" ); continue; } } } boolean resolved = false; if ( !unresolvable.contains( wholeExpr ) ) { if ( realExpr.startsWith( "." ) ) { realExpr = realExpr.substring( 1 ); } if ( recursionInterceptor.hasRecursiveExpression( realExpr ) ) { throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr ); } recursionInterceptor.expressionResolutionStarted( realExpr ); try { Object value = existingAnswers.get( realExpr ); Object bestAnswer = null; for ( ValueSource valueSource : valueSources ) { if ( value != null ) { break; } value = valueSource.getValue( realExpr ); if ( value != null && value.toString().contains( wholeExpr ) ) { bestAnswer = value; value = null; } } // this is the simplest recursion check to catch exact recursion // (non synonym), and avoid the extra effort of more string // searching. if ( value == null && bestAnswer != null ) { throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr ); } if ( value != null ) { value = interpolate( String.valueOf( value ), recursionInterceptor, unresolvable ); if ( postProcessors != null && !postProcessors.isEmpty() ) { for ( InterpolationPostProcessor postProcessor : postProcessors ) { Object newVal = postProcessor.execute( realExpr, value ); if ( newVal != null ) { value = newVal; break; } } } // could use: // result = matcher.replaceFirst( stringValue ); // but this could result in multiple lookups of stringValue, and replaceAll is not correct // behaviour result.append( String.valueOf( value ) ); resolved = true; } else { unresolvable.add( wholeExpr ); } } finally { recursionInterceptor.expressionResolutionFinished( realExpr ); } } if ( !resolved ) { result.append( wholeExpr ); } if ( endIdx > -1 ) { endIdx += endExpr.length() - 1; } } if ( endIdx == -1 && startIdx > -1 ) { result.append( input, startIdx, input.length()); } else if ( endIdx < input.length() ) { result.append( input, endIdx + 1, input.length() ); } return result.toString(); } /** * Return any feedback messages and errors that were generated - but * suppressed - during the interpolation process. Since unresolvable * expressions will be left in the source string as-is, this feedback is * optional, and will only be useful for debugging interpolation problems. * * @return a {@link List} that may be interspersed with {@link String} and * {@link Throwable} instances. */ public List getFeedback() { List messages = new ArrayList(); for ( ValueSource vs : valueSources ) { List feedback = vs.getFeedback(); if ( feedback != null && !feedback.isEmpty() ) { messages.addAll( feedback ); } } return messages; } /** * Clear the feedback messages from previous interpolate(..) calls. */ public void clearFeedback() { for ( ValueSource vs : valueSources ) { vs.clearFeedback(); } } public boolean isCacheAnswers() { return cacheAnswers; } public void setCacheAnswers( boolean cacheAnswers ) { this.cacheAnswers = cacheAnswers; } public void clearAnswers() { existingAnswers.clear(); } public String getEscapeString() { return escapeString; } public void setEscapeString( String escapeString ) { this.escapeString = escapeString; } } ValueSource.java000066400000000000000000000025131242026660100363130ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; import java.util.List; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ /** * Supplies one strategy for resolving a value for an interpolation expression. * ValueSources may be stacked. * @version $Id$ */ public interface ValueSource { /** * @return the value related to the expression, or null if not found. */ public Object getValue( String expression ); /** * Return the feedback about resolution failures for a particular expression. * * @return a combination of String and Throwable instances, where strings * related to throwables are listed first. */ List getFeedback(); /** * Clear the feedback accumulated by a prior interpolation run. */ void clearFeedback(); } 000077500000000000000000000000001242026660100343445ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/multiDelimiterSpecification.java000066400000000000000000000062511242026660100416320ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/multipackage org.codehaus.plexus.interpolation.multi; /* * Copyright 2001-2009 Codehaus Foundation. * * 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. */ public final class DelimiterSpecification { public static final DelimiterSpecification DEFAULT_SPEC = DelimiterSpecification.parse( "${*}" ); private String begin; private String end; private int nextStart; public DelimiterSpecification( String begin, String end ) { this.begin = begin; this.end = end; } public int getNextStartIndex() { return nextStart; } public void setNextStartIndex( int nextStart ) { this.nextStart = nextStart; } public void clearNextStart() { nextStart = -1; } public static DelimiterSpecification parse( String delimiterSpec ) { final String[] spec = new String[2]; int splitIdx = delimiterSpec.indexOf( '*' ); if ( splitIdx < 0 ) { spec[0] = delimiterSpec; spec[1] = spec[0]; } else if ( splitIdx == delimiterSpec.length() - 1 ) { spec[0] = delimiterSpec.substring( 0, delimiterSpec.length() - 1 ); spec[1] = spec[0]; } else { spec[0] = delimiterSpec.substring( 0, splitIdx ); spec[1] = delimiterSpec.substring( splitIdx + 1 ); } return new DelimiterSpecification( spec[0], spec[1] ); } public String getBegin() { return begin; } public String getEnd() { return end; } public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ( ( begin == null ) ? 0 : begin.hashCode() ); result = prime * result + ( ( end == null ) ? 0 : end.hashCode() ); return result; } public boolean equals( Object obj ) { if ( this == obj ) return true; if ( obj == null ) return false; if ( getClass() != obj.getClass() ) return false; DelimiterSpecification other = (DelimiterSpecification) obj; if ( begin == null ) { if ( other.begin != null ) return false; } else if ( !begin.equals( other.begin ) ) return false; if ( end == null ) { if ( other.end != null ) return false; } else if ( !end.equals( other.end ) ) return false; return true; } public String toString() { return "Interpolation delimiter [begin: '" + begin + "', end: '" + end + "']"; } } MultiDelimiterInterpolatorFilterReader.java000066400000000000000000000410631242026660100450400ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/multi/* * The Apache Software License, Version 1.1 * * Copyright (c) 2002-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.codehaus.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "Ant" and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact codehaus@codehaus.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.codehaus.plexus.interpolation.multi; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.Interpolator; import org.codehaus.plexus.interpolation.RecursionInterceptor; import org.codehaus.plexus.interpolation.SimpleRecursionInterceptor; import java.io.FilterReader; import java.io.IOException; import java.io.Reader; import java.util.LinkedHashSet; /** * A FilterReader implementation, that works with Interpolator interface instead of it's own interpolation * implementation. This implementation is heavily based on org.codehaus.plexus.util.InterpolationFilterReader. * * @author cstamas * @version $Id: InterpolatorFilterReader.java 8351 2009-08-20 22:25:14Z jdcasey $ */ public class MultiDelimiterInterpolatorFilterReader extends FilterReader { /** Interpolator used to interpolate */ private Interpolator interpolator; /** * @since 1.12 */ private RecursionInterceptor recursionInterceptor; /** replacement text from a token */ private String replaceData = null; /** Index into replacement data */ private int replaceIndex = -1; /** Index into previous data */ private int previousIndex = -1; /** Default begin token. */ public static final String DEFAULT_BEGIN_TOKEN = "${"; /** Default end token. */ public static final String DEFAULT_END_TOKEN = "}"; /** true by default to preserve backward comp */ private boolean interpolateWithPrefixPattern = true; private String escapeString; private boolean useEscape = false; /** if true escapeString will be preserved \{foo} -> \{foo} */ private boolean preserveEscapeString = false; private LinkedHashSet delimiters = new LinkedHashSet(); private DelimiterSpecification currentSpec; private String beginToken; private String originalBeginToken; private String endToken; /** * this constructor use default begin token ${ and default end token } * @param in reader to use * @param interpolator interpolator instance to use */ public MultiDelimiterInterpolatorFilterReader( Reader in, Interpolator interpolator ) { this( in, interpolator, new SimpleRecursionInterceptor() ); } /** * @param in reader to use * @param interpolator interpolator instance to use * @param ri The {@link RecursionInterceptor} to use to prevent recursive expressions. * @since 1.12 */ public MultiDelimiterInterpolatorFilterReader( Reader in, Interpolator interpolator, RecursionInterceptor ri ) { super( in ); this.interpolator = interpolator; // always cache answers, since we'll be sending in pure expressions, not mixed text. this.interpolator.setCacheAnswers( true ); recursionInterceptor = ri; delimiters.add( DelimiterSpecification.DEFAULT_SPEC ); } public MultiDelimiterInterpolatorFilterReader addDelimiterSpec( String delimiterSpec ) { if ( delimiterSpec == null ) { return this; } delimiters.add( DelimiterSpecification.parse( delimiterSpec ) ); return this; } public boolean removeDelimiterSpec( String delimiterSpec ) { if ( delimiterSpec == null ) { return false; } return delimiters.remove( DelimiterSpecification.parse( delimiterSpec ) ); } public MultiDelimiterInterpolatorFilterReader setDelimiterSpecs( LinkedHashSet specs ) { delimiters.clear(); for ( String spec : specs ) { if ( spec == null ) { continue; } delimiters.add( DelimiterSpecification.parse( spec ) ); } return this; } /** * Skips characters. This method will block until some characters are available, an I/O error occurs, or the end of * the stream is reached. * * @param n The number of characters to skip * @return the number of characters actually skipped * @exception IllegalArgumentException If n is negative. * @exception IOException If an I/O error occurs */ public long skip( long n ) throws IOException { if ( n < 0L ) { throw new IllegalArgumentException( "skip value is negative" ); } for ( long i = 0; i < n; i++ ) { if ( read() == -1 ) { return i; } } return n; } /** * Reads characters into a portion of an array. This method will block until some input is available, an I/O error * occurs, or the end of the stream is reached. * * @param cbuf Destination buffer to write characters to. Must not be null. * @param off Offset at which to start storing characters. * @param len Maximum number of characters to read. * @return the number of characters read, or -1 if the end of the stream has been reached * @exception IOException If an I/O error occurs */ public int read( char cbuf[], int off, int len ) throws IOException { for ( int i = 0; i < len; i++ ) { int ch = read(); if ( ch == -1 ) { if ( i == 0 ) { return -1; } else { return i; } } cbuf[off + i] = (char) ch; } return len; } /** * Returns the next character in the filtered stream, replacing tokens from the original stream. * * @return the next character in the resulting stream, or -1 if the end of the resulting stream has been reached * @exception IOException if the underlying stream throws an IOException during reading */ public int read() throws IOException { if ( replaceIndex != -1 && replaceIndex < replaceData.length() ) { int ch = replaceData.charAt( replaceIndex++ ); if ( replaceIndex >= replaceData.length() ) { replaceIndex = -1; } return ch; } int ch = -1; if ( previousIndex != -1 && previousIndex < this.endToken.length() ) { ch = this.endToken.charAt( previousIndex++ ); } else { ch = in.read(); } boolean inEscape = false; if ( ( inEscape = ( useEscape && ch == escapeString.charAt( 0 ) ) ) || reselectDelimiterSpec( ch ) ) { StringBuilder key = new StringBuilder( ); key.append( (char) ch ); // this will happen when we're using an escape string, and ONLY then. boolean atEnd = false; if ( inEscape ) { for( int i = 0; i < escapeString.length() - 1; i++ ) { ch = in.read(); if ( ch == -1 ) { atEnd = true; break; } key.append( (char) ch ); } if ( !atEnd ) { ch = in.read(); if ( !reselectDelimiterSpec( ch ) ) { replaceData = key.toString(); replaceIndex = 1; return replaceData.charAt( 0 ); } else { key.append( (char) ch ); } } } int beginTokenMatchPos = 1; do { if ( atEnd ) { // didn't finish reading the escape string. break; } if ( previousIndex != -1 && previousIndex < this.endToken.length() ) { ch = this.endToken.charAt( previousIndex++ ); } else { ch = in.read(); } if ( ch != -1 ) { key.append( (char) ch ); if ( ( beginTokenMatchPos < this.originalBeginToken.length() ) && ( ch != this.originalBeginToken.charAt( beginTokenMatchPos ) ) ) { ch = -1; // not really EOF but to trigger code below break; } } else { break; } beginTokenMatchPos++; } while ( ch != this.endToken.charAt( 0 ) ); // now test endToken if ( ch != -1 && this.endToken.length() > 1 ) { int endTokenMatchPos = 1; do { if ( previousIndex != -1 && previousIndex < this.endToken.length() ) { ch = this.endToken.charAt( previousIndex++ ); } else { ch = in.read(); } if ( ch != -1 ) { key.append( (char) ch ); if ( ch != this.endToken.charAt( endTokenMatchPos++ ) ) { ch = -1; // not really EOF but to trigger code below break; } } else { break; } } while ( endTokenMatchPos < this.endToken.length() ); } // There is nothing left to read so we have the situation where the begin/end token // are in fact the same and as there is nothing left to read we have got ourselves // end of a token boundary so let it pass through. if ( ch == -1 ) { replaceData = key.toString(); replaceIndex = 1; return replaceData.charAt( 0 ); } String value = null; try { boolean escapeFound = false; if ( useEscape ) { if ( key.toString().startsWith( beginToken ) ) { String keyStr = key.toString(); if ( !preserveEscapeString ) { value = keyStr.substring( escapeString.length(), keyStr.length() ); } else { value = keyStr; } escapeFound = true; } } if ( !escapeFound ) { if ( interpolateWithPrefixPattern ) { value = interpolator.interpolate( key.toString(), "", recursionInterceptor ); } else { value = interpolator.interpolate( key.toString(), recursionInterceptor ); } } } catch ( InterpolationException e ) { IllegalArgumentException error = new IllegalArgumentException( e.getMessage() ); error.initCause( e ); throw error; } if ( value != null ) { if ( value.length() != 0 ) { replaceData = value; replaceIndex = 0; } return read(); } else { previousIndex = 0; replaceData = key.substring( 0, key.length() - this.endToken.length() ); replaceIndex = 0; return this.beginToken.charAt( 0 ); } } return ch; } private boolean reselectDelimiterSpec( int ch ) { for ( DelimiterSpecification spec : delimiters ) { if ( ch == spec.getBegin().charAt( 0 ) ) { currentSpec = spec; originalBeginToken = currentSpec.getBegin(); beginToken = useEscape ? escapeString + originalBeginToken : originalBeginToken; endToken = currentSpec.getEnd(); return true; } } return false; } public boolean isInterpolateWithPrefixPattern() { return interpolateWithPrefixPattern; } public void setInterpolateWithPrefixPattern( boolean interpolateWithPrefixPattern ) { this.interpolateWithPrefixPattern = interpolateWithPrefixPattern; } public String getEscapeString() { return escapeString; } public void setEscapeString( String escapeString ) { // TODO NPE if escapeString is null ? if ( escapeString != null && escapeString.length() >= 1 ) { this.escapeString = escapeString; this.useEscape = escapeString != null && escapeString.length() >= 1; } } public boolean isPreserveEscapeString() { return preserveEscapeString; } public void setPreserveEscapeString( boolean preserveEscapeString ) { this.preserveEscapeString = preserveEscapeString; } public RecursionInterceptor getRecursionInterceptor() { return recursionInterceptor; } public MultiDelimiterInterpolatorFilterReader setRecursionInterceptor( RecursionInterceptor recursionInterceptor ) { this.recursionInterceptor = recursionInterceptor; return this; } } MultiDelimiterStringSearchInterpolator.java000066400000000000000000000312351242026660100450640ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/multipackage org.codehaus.plexus.interpolation.multi; /* * Copyright 2001-2009 Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.InterpolationCycleException; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.InterpolationPostProcessor; import org.codehaus.plexus.interpolation.Interpolator; import org.codehaus.plexus.interpolation.RecursionInterceptor; import org.codehaus.plexus.interpolation.SimpleRecursionInterceptor; import org.codehaus.plexus.interpolation.ValueSource; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; public class MultiDelimiterStringSearchInterpolator implements Interpolator { private static final int MAX_TRIES = 10; private Map existingAnswers = new HashMap(); private List valueSources = new ArrayList(); private List postProcessors = new ArrayList(); private boolean cacheAnswers = false; private LinkedHashSet delimiters = new LinkedHashSet(); private String escapeString; public MultiDelimiterStringSearchInterpolator() { delimiters.add( DelimiterSpecification.DEFAULT_SPEC ); } public MultiDelimiterStringSearchInterpolator addDelimiterSpec( String delimiterSpec ) { if ( delimiterSpec == null ) { return this; } delimiters.add( DelimiterSpecification.parse( delimiterSpec ) ); return this; } public boolean removeDelimiterSpec( String delimiterSpec ) { if ( delimiterSpec == null ) { return false; } return delimiters.remove( DelimiterSpecification.parse( delimiterSpec ) ); } public MultiDelimiterStringSearchInterpolator withValueSource( ValueSource vs ) { addValueSource( vs ); return this; } public MultiDelimiterStringSearchInterpolator withPostProcessor( InterpolationPostProcessor postProcessor ) { addPostProcessor( postProcessor ); return this; } /** * {@inheritDoc} */ public void addValueSource( ValueSource valueSource ) { valueSources.add( valueSource ); } /** * {@inheritDoc} */ public void removeValuesSource( ValueSource valueSource ) { valueSources.remove( valueSource ); } /** * {@inheritDoc} */ public void addPostProcessor( InterpolationPostProcessor postProcessor ) { postProcessors.add( postProcessor ); } /** * {@inheritDoc} */ public void removePostProcessor( InterpolationPostProcessor postProcessor ) { postProcessors.remove( postProcessor ); } public String interpolate( String input, String thisPrefixPattern ) throws InterpolationException { return interpolate( input, new SimpleRecursionInterceptor() ); } public String interpolate( String input, String thisPrefixPattern, RecursionInterceptor recursionInterceptor ) throws InterpolationException { return interpolate( input, recursionInterceptor ); } public String interpolate( String input ) throws InterpolationException { return interpolate( input, new SimpleRecursionInterceptor() ); } /** * Entry point for recursive resolution of an expression and all of its nested expressions. * * @todo Ensure unresolvable expressions don't trigger infinite recursion. */ public String interpolate( String input, RecursionInterceptor recursionInterceptor ) throws InterpolationException { try { return interpolate( input, recursionInterceptor, new HashSet() ); } finally { if ( !cacheAnswers ) { existingAnswers.clear(); } } } private String interpolate( String input, RecursionInterceptor recursionInterceptor, Set unresolvable ) throws InterpolationException { if ( input == null ) { // return empty String to prevent NPE too return ""; } StringBuilder result = new StringBuilder( input.length() * 2 ); String lastResult = input; int tries = 0; do { tries++; if ( result.length() > 0 ) { lastResult = result.toString(); result.setLength( 0 ); } int startIdx = -1; int endIdx = -1; DelimiterSpecification selectedSpec = null; while( ( selectedSpec = select( input, endIdx ) ) != null ) { String startExpr = selectedSpec.getBegin(); String endExpr = selectedSpec.getEnd(); startIdx = selectedSpec.getNextStartIndex(); result.append( input, endIdx + 1, startIdx ); endIdx = input.indexOf( endExpr, startIdx + 1 ); if ( endIdx < 0 ) { break; } String wholeExpr = input.substring( startIdx, endIdx + endExpr.length() ); String realExpr = wholeExpr.substring( startExpr.length(), wholeExpr.length() - endExpr.length() ); if ( startIdx >= 0 && escapeString != null && escapeString.length() > 0 ) { int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString.length(); if ( startEscapeIdx >= 0 ) { String escape = input.substring( startEscapeIdx, startIdx ); if ( escape != null && escapeString.equals( escape ) ) { result.append( wholeExpr ); result.replace( startEscapeIdx, startEscapeIdx + escapeString.length(), "" ); continue; } } } boolean resolved = false; if ( !unresolvable.contains( wholeExpr ) ) { if ( realExpr.startsWith( "." ) ) { realExpr = realExpr.substring( 1 ); } if ( recursionInterceptor.hasRecursiveExpression( realExpr ) ) { throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr ); } recursionInterceptor.expressionResolutionStarted( realExpr ); Object value = existingAnswers.get( realExpr ); Object bestAnswer = null; for ( ValueSource vs : valueSources ) { if (value != null ) break; value = vs.getValue( realExpr ); if ( value != null && value.toString().contains( wholeExpr ) ) { bestAnswer = value; value = null; } } // this is the simplest recursion check to catch exact recursion // (non synonym), and avoid the extra effort of more string // searching. if ( value == null && bestAnswer != null ) { throw new InterpolationCycleException( recursionInterceptor, realExpr, wholeExpr ); } if ( value != null ) { value = interpolate( String.valueOf( value ), recursionInterceptor, unresolvable ); if ( postProcessors != null && !postProcessors.isEmpty() ) { for ( Object postProcessor1 : postProcessors ) { InterpolationPostProcessor postProcessor = (InterpolationPostProcessor) postProcessor1; Object newVal = postProcessor.execute( realExpr, value ); if ( newVal != null ) { value = newVal; break; } } } // could use: // result = matcher.replaceFirst( stringValue ); // but this could result in multiple lookups of stringValue, and replaceAll is not correct behaviour result.append( String.valueOf( value ) ); resolved = true; } else { unresolvable.add( wholeExpr ); } recursionInterceptor.expressionResolutionFinished( realExpr ); } if ( !resolved ) { result.append( wholeExpr ); } if ( endIdx > -1 ) { endIdx += endExpr.length() - 1; } } if ( endIdx == -1 && startIdx > -1 ) { result.append( input, startIdx, input.length() ); } else if ( endIdx < input.length() ) { result.append( input, endIdx + 1, input.length() ); } } while( !lastResult.equals( result.toString() ) && tries < MAX_TRIES ); return result.toString(); } private DelimiterSpecification select( String input, int lastEndIdx ) { DelimiterSpecification selected = null; for ( DelimiterSpecification spec : delimiters ) { spec.clearNextStart(); if ( selected == null ) { int idx = input.indexOf( spec.getBegin(), lastEndIdx + 1 ); if ( idx > -1 ) { spec.setNextStartIndex( idx ); selected = spec; } } } return selected; } /** * Return any feedback messages and errors that were generated - but suppressed - during the interpolation process. * Since unresolvable expressions will be left in the source string as-is, this feedback is optional, and will only * be useful for debugging interpolation problems. * * @return a {@link List} that may be interspersed with {@link String} and {@link Throwable} instances. */ public List getFeedback() { List messages = new ArrayList(); for ( ValueSource vs : valueSources ) { List feedback = vs.getFeedback(); if ( feedback != null && !feedback.isEmpty() ) { messages.addAll( feedback ); } } return messages; } /** * Clear the feedback messages from previous interpolate(..) calls. */ public void clearFeedback() { for ( ValueSource vs : valueSources ) { vs.clearFeedback(); } } public boolean isCacheAnswers() { return cacheAnswers; } public void setCacheAnswers( boolean cacheAnswers ) { this.cacheAnswers = cacheAnswers; } public void clearAnswers() { existingAnswers.clear(); } public String getEscapeString() { return escapeString; } public void setEscapeString( String escapeString ) { this.escapeString = escapeString; } public MultiDelimiterStringSearchInterpolator setDelimiterSpecs( LinkedHashSet specs ) { delimiters.clear(); for ( String spec : specs ) { if ( spec == null ) { continue; } delimiters.add( DelimiterSpecification.parse( spec ) ); } return this; } } 000077500000000000000000000000001242026660100344605ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/objectFieldBasedObjectInterpolator.java000066400000000000000000000511731242026660100430460ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/objectpackage org.codehaus.plexus.interpolation.object; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.Interpolator; import org.codehaus.plexus.interpolation.RecursionInterceptor; import org.codehaus.plexus.interpolation.SimpleRecursionInterceptor; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; /** * Reflectively traverses an object graph and uses an {@link Interpolator} instance to resolve any String fields in the * graph. *
*
* NOTE: This code is based on a reimplementation of ModelInterpolator in * maven-project 2.1.0-M1, which became a performance bottleneck when the * interpolation process became a hotspot. * * @author jdcasey */ public class FieldBasedObjectInterpolator implements ObjectInterpolator { public static final Set DEFAULT_BLACKLISTED_FIELD_NAMES; public static final Set DEFAULT_BLACKLISTED_PACKAGE_PREFIXES; private static final Map fieldsByClass = new WeakHashMap(); private static final Map fieldIsPrimitiveByClass = new WeakHashMap(); static { Set blacklistedFields = new HashSet(); blacklistedFields.add( "parent" ); DEFAULT_BLACKLISTED_FIELD_NAMES = Collections.unmodifiableSet( blacklistedFields ); Set blacklistedPackages = new HashSet(); blacklistedPackages.add( "java" ); DEFAULT_BLACKLISTED_PACKAGE_PREFIXES = Collections.unmodifiableSet( blacklistedPackages ); } /** * Clear out the Reflection caches kept for the most expensive operations encountered: field lookup and primitive * queries for fields. These caches are static since they apply at the class level, not the instance level. */ public static void clearCaches() { fieldsByClass.clear(); fieldIsPrimitiveByClass.clear(); } private Set blacklistedFieldNames; private Set blacklistedPackagePrefixes; private List warnings = new ArrayList(); /** * Use the default settings for blacklisted fields and packages, where fields named 'parent' and classes in packages * starting with 'java' will not be interpolated. */ public FieldBasedObjectInterpolator() { this.blacklistedFieldNames = DEFAULT_BLACKLISTED_FIELD_NAMES; this.blacklistedPackagePrefixes = DEFAULT_BLACKLISTED_PACKAGE_PREFIXES; } /** * Use the given black-lists to limit the interpolation of fields and classes (by package). * * @param blacklistedFieldNames The list of field names to ignore * @param blacklistedPackagePrefixes The list of package prefixes whose classes should be ignored */ public FieldBasedObjectInterpolator( Set blacklistedFieldNames, Set blacklistedPackagePrefixes ) { this.blacklistedFieldNames = blacklistedFieldNames; this.blacklistedPackagePrefixes = blacklistedPackagePrefixes; } /** * Returns true if the last interpolation execution generated warnings. */ public boolean hasWarnings() { return warnings != null && !warnings.isEmpty(); } /** * Retrieve the {@link List} of warnings ({@link ObjectInterpolationWarning} * instances) generated during the last interpolation execution. */ public List getWarnings() { return new ArrayList( warnings ); } /** * Using reflective field access and mutation, traverse the object graph from the given starting point and * interpolate any Strings found in that graph using the given {@link Interpolator}. Limits to this process can be * managed using the black lists configured in the constructor. * * @param target The starting point of the object graph to traverse * @param interpolator The {@link Interpolator} used to resolve any Strings encountered during traversal. *

* NOTE: Uses {@link SimpleRecursionInterceptor}. */ public void interpolate( Object target, Interpolator interpolator ) throws InterpolationException { interpolate( target, interpolator, new SimpleRecursionInterceptor() ); } /** * Using reflective field access and mutation, traverse the object graph from the given starting point and * interpolate any Strings found in that graph using the given {@link Interpolator}. Limits to this process can be * managed using the black lists configured in the constructor. * * @param target The starting point of the object graph to traverse * @param interpolator The {@link Interpolator} used to resolve any Strings encountered during traversal. * @param recursionInterceptor The {@link RecursionInterceptor} used to detect cyclical expressions in the graph */ public void interpolate( Object target, Interpolator interpolator, RecursionInterceptor recursionInterceptor ) throws InterpolationException { warnings.clear(); InterpolateObjectAction action = new InterpolateObjectAction( target, interpolator, recursionInterceptor, blacklistedFieldNames, blacklistedPackagePrefixes, warnings ); InterpolationException error = (InterpolationException) AccessController.doPrivileged( action ); if ( error != null ) { throw error; } } private static final class InterpolateObjectAction implements PrivilegedAction { private final LinkedList interpolationTargets; private final Interpolator interpolator; private final Set blacklistedFieldNames; private final String[] blacklistedPackagePrefixes; private final List warningCollector; private final RecursionInterceptor recursionInterceptor; /** * Setup an object graph traversal for the given target starting point. This will initialize a queue of objects * to traverse and interpolate by adding the target object. */ public InterpolateObjectAction( Object target, Interpolator interpolator, RecursionInterceptor recursionInterceptor, Set blacklistedFieldNames, Set blacklistedPackagePrefixes, List warningCollector ) { this.recursionInterceptor = recursionInterceptor; this.blacklistedFieldNames = blacklistedFieldNames; this.warningCollector = warningCollector; this.blacklistedPackagePrefixes = (String[]) blacklistedPackagePrefixes.toArray( new String[blacklistedPackagePrefixes.size()] ); this.interpolationTargets = new LinkedList(); interpolationTargets.add( new InterpolationTarget( target, "" ) ); this.interpolator = interpolator; } /** * As long as the traversal queue is non-empty, traverse the next object in the queue. If an interpolation error * occurs, return it immediately. */ public Object run() { while ( !interpolationTargets.isEmpty() ) { InterpolationTarget target = interpolationTargets.removeFirst(); try { traverseObjectWithParents( target.value.getClass(), target ); } catch ( InterpolationException e ) { return e; } } return null; } /** * Traverse the given object, interpolating any String fields and adding non-primitive field values to the * interpolation queue for later processing. */ private void traverseObjectWithParents( Class cls, InterpolationTarget target ) throws InterpolationException { Object obj = target.value; String basePath = target.path; if ( cls == null ) { return; } if ( cls.isArray() ) { evaluateArray( obj, basePath ); } else if ( isQualifiedForInterpolation( cls ) ) { Field[] fields = fieldsByClass.get( cls ); if ( fields == null ) { fields = cls.getDeclaredFields(); fieldsByClass.put( cls, fields ); } for ( Field field : fields ) { Class type = field.getType(); if ( isQualifiedForInterpolation( field, type ) ) { boolean isAccessible = field.isAccessible(); synchronized ( cls ) { field.setAccessible( true ); try { try { if ( String.class == type ) { interpolateString( obj, field ); } else if ( Collection.class.isAssignableFrom( type ) ) { if ( interpolateCollection( obj, basePath, field ) ) { continue; } } else if ( Map.class.isAssignableFrom( type ) ) { interpolateMap( obj, basePath, field ); } else { interpolateObject( obj, basePath, field ); } } catch ( IllegalArgumentException e ) { warningCollector.add( new ObjectInterpolationWarning( "Failed to interpolate field. Skipping.", basePath + "." + field.getName(), e ) ); } catch ( IllegalAccessException e ) { warningCollector.add( new ObjectInterpolationWarning( "Failed to interpolate field. Skipping.", basePath + "." + field.getName(), e ) ); } } finally { field.setAccessible( isAccessible ); } } } } traverseObjectWithParents( cls.getSuperclass(), target ); } } private void interpolateObject( Object obj, String basePath, Field field ) throws IllegalAccessException, InterpolationException { Object value = field.get( obj ); if ( value != null ) { if ( field.getType().isArray() ) { evaluateArray( value, basePath + "." + field.getName() ); } else { interpolationTargets.add( new InterpolationTarget( value, basePath + "." + field.getName() ) ); } } } private void interpolateMap( Object obj, String basePath, Field field ) throws IllegalAccessException, InterpolationException { Map m = (Map) field.get( obj ); if ( m != null && !m.isEmpty() ) { for ( Object o : m.entrySet() ) { Map.Entry entry = (Map.Entry) o; Object value = entry.getValue(); if ( value != null ) { if ( String.class == value.getClass() ) { String interpolated = interpolator.interpolate( (String) value, recursionInterceptor ); if ( !interpolated.equals( value ) ) { try { entry.setValue( interpolated ); } catch ( UnsupportedOperationException e ) { warningCollector.add( new ObjectInterpolationWarning( "Field is an unmodifiable collection. Skipping interpolation.", basePath + "." + field.getName(), e ) ); continue; } } } else { if ( value.getClass().isArray() ) { evaluateArray( value, basePath + "." + field.getName() ); } else { interpolationTargets.add( new InterpolationTarget( value, basePath + "." + field.getName() ) ); } } } } } } private boolean interpolateCollection( Object obj, String basePath, Field field ) throws IllegalAccessException, InterpolationException { Collection c = (Collection) field.get( obj ); if ( c != null && !c.isEmpty() ) { List originalValues = new ArrayList( c ); try { c.clear(); } catch ( UnsupportedOperationException e ) { warningCollector.add( new ObjectInterpolationWarning( "Field is an unmodifiable collection. Skipping interpolation.", basePath + "." + field.getName(), e ) ); return true; } for ( Object value : originalValues ) { if ( value != null ) { if ( String.class == value.getClass() ) { String interpolated = interpolator.interpolate( (String) value, recursionInterceptor ); if ( !interpolated.equals( value ) ) { c.add( interpolated ); } else { c.add( value ); } } else { c.add( value ); if ( value.getClass().isArray() ) { evaluateArray( value, basePath + "." + field.getName() ); } else { interpolationTargets.add( new InterpolationTarget( value, basePath + "." + field.getName() ) ); } } } else { // add the null back in...not sure what else to do... c.add( value ); } } } return false; } private void interpolateString( Object obj, Field field ) throws IllegalAccessException, InterpolationException { String value = (String) field.get( obj ); if ( value != null ) { String interpolated = interpolator.interpolate( value, recursionInterceptor ); if ( !interpolated.equals( value ) ) { field.set( obj, interpolated ); } } } /** * Using the package-prefix blacklist, determine whether the given class is qualified for interpolation, or * whether it should be ignored. */ private boolean isQualifiedForInterpolation( Class cls ) { String pkgName = cls.getPackage().getName(); for ( String prefix : blacklistedPackagePrefixes ) { if ( pkgName.startsWith( prefix ) ) { return false; } } return true; } /** * Using the field-name blacklist and the primitive-field cache, determine whether the given field in the given * class is qualified for interpolation. Primitive fields and fields listed in the blacklist will be ignored. * The primitive-field cache is used to improve the performance of the reflective operations in this method, * since this method is a hotspot. */ private boolean isQualifiedForInterpolation( Field field, Class fieldType ) { if ( !fieldIsPrimitiveByClass.containsKey( fieldType ) ) { fieldIsPrimitiveByClass.put( fieldType, fieldType.isPrimitive() ); } //noinspection UnnecessaryUnboxing if ( fieldIsPrimitiveByClass.get( fieldType ) ) { return false; } return !blacklistedFieldNames.contains( field.getName() ); } /** * Traverse the elements of an array, and interpolate any qualified objects or add them to the traversal queue. */ private void evaluateArray( Object target, String basePath ) throws InterpolationException { int len = Array.getLength( target ); for ( int i = 0; i < len; i++ ) { Object value = Array.get( target, i ); if ( value != null ) { if ( String.class == value.getClass() ) { String interpolated = interpolator.interpolate( (String) value, recursionInterceptor ); if ( !interpolated.equals( value ) ) { Array.set( target, i, interpolated ); } } else { interpolationTargets.add( new InterpolationTarget( value, basePath + "[" + i + "]" ) ); } } } } } private static final class InterpolationTarget { private Object value; private String path; private InterpolationTarget( Object value, String path ) { this.value = value; this.path = path; } } } ObjectInterpolationWarning.java000066400000000000000000000044131242026660100426310ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/objectpackage org.codehaus.plexus.interpolation.object; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.io.PrintWriter; import java.io.StringWriter; /** * Represents a warning that occurred while interpolating an object graph. These * warnings may not have a serious effect, so they don't cause an exception to be * thrown. Each warning contains the path through the object graph from the point * of entry to the place where the warning occurred, along with a message containing * the actual warning and possibly a {@link Throwable} cause. * * @author jdcasey */ public class ObjectInterpolationWarning { private final String message; private Throwable cause; private final String path; public ObjectInterpolationWarning( String path, String message ) { this.path = path; this.message = message; } public ObjectInterpolationWarning( String path, String message, Throwable cause ) { this.path = path; this.message = message; this.cause = cause; } public String getPath() { return path; } public String getMessage() { return message; } public Throwable getCause() { return cause; } public String toString() { if ( cause == null ) { return path + ": " + message; } else { StringWriter w = new StringWriter(); PrintWriter pw = new PrintWriter( w ); pw.print( path ); pw.print( ": " ); pw.println( message ); pw.println( "Cause: " ); cause.printStackTrace( pw ); return w.toString(); } } } ObjectInterpolator.java000066400000000000000000000046571242026660100411500ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/objectpackage org.codehaus.plexus.interpolation.object; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.List; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.Interpolator; import org.codehaus.plexus.interpolation.RecursionInterceptor; /** * Traverses an object graph and uses an {@link Interpolator} instance to resolve any String values in the * graph. * * @author jdcasey */ public interface ObjectInterpolator { /** * Traverse the object graph from the given starting point and interpolate * any Strings found in that graph using the given {@link Interpolator}. * * @param target The starting point of the object graph to traverse * @param interpolator The {@link Interpolator} used to resolve any Strings encountered during traversal. */ void interpolate( Object target, Interpolator interpolator ) throws InterpolationException; /** * Traverse the object graph from the given starting point and interpolate * any Strings found in that graph using the given {@link Interpolator}. * * @param target The starting point of the object graph to traverse * @param interpolator The {@link Interpolator} used to resolve any Strings encountered during traversal. * @param recursionInterceptor The {@link RecursionInterceptor} used to detect cyclical expressions in the graph */ void interpolate( Object target, Interpolator interpolator, RecursionInterceptor recursionInterceptor ) throws InterpolationException; /** * Returns true if the last interpolation execution generated warnings. */ boolean hasWarnings(); /** * Retrieve the {@link List} of warnings ({@link ObjectInterpolationWarning} * instances) generated during the last interpolation execution. */ List getWarnings(); } plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/os/000077500000000000000000000000001242026660100337125ustar00rootroot00000000000000OperatingSystemUtils.java000066400000000000000000000050621242026660100406570ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/ospackage org.codehaus.plexus.interpolation.os; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import java.io.IOException; import java.util.Locale; import java.util.Map; import java.util.Properties; /** * NOTE: This class was copied from plexus-utils, to allow this library * to stand completely self-contained. *
* @author Trygve Laugstøl * @version $Id$ */ public final class OperatingSystemUtils { private OperatingSystemUtils() { } public static Properties getSystemEnvVars() throws IOException { return getSystemEnvVars( true ); } /** * Return the shell environment variables. If caseSensitive == true, then envar * keys will all be upper-case. * * @param caseSensitive Whether environment variable keys should be treated case-sensitively. * @return Properties object of (possibly modified) envar keys mapped to their values. * @throws IOException */ public static Properties getSystemEnvVars( boolean caseSensitive ) throws IOException { Properties envVars = new Properties(); Map envs = System.getenv(); for ( String key : envs.keySet() ) { String value = envs.get( key ); if ( !caseSensitive) { key = key.toUpperCase( Locale.ENGLISH ); } envVars.put( key, value ); } return envVars; } } Os.java000066400000000000000000000317311242026660100350640ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/os/* * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "Ant" and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.codehaus.plexus.interpolation.os; import java.util.HashSet; import java.util.Locale; import java.util.Set; /** * NOTE: This class was copied from plexus-utils, to allow this library * to stand completely self-contained. *
* Condition that tests the OS type. * * @author Stefan Bodewig * @author Magesh Umasankar * @author Brian Fox * @since 1.0 * @version $Id$ */ public class Os { // define the families for easier reference public static final String FAMILY_DOS = "dos"; public static final String FAMILY_MAC = "mac"; public static final String FAMILY_NETWARE = "netware"; public static final String FAMILY_OS2 = "os/2"; public static final String FAMILY_TANDEM = "tandem"; public static final String FAMILY_UNIX = "unix"; public static final String FAMILY_WINDOWS = "windows"; public static final String FAMILY_WIN9X = "win9x"; public static final String FAMILY_ZOS = "z/os"; public static final String FAMILY_OS400 = "os/400"; public static final String FAMILY_OPENVMS = "openvms"; // store the valid families private static final Set validFamilies = setValidFamilies(); // get the current info private static final String PATH_SEP = System.getProperty( "path.separator" ); public static final String OS_NAME = System.getProperty( "os.name" ).toLowerCase( Locale.US ); public static final String OS_ARCH = System.getProperty( "os.arch" ).toLowerCase( Locale.US ); public static final String OS_VERSION = System.getProperty( "os.version" ).toLowerCase( Locale.US ); // Make sure this method is called after static fields it depends on have been set! public static final String OS_FAMILY = getOsFamily(); private String family; private String name; private String version; private String arch; /** * Default constructor */ public Os() { } /** * Constructor that sets the family attribute * * @param family a String value */ public Os( String family ) { setFamily( family ); } /** * Initializes the set of valid families. */ private static Set setValidFamilies() { Set valid = new HashSet(); valid.add( FAMILY_DOS ); valid.add( FAMILY_MAC ); valid.add( FAMILY_NETWARE ); valid.add( FAMILY_OS2 ); valid.add( FAMILY_TANDEM ); valid.add( FAMILY_UNIX ); valid.add( FAMILY_WINDOWS ); valid.add( FAMILY_WIN9X ); valid.add( FAMILY_ZOS ); valid.add( FAMILY_OS400 ); valid.add( FAMILY_OPENVMS ); return valid; } /** * Sets the desired OS family type * * @param f The OS family type desired
* Possible values:
*

    *
  • dos
  • *
  • mac
  • *
  • netware
  • *
  • os/2
  • *
  • tandem
  • *
  • unix
  • *
  • windows
  • *
  • win9x
  • *
  • z/os
  • *
  • os/400
  • *
  • openvms
  • *
*/ public void setFamily( String f ) { family = f.toLowerCase( Locale.US ); } /** * Sets the desired OS name * * @param name The OS name */ public void setName( String name ) { this.name = name.toLowerCase( Locale.US ); } /** * Sets the desired OS architecture * * @param arch The OS architecture */ public void setArch( String arch ) { this.arch = arch.toLowerCase( Locale.US ); } /** * Sets the desired OS version * * @param version The OS version */ public void setVersion( String version ) { this.version = version.toLowerCase( Locale.US ); } /** * Determines if the current OS matches the type of that * set in setFamily. * * @see Os#setFamily(String) */ public boolean eval() throws Exception { return isOs( family, name, arch, version ); } /** * Determines if the current OS matches the given OS * family. * * @param family the family to check for * @return true if the OS matches * @since 1.0 */ public static boolean isFamily( String family ) { return isOs( family, null, null, null ); } /** * Determines if the current OS matches the given OS * name. * * @param name the OS name to check for * @return true if the OS matches * @since 1.0 */ public static boolean isName( String name ) { return isOs( null, name, null, null ); } /** * Determines if the current OS matches the given OS * architecture. * * @param arch the OS architecture to check for * @return true if the OS matches * @since 1.0 */ public static boolean isArch( String arch ) { return isOs( null, null, arch, null ); } /** * Determines if the current OS matches the given OS * version. * * @param version the OS version to check for * @return true if the OS matches * @since 1.0 */ public static boolean isVersion( String version ) { return isOs( null, null, null, version ); } /** * Determines if the current OS matches the given OS * family, name, architecture and version. * * The name, archictecture and version are compared to * the System properties os.name, os.version and os.arch * in a case-independent way. * * @param family The OS family * @param name The OS name * @param arch The OS architecture * @param version The OS version * @return true if the OS matches * @since 1.0 */ public static boolean isOs( String family, String name, String arch, String version ) { boolean retValue = false; if ( family != null || name != null || arch != null || version != null ) { boolean isFamily = true; boolean isName = true; boolean isArch = true; boolean isVersion = true; if ( family != null ) { if ( family.equalsIgnoreCase( FAMILY_WINDOWS ) ) { isFamily = OS_NAME.contains( FAMILY_WINDOWS ); } else if ( family.equalsIgnoreCase( FAMILY_OS2 ) ) { isFamily = OS_NAME.contains( FAMILY_OS2 ); } else if ( family.equalsIgnoreCase( FAMILY_NETWARE ) ) { isFamily = OS_NAME.contains( FAMILY_NETWARE ); } else if ( family.equalsIgnoreCase( FAMILY_DOS ) ) { isFamily = PATH_SEP.equals( ";" ) && !isFamily( FAMILY_NETWARE ); } else if ( family.equalsIgnoreCase( FAMILY_MAC ) ) { isFamily = OS_NAME.contains( FAMILY_MAC ); } else if ( family.equalsIgnoreCase( FAMILY_TANDEM ) ) { isFamily = OS_NAME.contains( "nonstop_kernel" ); } else if ( family.equalsIgnoreCase( FAMILY_UNIX ) ) { isFamily = PATH_SEP.equals( ":" ) && !isFamily( FAMILY_OPENVMS ) && ( !isFamily( FAMILY_MAC ) || OS_NAME.endsWith( "x" ) ); } else if ( family.equalsIgnoreCase( FAMILY_WIN9X ) ) { isFamily = isFamily( FAMILY_WINDOWS ) && ( OS_NAME.contains( "95" ) || OS_NAME.contains( "98" ) || OS_NAME.contains( "me" ) || OS_NAME.contains( "ce" ) ); } else if ( family.equalsIgnoreCase( FAMILY_ZOS ) ) { isFamily = OS_NAME.contains( FAMILY_ZOS ) || OS_NAME.contains( "os/390" ); } else if ( family.equalsIgnoreCase( FAMILY_OS400 ) ) { isFamily = OS_NAME.contains( FAMILY_OS400 ); } else if ( family.equalsIgnoreCase( FAMILY_OPENVMS ) ) { isFamily = OS_NAME.contains( FAMILY_OPENVMS ); } else { isFamily = OS_NAME.contains( family.toLowerCase( Locale.US ) ); } } if ( name != null ) { isName = name.toLowerCase( Locale.US ).equals( OS_NAME ); } if ( arch != null ) { isArch = arch.toLowerCase( Locale.US ).equals( OS_ARCH ); } if ( version != null ) { isVersion = version.toLowerCase( Locale.US ).equals( OS_VERSION ); } retValue = isFamily && isName && isArch && isVersion; } return retValue; } /** * Helper method to determine the current OS family. * * @return name of current OS family. * @since 1.4.2 */ private static String getOsFamily() { // in case the order of static initialization is // wrong, get the list // safely. Set families = null; if ( !validFamilies.isEmpty() ) { families = validFamilies; } else { families = setValidFamilies(); } for ( String fam : families ) { if ( Os.isFamily( fam ) ) { return fam; } } return null; } /** * Helper method to check if the given family is in the * following list: *
    *
  • dos
  • *
  • mac
  • *
  • netware
  • *
  • os/2
  • *
  • tandem
  • *
  • unix
  • *
  • windows
  • *
  • win9x
  • *
  • z/os
  • *
  • os/400
  • *
  • openvms
  • *
* * @param theFamily the family to check. * @return true if one of the valid families. * @since 1.4.2 */ public static boolean isValidFamily( String theFamily ) { return ( validFamilies.contains( theFamily ) ); } /** * @return a copy of the valid families * @since 1.4.2 */ public static Set getValidFamilies() { return new HashSet( validFamilies ); } } 000077500000000000000000000000001242026660100353445ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/reflectionClassMap.java000066400000000000000000000362501242026660100377200ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/reflectionpackage org.codehaus.plexus.interpolation.reflection; /* ==================================================================== * Copyright 2001-2004 The Apache Software Foundation. * * 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. * ==================================================================== */ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Hashtable; import java.util.Map; /** * NOTE: This class was copied from plexus-utils, to allow this library * to stand completely self-contained. *
* A cache of introspection information for a specific class instance. * Keys {@link java.lang.Method} objects by a concatenation of the * method name and the names of classes that make up the parameters. * * @author Jason van Zyl * @author Bob McWhirter * @author Attila Szegedi * @author Geir Magnusson Jr. * @version $Id$ */ public class ClassMap { private static final class CacheMiss { } private static final CacheMiss CACHE_MISS = new CacheMiss(); private static final Object OBJECT = new Object(); /** * Class passed into the constructor used to as * the basis for the Method map. */ private Class clazz; /** * Cache of Methods, or CACHE_MISS, keyed by method * name and actual arguments used to find it. */ private Map methodCache = new Hashtable(); private MethodMap methodMap = new MethodMap(); /** * Standard constructor */ public ClassMap( Class clazz ) { this.clazz = clazz; populateMethodCache(); } /** * @return the class object whose methods are cached by this map. */ Class getCachedClass() { return clazz; } /** * Find a Method using the methodKey * provided. *

* Look in the methodMap for an entry. If found, * it'll either be a CACHE_MISS, in which case we * simply give up, or it'll be a Method, in which * case, we return it. *

* If nothing is found, then we must actually go * and introspect the method from the MethodMap. */ public Method findMethod( String name, Object[] params ) throws MethodMap.AmbiguousException { String methodKey = makeMethodKey( name, params ); Object cacheEntry = methodCache.get( methodKey ); if ( cacheEntry == CACHE_MISS ) { return null; } if ( cacheEntry == null ) { try { cacheEntry = methodMap.find( name, params ); } catch ( MethodMap.AmbiguousException ae ) { /* * that's a miss :) */ methodCache.put( methodKey, CACHE_MISS ); throw ae; } if ( cacheEntry == null ) { methodCache.put( methodKey, CACHE_MISS ); } else { methodCache.put( methodKey, cacheEntry ); } } // Yes, this might just be null. return (Method) cacheEntry; } /** * Populate the Map of direct hits. These * are taken from all the public methods * that our class provides. */ private void populateMethodCache() { /* * get all publicly accessible methods */ Method[] methods = getAccessibleMethods( clazz ); /* * map and cache them */ for ( Method method : methods ) { /* * now get the 'public method', the method declared by a * public interface or class. (because the actual implementing * class may be a facade... */ Method publicMethod = getPublicMethod( method ); /* * it is entirely possible that there is no public method for * the methods of this class (i.e. in the facade, a method * that isn't on any of the interfaces or superclass * in which case, ignore it. Otherwise, map and cache */ if ( publicMethod != null ) { methodMap.add( publicMethod ); methodCache.put( makeMethodKey( publicMethod ), publicMethod ); } } } /** * Make a methodKey for the given method using * the concatenation of the name and the * types of the method parameters. */ private String makeMethodKey( Method method ) { Class[] parameterTypes = method.getParameterTypes(); StringBuilder methodKey = new StringBuilder( method.getName() ); for ( Class parameterType : parameterTypes ) { /* * If the argument type is primitive then we want * to convert our primitive type signature to the * corresponding Object type so introspection for * methods with primitive types will work correctly. */ if ( parameterType.isPrimitive() ) { if ( parameterType.equals( Boolean.TYPE ) ) { methodKey.append( "java.lang.Boolean" ); } else if ( parameterType.equals( Byte.TYPE ) ) { methodKey.append( "java.lang.Byte" ); } else if ( parameterType.equals( Character.TYPE ) ) { methodKey.append( "java.lang.Character" ); } else if ( parameterType.equals( Double.TYPE ) ) { methodKey.append( "java.lang.Double" ); } else if ( parameterType.equals( Float.TYPE ) ) { methodKey.append( "java.lang.Float" ); } else if ( parameterType.equals( Integer.TYPE ) ) { methodKey.append( "java.lang.Integer" ); } else if ( parameterType.equals( Long.TYPE ) ) { methodKey.append( "java.lang.Long" ); } else if ( parameterType.equals( Short.TYPE ) ) { methodKey.append( "java.lang.Short" ); } } else { methodKey.append( parameterType.getName() ); } } return methodKey.toString(); } private static String makeMethodKey( String method, Object[] params ) { if (params.length == 0) { return method; } StringBuilder methodKey = new StringBuilder().append( method ); for ( Object arg : params ) { if ( arg == null ) { arg = OBJECT; } methodKey.append( arg.getClass().getName() ); } return methodKey.toString(); } /** * Retrieves public methods for a class. In case the class is not * public, retrieves methods with same signature as its public methods * from public superclasses and interfaces (if they exist). Basically * upcasts every method to the nearest acccessible method. */ private static Method[] getAccessibleMethods( Class clazz ) { Method[] methods = clazz.getMethods(); /* * Short circuit for the (hopefully) majority of cases where the * clazz is public */ if ( Modifier.isPublic( clazz.getModifiers() ) ) { return methods; } /* * No luck - the class is not public, so we're going the longer way. */ MethodInfo[] methodInfos = new MethodInfo[methods.length]; for ( int i = methods.length; i-- > 0; ) { methodInfos[i] = new MethodInfo( methods[i] ); } int upcastCount = getAccessibleMethods( clazz, methodInfos, 0 ); /* * Reallocate array in case some method had no accessible counterpart. */ if ( upcastCount < methods.length ) { methods = new Method[upcastCount]; } int j = 0; for ( MethodInfo methodInfo : methodInfos ) { if ( methodInfo.upcast ) { methods[j++] = methodInfo.method; } } return methods; } /** * Recursively finds a match for each method, starting with the class, and then * searching the superclass and interfaces. * * @param clazz Class to check * @param methodInfos array of methods we are searching to match * @param upcastCount current number of methods we have matched * @return count of matched methods */ private static int getAccessibleMethods( Class clazz, MethodInfo[] methodInfos, int upcastCount ) { int l = methodInfos.length; /* * if this class is public, then check each of the currently * 'non-upcasted' methods to see if we have a match */ if ( Modifier.isPublic( clazz.getModifiers() ) ) { for ( int i = 0; i < l && upcastCount < l; ++i ) { try { MethodInfo methodInfo = methodInfos[i]; if ( !methodInfo.upcast ) { methodInfo.tryUpcasting( clazz ); upcastCount++; } } catch ( NoSuchMethodException e ) { /* * Intentionally ignored - it means * it wasn't found in the current class */ } } /* * Short circuit if all methods were upcast */ if ( upcastCount == l ) { return upcastCount; } } /* * Examine superclass */ Class superclazz = clazz.getSuperclass(); if ( superclazz != null ) { upcastCount = getAccessibleMethods( superclazz, methodInfos, upcastCount ); /* * Short circuit if all methods were upcast */ if ( upcastCount == l ) { return upcastCount; } } /* * Examine interfaces. Note we do it even if superclazz == null. * This is redundant as currently java.lang.Object does not implement * any interfaces, however nothing guarantees it will not in future. */ Class[] interfaces = clazz.getInterfaces(); for ( int i = interfaces.length; i-- > 0; ) { upcastCount = getAccessibleMethods( interfaces[i], methodInfos, upcastCount ); /* * Short circuit if all methods were upcast */ if ( upcastCount == l ) { return upcastCount; } } return upcastCount; } /** * For a given method, retrieves its publicly accessible counterpart. * This method will look for a method with same name * and signature declared in a public superclass or implemented interface of this * method's declaring class. This counterpart method is publicly callable. * * @param method a method whose publicly callable counterpart is requested. * @return the publicly callable counterpart method. Note that if the parameter * method is itself declared by a public class, this method is an identity * function. */ public static Method getPublicMethod( Method method ) { Class clazz = method.getDeclaringClass(); /* * Short circuit for (hopefully the majority of) cases where the declaring * class is public. */ if ( ( clazz.getModifiers() & Modifier.PUBLIC ) != 0 ) { return method; } return getPublicMethod( clazz, method.getName(), method.getParameterTypes() ); } /** * Looks up the method with specified name and signature in the first public * superclass or implemented interface of the class. * * @param class the class whose method is sought * @param name the name of the method * @param paramTypes the classes of method parameters */ private static Method getPublicMethod( Class clazz, String name, Class[] paramTypes ) { /* * if this class is public, then try to get it */ if ( ( clazz.getModifiers() & Modifier.PUBLIC ) != 0 ) { try { return clazz.getMethod( name, paramTypes ); } catch ( NoSuchMethodException e ) { /* * If the class does not have the method, then neither its * superclass nor any of its interfaces has it so quickly return * null. */ return null; } } /* * try the superclass */ Class superclazz = clazz.getSuperclass(); if ( superclazz != null ) { Method superclazzMethod = getPublicMethod( superclazz, name, paramTypes ); if ( superclazzMethod != null ) { return superclazzMethod; } } /* * and interfaces */ for ( Class interface_ : clazz.getInterfaces() ) { Method interfaceMethod = getPublicMethod( interface_, name, paramTypes ); if ( interfaceMethod != null ) { return interfaceMethod; } } return null; } /** * Used for the iterative discovery process for public methods. */ private static final class MethodInfo { Method method; String name; Class[] parameterTypes; boolean upcast; MethodInfo( Method method ) { this.method = null; name = method.getName(); parameterTypes = method.getParameterTypes(); upcast = false; } void tryUpcasting( Class clazz ) throws NoSuchMethodException { method = clazz.getMethod( name, parameterTypes ); name = null; parameterTypes = null; upcast = true; } } } MethodMap.java000066400000000000000000000351301242026660100400670ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/reflectionpackage org.codehaus.plexus.interpolation.reflection; /* ==================================================================== * Copyright 2001-2004 The Apache Software Foundation. * * 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. * ==================================================================== */ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * NOTE: This class was copied from plexus-utils, to allow this library * to stand completely self-contained. *
* @author Jason van Zyl * @author Bob McWhirter * @author Christoph Reck * @author Geir Magnusson Jr. * @author Attila Szegedi * @version $Id$ */ public class MethodMap { private static final int MORE_SPECIFIC = 0; private static final int LESS_SPECIFIC = 1; private static final int INCOMPARABLE = 2; /** * Keep track of all methods with the same name. */ Map> methodByNameMap = new Hashtable>(); /** * Add a method to a list of methods by name. * For a particular class we are keeping track * of all the methods with the same name. */ public void add( Method method ) { String methodName = method.getName(); List l = get( methodName ); if ( l == null) { l = new ArrayList(); methodByNameMap.put( methodName, l ); } l.add( method ); } /** * Return a list of methods with the same name. * * @param key the key * @return list of methods */ public List get( String key ) { return methodByNameMap.get( key ); } /** *

* Find a method. Attempts to find the * most specific applicable method using the * algorithm described in the JLS section * 15.12.2 (with the exception that it can't * distinguish a primitive type argument from * an object type argument, since in reflection * primitive type arguments are represented by * their object counterparts, so for an argument of * type (say) java.lang.Integer, it will not be able * to decide between a method that takes int and a * method that takes java.lang.Integer as a parameter. *

* *

* This turns out to be a relatively rare case * where this is needed - however, functionality * like this is needed. *

* * @param methodName name of method * @param args the actual arguments with which the method is called * @return the most specific applicable method, or null if no * method is applicable. * @throws AmbiguousException if there is more than one maximally * specific applicable method */ public Method find( String methodName, Object[] args ) throws AmbiguousException { List methodList = get( methodName ); if ( methodList == null ) { return null; } int l = args.length; Class[] classes = new Class[l]; for ( int i = 0; i < l; ++i ) { Object arg = args[i]; /* * if we are careful down below, a null argument goes in there * so we can know that the null was passed to the method */ classes[i] = arg == null ? null : arg.getClass(); } return getMostSpecific( methodList, classes ); } /** * simple distinguishable exception, used when * we run across ambiguous overloading */ public static class AmbiguousException extends Exception { } private static Method getMostSpecific( List methods, Class[] classes ) throws AmbiguousException { LinkedList applicables = getApplicables( methods, classes ); if ( applicables.isEmpty() ) { return null; } if ( applicables.size() == 1 ) { return applicables.getFirst(); } /* * This list will contain the maximally specific methods. Hopefully at * the end of the below loop, the list will contain exactly one method, * (the most specific method) otherwise we have ambiguity. */ LinkedList maximals = new LinkedList(); for ( Method app : applicables ) { Class[] appArgs = app.getParameterTypes(); boolean lessSpecific = false; for ( Iterator maximal = maximals.iterator(); !lessSpecific && maximal.hasNext(); ) { Method max = maximal.next(); switch ( moreSpecific( appArgs, max.getParameterTypes() ) ) { case MORE_SPECIFIC: { /* * This method is more specific than the previously * known maximally specific, so remove the old maximum. */ maximal.remove(); break; } case LESS_SPECIFIC: { /* * This method is less specific than some of the * currently known maximally specific methods, so we * won't add it into the set of maximally specific * methods */ lessSpecific = true; break; } } } if ( !lessSpecific ) { maximals.addLast( app ); } } if ( maximals.size() > 1 ) { // We have more than one maximally specific method throw new AmbiguousException(); } return maximals.getFirst(); } /** * Determines which method signature (represented by a class array) is more * specific. This defines a partial ordering on the method signatures. * @param c1 first signature to compare * @param c2 second signature to compare * @return MORE_SPECIFIC if c1 is more specific than c2, LESS_SPECIFIC if * c1 is less specific than c2, INCOMPARABLE if they are incomparable. */ private static int moreSpecific( Class[] c1, Class[] c2 ) { boolean c1MoreSpecific = false; boolean c2MoreSpecific = false; for ( int i = 0; i < c1.length; ++i ) { if ( c1[i] != c2[i] ) { c1MoreSpecific = c1MoreSpecific || isStrictMethodInvocationConvertible( c2[i], c1[i] ); c2MoreSpecific = c2MoreSpecific || isStrictMethodInvocationConvertible( c1[i], c2[i] ); } } if ( c1MoreSpecific ) { if ( c2MoreSpecific ) { /* * Incomparable due to cross-assignable arguments (i.e. * foo(String, Object) vs. foo(Object, String)) */ return INCOMPARABLE; } return MORE_SPECIFIC; } if ( c2MoreSpecific ) { return LESS_SPECIFIC; } /* * Incomparable due to non-related arguments (i.e. * foo(Runnable) vs. foo(Serializable)) */ return INCOMPARABLE; } /** * Returns all methods that are applicable to actual argument types. * @param methods list of all candidate methods * @param classes the actual types of the arguments * @return a list that contains only applicable methods (number of * formal and actual arguments matches, and argument types are assignable * to formal types through a method invocation conversion). */ private static LinkedList getApplicables( List methods, Class[] classes ) { LinkedList list = new LinkedList(); for ( Method method : methods ) { if ( isApplicable( method, classes ) ) { list.add( method ); } } return list; } /** * Returns true if the supplied method is applicable to actual * argument types. */ private static boolean isApplicable( Method method, Class[] classes ) { Class[] methodArgs = method.getParameterTypes(); if ( methodArgs.length != classes.length ) { return false; } for ( int i = 0; i < classes.length; ++i ) { if ( !isMethodInvocationConvertible( methodArgs[i], classes[i] ) ) { return false; } } return true; } /** * Determines whether a type represented by a class object is * convertible to another type represented by a class object using a * method invocation conversion, treating object types of primitive * types as if they were primitive types (that is, a Boolean actual * parameter type matches boolean primitive formal type). This behavior * is because this method is used to determine applicable methods for * an actual parameter list, and primitive types are represented by * their object duals in reflective method calls. * * @param formal the formal parameter type to which the actual * parameter type should be convertible * @param actual the actual parameter type. * @return true if either formal type is assignable from actual type, * or formal is a primitive type and actual is its corresponding object * type or an object type of a primitive type that can be converted to * the formal type. */ private static boolean isMethodInvocationConvertible( Class formal, Class actual ) { /* * if it's a null, it means the arg was null */ if ( actual == null && !formal.isPrimitive() ) { return true; } /* * Check for identity or widening reference conversion */ if ( actual != null && formal.isAssignableFrom( actual ) ) { return true; } /* * Check for boxing with widening primitive conversion. Note that * actual parameters are never primitives. */ if ( formal.isPrimitive() ) { if ( formal == Boolean.TYPE ) { return actual == Boolean.class; } if ( formal == Character.TYPE ) { return actual == Character.class; } if ( formal == Byte.TYPE ) { return actual == Byte.class; } if ( formal == Short.TYPE ) { return actual == Short.class || actual == Byte.class; } if ( formal == Integer.TYPE ) { return actual == Integer.class || actual == Short.class || actual == Byte.class; } if ( formal == Long.TYPE ) { return actual == Long.class || actual == Integer.class || actual == Short.class || actual == Byte.class; } if ( formal == Float.TYPE ) { return actual == Float.class || actual == Long.class || actual == Integer.class || actual == Short.class || actual == Byte.class; } if ( formal == Double.TYPE ) { return actual == Double.class || actual == Float.class || actual == Long.class || actual == Integer.class || actual == Short.class || actual == Byte.class; } } return false; } /** * Determines whether a type represented by a class object is * convertible to another type represented by a class object using a * method invocation conversion, without matching object and primitive * types. This method is used to determine the more specific type when * comparing signatures of methods. * * @param formal the formal parameter type to which the actual * parameter type should be convertible * @param actual the actual parameter type. * @return true if either formal type is assignable from actual type, * or formal and actual are both primitive types and actual can be * subject to widening conversion to formal. */ private static boolean isStrictMethodInvocationConvertible( Class formal, Class actual ) { /* * we shouldn't get a null into, but if so */ if ( actual == null && !formal.isPrimitive() ) { return true; } /* * Check for identity or widening reference conversion */ if ( formal.isAssignableFrom( actual ) ) { return true; } /* * Check for widening primitive conversion. */ if ( formal.isPrimitive() ) { if ( formal == Short.TYPE ) { return actual == Byte.TYPE; } if ( formal == Integer.TYPE ) { return actual == Short.TYPE || actual == Byte.TYPE; } if ( formal == Long.TYPE ) { return actual == Integer.TYPE || actual == Short.TYPE || actual == Byte.TYPE; } if ( formal == Float.TYPE ) { return actual == Long.TYPE || actual == Integer.TYPE || actual == Short.TYPE || actual == Byte.TYPE; } if ( formal == Double.TYPE ) { return actual == Float.TYPE || actual == Long.TYPE || actual == Integer.TYPE || actual == Short.TYPE || actual == Byte.TYPE; } } return false; } } ReflectionValueExtractor.java000066400000000000000000000077251242026660100432050ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/reflectionpackage org.codehaus.plexus.interpolation.reflection; /* * Copyright 2001-2006 Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.util.StringUtils; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.Map; import java.util.StringTokenizer; import java.util.WeakHashMap; /** * NOTE: This class was copied from plexus-utils, to allow this library * to stand completely self-contained. *
* Using simple dotted expressions extract the values from a MavenProject * instance, For example we might want to extract a value like: * project.build.sourceDirectory * * @author Jason van Zyl * @version $Id$ */ public class ReflectionValueExtractor { private static final Class[] CLASS_ARGS = new Class[0]; private static final Object[] OBJECT_ARGS = new Object[0]; /** * Use a WeakHashMap here, so the keys (Class objects) can be garbage collected. * This approach prevents permgen space overflows due to retention of discarded * classloaders. */ private static final Map, WeakReference> classMaps = new WeakHashMap, WeakReference>(); private ReflectionValueExtractor() { } public static Object evaluate( String expression, Object root ) throws Exception { return evaluate( expression, root, true ); } // TODO: don't throw Exception public static Object evaluate( String expression, Object root, boolean trimRootToken ) throws Exception { // if the root token refers to the supplied root object parameter, remove it. if ( trimRootToken ) { expression = expression.substring( expression.indexOf( '.' ) + 1 ); } Object value = root; // ---------------------------------------------------------------------- // Walk the dots and retrieve the ultimate value desired from the // MavenProject instance. // ---------------------------------------------------------------------- StringTokenizer parser = new StringTokenizer( expression, "." ); while ( parser.hasMoreTokens() ) { String token = parser.nextToken(); if ( value == null ) { return null; } ClassMap classMap = getClassMap( value.getClass() ); String methodBase = StringUtils.capitalizeFirstLetter( token ); String methodName = "get" + methodBase; Method method = classMap.findMethod( methodName, CLASS_ARGS ); if ( method == null ) { // perhaps this is a boolean property?? methodName = "is" + methodBase; method = classMap.findMethod( methodName, CLASS_ARGS ); } if ( method == null ) { return null; } value = method.invoke( value, OBJECT_ARGS ); } return value; } private static ClassMap getClassMap( Class clazz ) { WeakReference ref = classMaps.get( clazz); ClassMap classMap; if ( ref == null || (classMap = ref.get()) == null ) { classMap = new ClassMap( clazz ); classMaps.put( clazz, new WeakReference(classMap) ); } return classMap; } } plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/util/000077500000000000000000000000001242026660100342465ustar00rootroot00000000000000StringUtils.java000066400000000000000000000120171242026660100373220ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/util/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.codehaus.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact codehaus@codehaus.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . */ package org.codehaus.plexus.interpolation.util; /** * Code here was swiped from plexus-utils' StringUtils class, so * plexus-interpolation could be completely self-contained. * * @author jdcasey * @version $Id$ */ public class StringUtils { /** *

Replace all occurances of a String within another String.

* *

A null reference passed to this method is a no-op.

* * @see #replace(String text, String repl, String with, int max) * @param text text to search and replace in * @param repl String to search for * @param with String to replace with * @return the text with any replacements processed */ public static String replace( String text, String repl, String with ) { return replace( text, repl, with, -1 ); } /** *

Replace a String with another String inside a larger String, * for the first max values of the search String.

* *

A null reference passed to this method is a no-op.

* * @param text text to search and replace in * @param repl String to search for * @param with String to replace with * @param max maximum number of values to replace, or -1 if no maximum * @return the text with any replacements processed */ public static String replace( String text, String repl, String with, int max ) { if ( ( text == null ) || ( repl == null ) || ( with == null ) || ( repl.length() == 0 ) ) { return text; } StringBuilder buf = new StringBuilder( text.length() ); int start = 0, end; while ( ( end = text.indexOf( repl, start ) ) != -1 ) { buf.append( text, start, end ).append( with ); start = end + repl.length(); if ( --max == 0 ) { break; } } buf.append( text, start, text.length()); return buf.toString(); } public static String capitalizeFirstLetter( String data ) { char firstChar = data.charAt( 0 ); char titleCase = Character.toTitleCase( firstChar ); if (firstChar == titleCase) { return data; } StringBuilder result = new StringBuilder( data.length() ); result.append( titleCase ); result.append( data, 1, data.length() ); return result.toString(); } } ValueSourceUtils.java000066400000000000000000000067211242026660100403160ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/main/java/org/codehaus/plexus/interpolation/utilpackage org.codehaus.plexus.interpolation.util; /* * Copyright 2001-2006 Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.ValueSource; import java.util.Collection; /** * Utility methods shared by multiple {@link ValueSource} implementations. * * @author jdcasey * @version $Id$ */ public final class ValueSourceUtils { private ValueSourceUtils() { } /** * If the expression starts with one of the provided prefixes, trim that prefix * and return the remaining expression. If it doesn't start with a provided * prefix, and the allowUnprefixedExpressions flag is true, then return the * expression unchanged; if the flag is false, return null. Finally, if the * original expression is null, return null without attempting to process it. * * @param expression The expression to trim * @param possiblePrefixes The list of possible expression prefixes to trim * @param allowUnprefixedExpressions Whether to return the expression if it * doesn't start with one of the prefixes. If true, simply return the * original expression; if false, return null. * @return The trimmed expression, or null. See the behavior of * allowUnprefixedExpressions in this method for more detail. */ public static String trimPrefix( String expression, Collection possiblePrefixes, boolean allowUnprefixedExpressions ) { if ( expression == null ) { return null; } String realExpr = null; for ( String prefix : possiblePrefixes ) { if ( expression.startsWith( prefix ) ) { realExpr = expression.substring( prefix.length() ); if ( realExpr.startsWith( "." ) ) { realExpr = realExpr.substring( 1 ); } break; } } if ( realExpr == null && allowUnprefixedExpressions ) { realExpr = expression; } return realExpr; } public static String trimPrefix( String expression, String[] possiblePrefixes, boolean allowUnprefixedExpressions ) { if ( expression == null ) { return null; } String realExpr = null; for ( String prefix : possiblePrefixes ) { if ( expression.startsWith( prefix ) ) { realExpr = expression.substring( prefix.length() ); if ( realExpr.startsWith( "." ) ) { realExpr = realExpr.substring( 1 ); } break; } } if ( realExpr == null && allowUnprefixedExpressions ) { realExpr = expression; } return realExpr; } } plexus-interpolation-plexus-interpolation-1.21/src/site/000077500000000000000000000000001242026660100235775ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/site/apt/000077500000000000000000000000001242026660100243635ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/site/apt/index.apt000066400000000000000000000115331242026660100262030ustar00rootroot00000000000000 ----- Plexus Interpolator ----- John Casey Hervé Boutemy ----- 2012-10-31 ----- Introduction Plexus interpolator is the outgrowth of multiple iterations of development focused on providing a more modular, flexible interpolation framework for the expression language style commonly seen in Maven, Plexus, and other related projects. It has its foundation in the <<>> package within {{{/plexus-utils/}<<>>}}, but has been separated in order to allow these two libraries to vary independently of one another. Features * Stackable Expression-Resolution Strategies Expression-resolution strategies can be 'stacked' to provide an order of operations, containing multiple approaches that could potentially resolve a given expression. These strategies are called {{{./apidocs/org/codehaus/plexus/interpolation/ValueSource.html}<<>>s}}, and each implements a very simple piece of resolution logic. It's also possible to define your own, domain-specific value source. * Flexible Expression-Cycle Detection Expression cycles are detected using various strategies, ranging from simplistic consultation of a stack of explicit in-process expressions, to tracking of in-process expressions that takes multiple synonym expression variants into account. It's even possible to define your own {{{./apidocs/org/codehaus/plexus/interpolation/RecursionInterceptor.html}<<>>}} to implement an alternative strategy. * Configurable Regular Expression-Based Default Interpolator The default interpolator implementation uses regular expressions to search for interpolation candidate expressions within an input string. This interpolator can use a custom prefix/suffix pair that will effectively redefine the regular expression used to extract candidate expressions. * Built-In Synonym Support for Expressions Any <<>> implementation can be wrapped to allow multiple synonym expressions using different expression prefixes. * Resolution Feedback <<>> implementations have the option of implementing <<>>, which provides the ability to give feedback to the calling code about what failed during expression resolution. For instance, the <<>> traverses the object graph below a given root object; if an object in that graph doesn't contain a property corresponding to the expression-part currently being navigated, the value source can store a feedback message to that effect. Once interpolation of the larger input string has completed, the calling code can use the <<>> method to retrieve this feedback message (among others). Getting Started The simplest way to explain how to use the plexus-interpolation API is with a few examples. First, let's look at a simplified version of the interpolation configuration used in Maven. Remember that Maven uses several source for interpolation of its POM files: the POM itself, system properties, user-defined properties, and environment variables from the shell that spawned the current Java process. Also, Maven allows POM references to be defined as $\{pom.groupId}, $\{project.groupId}, or even the discouraged $\{groupId}. The following is a simplified version of the plexus-interpolation configuration Maven might use to resolve POM expressions: +---+ // serialize current POM object graph into a string called serializedPOM. RegexBasedInterpolator interpolator = new RegexBasedInterpolator(); interpolator.addValueSource( new EnvarBasedValueSource() ); interpolator.addValueSource( new PropertiesBasedValueSource( systemProperties ) ); List synonymPrefixes = new ArrayList(); synonymPrefixes.add( "project." ); synonymPrefixes.add( "pom." ); PrefixedValueSourceWrapper modelWrapper = new PrefixedValueSourceWrapper( synonymPrefixes, new ObjectBasedValueSource( pomModel ), true ); interpolator.addValueSource( modelWrapper ); PrefixedValueSourceWrapper pomPropertyWrapper = new PrefixedValueSourceWrapper( synonymPrefixes, new PropertiesBasedValueSource( pomModel.getProperties() ), true ); interpolator.addValueSource( pomPropertyWrapper ); interpolator.addValueSource( new PropertyBasedValueSource( userDefinedProperties ) ); RecursionInterceptor recursionInterceptor = new PrefixAwareRecursionInterceptor( synonymPrefixes, true ); serializedPOM = interpolator.interpolate( serializedPOM, recursionInterceptor ); // parse POM back into an object graph, and pass it back. +---+plexus-interpolation-plexus-interpolation-1.21/src/site/site.xml000066400000000000000000000011661242026660100252710ustar00rootroot00000000000000 plexus-interpolation-plexus-interpolation-1.21/src/test/000077500000000000000000000000001242026660100236125ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/000077500000000000000000000000001242026660100245335ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/000077500000000000000000000000001242026660100253225ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/000077500000000000000000000000001242026660100271155ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/000077500000000000000000000000001242026660100304355ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolation/000077500000000000000000000000001242026660100333245ustar00rootroot00000000000000InterpolatorFilterReaderTest.java000066400000000000000000000227571242026660100417400ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import junit.framework.TestCase; /** * InterpolatorFilterReaderTest, heavily based on InterpolationFilterReaderTest. Heh, even the test strings remained the * same! * * @author cstamas * */ public class InterpolatorFilterReaderTest extends TestCase { /* * Added and commented by jdcasey@03-Feb-2005 because it is a bug in the InterpolationFilterReader. * kenneyw@15-04-2005 fixed the bug. */ public void testShouldNotInterpolateExpressionAtEndOfDataWithInvalidEndToken() throws Exception { Map m = new HashMap(); m.put( "test", "TestValue" ); String testStr = "This is a ${test"; assertEquals( "This is a ${test", interpolate( testStr, m ) ); } /* * kenneyw@14-04-2005 Added test to check above fix. */ public void testShouldNotInterpolateExpressionWithMissingEndToken() throws Exception { Map m = new HashMap(); m.put( "test", "TestValue" ); String testStr = "This is a ${test, really"; assertEquals( "This is a ${test, really", interpolate( testStr, m ) ); } public void testShouldNotInterpolateWithMalformedStartToken() throws Exception { Map m = new HashMap(); m.put( "test", "testValue" ); String foo = "This is a $!test} again"; assertEquals( "This is a $!test} again", interpolate( foo, m ) ); } public void testShouldNotInterpolateWithMalformedEndToken() throws Exception { Map m = new HashMap(); m.put( "test", "testValue" ); String foo = "This is a ${test!} again"; assertEquals( "This is a ${test!} again", interpolate( foo, m ) ); } public void testDefaultInterpolationWithNonInterpolatedValueAtEnd() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "${name} is an ${noun}. ${not.interpolated}"; assertEquals( "jason is an asshole. ${not.interpolated}", interpolate( foo, m ) ); } public void testDefaultInterpolationWithInterpolatedValueAtEnd() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "${name} is an ${noun}"; assertEquals( "jason is an asshole", interpolate( foo, m ) ); } public void testInterpolationWithInterpolatedValueAtEndWithCustomToken() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "@{name} is an @{noun}"; assertEquals( "jason is an asshole", interpolate( foo, m, "@{", "}" ) ); } public void testInterpolationWithInterpolatedValueAtEndWithCustomTokenAndCustomString() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "@name@ is an @noun@"; assertEquals( "jason is an asshole", interpolate( foo, m, "@", "@" ) ); } public void testEscape() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "${name} is an \\${noun}"; assertEquals( "jason is an ${noun}", interpolate( foo, m, "\\" ) ); } public void testEscapeAtStart() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "\\${name} is an \\${noun}"; assertEquals( "${name} is an ${noun}", interpolate( foo, m, "\\" ) ); } public void testEscapeOnlyAtStart() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "\\@name@ is an @noun@"; String result = interpolate( foo, m, "@", "@" ); assertEquals( "@name@ is an asshole", result ); } public void testEscapeOnlyAtStartDefaultToken() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "\\${name} is an ${noun}"; String result = interpolate( foo, m, "${", "}" ); assertEquals( "${name} is an asshole", result ); } public void testShouldDetectRecursiveExpressionPassingThroughTwoPrefixes() throws Exception { List prefixes = new ArrayList(); prefixes.add( "prefix1" ); prefixes.add( "prefix2" ); RecursionInterceptor ri = new PrefixAwareRecursionInterceptor( prefixes, false ); Map context = new HashMap(); context.put( "name", "${prefix2.name}" ); String input = "${prefix1.name}"; StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new MapBasedValueSource( context ) ); InterpolatorFilterReader r = new InterpolatorFilterReader( new StringReader( input ), interpolator, ri ); r.setInterpolateWithPrefixPattern( false ); r.setEscapeString( "\\" ); StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } assertEquals( input, buf.toString() ); } public void testShouldDetectRecursiveExpressionWithPrefixAndWithout() throws Exception { List prefixes = new ArrayList(); prefixes.add( "prefix1" ); RecursionInterceptor ri = new PrefixAwareRecursionInterceptor( prefixes, false ); Map context = new HashMap(); context.put( "name", "${prefix1.name}" ); String input = "${name}"; StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new MapBasedValueSource( context ) ); InterpolatorFilterReader r = new InterpolatorFilterReader( new StringReader( input ), interpolator, ri ); r.setInterpolateWithPrefixPattern( false ); r.setEscapeString( "\\" ); StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } assertEquals( "${prefix1.name}", buf.toString() ); } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- private String interpolate( String input, Map context ) throws Exception { return interpolate( input, context, null ); } private String interpolate( String input, Map context, String escapeStr ) throws Exception { Interpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new MapBasedValueSource( context ) ); InterpolatorFilterReader r = new InterpolatorFilterReader( new StringReader( input ), interpolator ); r.setInterpolateWithPrefixPattern( false ); if ( escapeStr != null ) { r.setEscapeString( escapeStr ); } StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } return buf.toString(); } private String interpolate( String input, Map context, String beginToken, String endToken ) throws Exception { StringSearchInterpolator interpolator = new StringSearchInterpolator( beginToken, endToken ); interpolator.addValueSource( new MapBasedValueSource( context ) ); InterpolatorFilterReader r = new InterpolatorFilterReader( new StringReader( input ), interpolator, beginToken, endToken ); r.setInterpolateWithPrefixPattern( false ); r.setEscapeString( "\\" ); StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } return buf.toString(); } } PrefixAwareRecursionInterceptorTest.java000066400000000000000000000062011242026660100432750ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.Arrays; import java.util.Collections; import junit.framework.TestCase; public class PrefixAwareRecursionInterceptorTest extends TestCase { public void testFindExpression() { PrefixAwareRecursionInterceptor receptor = new PrefixAwareRecursionInterceptor( Collections.singleton( "prefix." ) ); String expr = "prefix.first"; receptor.expressionResolutionStarted( expr ); assertTrue( receptor.hasRecursiveExpression( expr ) ); assertEquals( "[first]", receptor.getExpressionCycle( expr ).toString() ); receptor.expressionResolutionFinished( expr ); assertFalse( receptor.hasRecursiveExpression( expr ) ); } public void testFindExpressionWithDifferentPrefix() { PrefixAwareRecursionInterceptor receptor = new PrefixAwareRecursionInterceptor( Arrays.asList( new String[] { "prefix.", "other." } ) ); String expr = "prefix.first"; receptor.expressionResolutionStarted( expr ); assertTrue( receptor.hasRecursiveExpression( expr ) ); receptor.expressionResolutionFinished( expr ); assertFalse( receptor.hasRecursiveExpression( expr ) ); } public void testFindExpressionWithoutPrefix() { PrefixAwareRecursionInterceptor receptor = new PrefixAwareRecursionInterceptor( Arrays.asList( new String[] { "prefix.", "other." } ) ); String prefixedExpr = "prefix.first"; String expr = "first"; receptor.expressionResolutionStarted( prefixedExpr ); assertTrue( receptor.hasRecursiveExpression( expr ) ); receptor.expressionResolutionFinished( prefixedExpr ); assertFalse( receptor.hasRecursiveExpression( expr ) ); } } PrefixedObjectValueSourceTest.java000066400000000000000000000041161242026660100420250ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2007 The Codehaus Foundation. * * 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. */ import java.util.ArrayList; import java.util.List; import junit.framework.TestCase; public class PrefixedObjectValueSourceTest extends TestCase { public void testEmptyExpressionResultsInNullReturn_NoPrefixUsed() { String target = "Target object"; List prefixes = new ArrayList(); prefixes.add( "target" ); prefixes.add( "object" ); PrefixedObjectValueSource vs = new PrefixedObjectValueSource( prefixes, target, true ); Object result = vs.getValue( "" ); assertNull( result ); } public void testEmptyExpressionResultsInNullReturn_PrefixUsedWithDot() { String target = "Target object"; List prefixes = new ArrayList(); prefixes.add( "target" ); prefixes.add( "object" ); PrefixedObjectValueSource vs = new PrefixedObjectValueSource( prefixes, target, true ); Object result = vs.getValue( "target." ); assertNull( result ); } public void testEmptyExpressionResultsInNullReturn_PrefixUsedWithoutDot() { String target = "Target object"; List prefixes = new ArrayList(); prefixes.add( "target" ); prefixes.add( "object" ); PrefixedObjectValueSource vs = new PrefixedObjectValueSource( prefixes, target, true ); Object result = vs.getValue( "target" ); assertNull( result ); } } PrefixedValueSourceWrapperTest.java000066400000000000000000000041661242026660100422440ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.Properties; import junit.framework.TestCase; public class PrefixedValueSourceWrapperTest extends TestCase { public void testShouldReturnValueForPropertyVSWRappedWithSinglePrefix() { String prefix = "prefix."; String key = "key"; String value = "value"; Properties props = new Properties(); props.setProperty( key, value ); PrefixedValueSourceWrapper wrapper = new PrefixedValueSourceWrapper( new PropertiesBasedValueSource( props ), prefix ); assertEquals( value, wrapper.getValue( prefix + key ) ); } public void testShouldReturnNullForIncorrectPrefixUsingPropertyVSWRappedWithSinglePrefix() { String prefix = "prefix."; String otherPrefix = "other."; String key = "key"; String value = "value"; Properties props = new Properties(); props.setProperty( key, value ); PrefixedValueSourceWrapper wrapper = new PrefixedValueSourceWrapper( new PropertiesBasedValueSource( props ), prefix ); assertNull( wrapper.getValue( otherPrefix + key ) ); } public void testShouldNullForMissingValueInPropertyVSWRappedWithSinglePrefix() { String prefix = "prefix."; String key = "key"; Properties props = new Properties(); PrefixedValueSourceWrapper wrapper = new PrefixedValueSourceWrapper( new PropertiesBasedValueSource( props ), prefix ); assertNull( wrapper.getValue( prefix + key ) ); } } PropertiesBasedValueSourceTest.java000066400000000000000000000026121242026660100422220ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.Properties; import junit.framework.TestCase; public class PropertiesBasedValueSourceTest extends TestCase { public void testPropertyShouldReturnValueFromProperties() { Properties props = new Properties(); String key = "key"; String value = "value"; props.setProperty( key, value ); PropertiesBasedValueSource vs = new PropertiesBasedValueSource( props ); assertNotNull( vs.getValue( key ) ); } public void testPropertyShouldReturnNullWhenPropertyMissing() { Properties props = new Properties(); String key = "key"; PropertiesBasedValueSource vs = new PropertiesBasedValueSource( props ); assertNull( vs.getValue( key ) ); } } RegexBasedInterpolatorTest.java000066400000000000000000000140651242026660100413720ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import junit.framework.TestCase; public class RegexBasedInterpolatorTest extends TestCase { public String getVar() { return "testVar"; } public void testShouldFailOnExpressionCycle() { Properties props = new Properties(); props.setProperty( "key1", "${key2}" ); props.setProperty( "key2", "${key1}" ); RegexBasedInterpolator rbi = new RegexBasedInterpolator(); rbi.addValueSource( new PropertiesBasedValueSource( props ) ); try { rbi.interpolate( "${key1}", new SimpleRecursionInterceptor() ); fail( "Should detect expression cycle and fail." ); } catch ( InterpolationException e ) { // expected } } public void testShouldResolveByMy_getVar_Method() throws InterpolationException { RegexBasedInterpolator rbi = new RegexBasedInterpolator(); rbi.addValueSource( new ObjectBasedValueSource( this ) ); String result = rbi.interpolate( "this is a ${this.var}", "this" ); assertEquals( "this is a testVar", result ); } public void testShouldResolveByContextValue() throws InterpolationException { RegexBasedInterpolator rbi = new RegexBasedInterpolator(); Map context = new HashMap(); context.put( "var", "testVar" ); rbi.addValueSource( new MapBasedValueSource( context ) ); String result = rbi.interpolate( "this is a ${this.var}", "this" ); assertEquals( "this is a testVar", result ); } public void testShouldResolveByEnvar() throws IOException, InterpolationException { RegexBasedInterpolator rbi = new RegexBasedInterpolator(); rbi.addValueSource( new EnvarBasedValueSource() ); String result = rbi.interpolate( "this is a ${env.HOME}", "this" ); assertFalse( "this is a ${HOME}".equals( result ) ); assertFalse( "this is a ${env.HOME}".equals( result ) ); } public void testUseAlternateRegex() throws Exception { RegexBasedInterpolator rbi = new RegexBasedInterpolator( "\\@\\{(", ")?([^}]+)\\}@" ); Map context = new HashMap(); context.put( "var", "testVar" ); rbi.addValueSource( new MapBasedValueSource( context ) ); String result = rbi.interpolate( "this is a @{this.var}@", "this" ); assertEquals( "this is a testVar", result ); } public void testNPEFree() throws Exception { RegexBasedInterpolator rbi = new RegexBasedInterpolator( "\\@\\{(", ")?([^}]+)\\}@" ); Map context = new HashMap(); context.put( "var", "testVar" ); rbi.addValueSource( new MapBasedValueSource( context ) ); String result = rbi.interpolate( null ); assertEquals( "", result ); } public void testUsePostProcessor_DoesNotChangeValue() throws InterpolationException { RegexBasedInterpolator rbi = new RegexBasedInterpolator(); Map context = new HashMap(); context.put( "test.var", "testVar" ); rbi.addValueSource( new MapBasedValueSource( context ) ); rbi.addPostProcessor( new InterpolationPostProcessor() { public Object execute( String expression, Object value ) { return null; } } ); String result = rbi.interpolate( "this is a ${test.var}", "" ); assertEquals( "this is a testVar", result ); } public void testUsePostProcessor_ChangesValue() throws InterpolationException { int loopNumber = 200000; long start = System.currentTimeMillis(); RegexBasedInterpolator rbi = new RegexBasedInterpolator(); Map context = new HashMap(); context.put( "test.var", "testVar" ); rbi.addValueSource( new MapBasedValueSource( context ) ); rbi.addPostProcessor( new InterpolationPostProcessor() { public Object execute( String expression, Object value ) { return value + "2"; } } ); for ( int i = 0, number = loopNumber; i < number; i++ ) { String result = rbi.interpolate( "this is a ${test.var}", "" ); assertEquals( "this is a testVar2", result ); } long end = System.currentTimeMillis(); System.out.println( "time without pattern reuse and RegexBasedInterpolator instance reuse " + ( end - start ) ); System.gc(); start = System.currentTimeMillis(); rbi = new RegexBasedInterpolator( true ); rbi.addPostProcessor( new InterpolationPostProcessor() { public Object execute( String expression, Object value ) { return value + "2"; } } ); rbi.addValueSource( new MapBasedValueSource( context ) ); for ( int i = 0, number = loopNumber; i < number; i++ ) { String result = rbi.interpolate( "this is a ${test.var}", "" ); assertEquals( "this is a testVar2", result ); } end = System.currentTimeMillis(); System.out.println( "time with pattern reuse and RegexBasedInterpolator instance reuse " + ( end - start ) ); } } StringSearchInterpolatorTest.java000066400000000000000000000344271242026660100417610ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolationpackage org.codehaus.plexus.interpolation; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import junit.framework.TestCase; public class StringSearchInterpolatorTest extends TestCase { public void testLongDelimitersInContext() throws InterpolationException { String src = "This is a test.label for long delimiters in context."; String result = "This is a test for long delimiters in context."; Properties p = new Properties(); p.setProperty( "test.label", "test" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "", "" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); assertEquals( result, interpolator.interpolate( src ) ); } public void testLongDelimitersWithNoStartContext() throws InterpolationException { String src = "test.label for long delimiters in context."; String result = "test for long delimiters in context."; Properties p = new Properties(); p.setProperty( "test.label", "test" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "", "" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); assertEquals( result, interpolator.interpolate( src ) ); } public void testLongDelimitersWithNoEndContext() throws InterpolationException { String src = "This is a test.label"; String result = "This is a test"; Properties p = new Properties(); p.setProperty( "test.label", "test" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "", "" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); assertEquals( result, interpolator.interpolate( src ) ); } public void testLongDelimitersWithNoContext() throws InterpolationException { String src = "test.label"; String result = "test"; Properties p = new Properties(); p.setProperty( "test.label", "test" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "", "" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); assertEquals( result, interpolator.interpolate( src ) ); } public void testSimpleSubstitution() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); assertEquals( "This is a test value.", interpolator.interpolate( "This is a test ${key}." ) ); } public void testSimpleSubstitution_TwoExpressions() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); assertEquals( "value-value2", interpolator.interpolate( "${key}-${key2}" ) ); } public void testBrokenExpression_LeaveItAlone() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); assertEquals( "This is a test ${key.", interpolator.interpolate( "This is a test ${key." ) ); } public void testShouldFailOnExpressionCycle() { Properties props = new Properties(); props.setProperty( "key1", "${key2}" ); props.setProperty( "key2", "${key1}" ); StringSearchInterpolator rbi = new StringSearchInterpolator(); rbi.addValueSource( new PropertiesBasedValueSource( props ) ); try { rbi.interpolate( "${key1}", new SimpleRecursionInterceptor() ); fail( "Should detect expression cycle and fail." ); } catch ( InterpolationException e ) { // expected } } public void testShouldResolveByMy_getVar_Method() throws InterpolationException { StringSearchInterpolator rbi = new StringSearchInterpolator(); rbi.addValueSource( new ObjectBasedValueSource( this ) ); String result = rbi.interpolate( "this is a ${var}" ); assertEquals( "this is a testVar", result ); } public void testShouldResolveByContextValue() throws InterpolationException { StringSearchInterpolator rbi = new StringSearchInterpolator(); Map context = new HashMap(); context.put( "var", "testVar" ); rbi.addValueSource( new MapBasedValueSource( context ) ); String result = rbi.interpolate( "this is a ${var}" ); assertEquals( "this is a testVar", result ); } public void testShouldResolveByEnvar() throws IOException, InterpolationException { StringSearchInterpolator rbi = new StringSearchInterpolator(); rbi.addValueSource( new EnvarBasedValueSource( false ) ); String result = rbi.interpolate( "this is a ${env.HOME} ${env.PATH}" ); assertFalse( "this is a ${HOME} ${PATH}".equals( result ) ); assertFalse( "this is a ${env.HOME} ${env.PATH}".equals( result ) ); } public void testUsePostProcessor_DoesNotChangeValue() throws InterpolationException { StringSearchInterpolator rbi = new StringSearchInterpolator(); Map context = new HashMap(); context.put( "test.var", "testVar" ); rbi.addValueSource( new MapBasedValueSource( context ) ); rbi.addPostProcessor( new InterpolationPostProcessor() { public Object execute( String expression, Object value ) { return null; } } ); String result = rbi.interpolate( "this is a ${test.var}" ); assertEquals( "this is a testVar", result ); } public void testUsePostProcessor_ChangesValue() throws InterpolationException { StringSearchInterpolator rbi = new StringSearchInterpolator(); Map context = new HashMap(); context.put( "test.var", "testVar" ); rbi.addValueSource( new MapBasedValueSource( context ) ); rbi.addPostProcessor( new InterpolationPostProcessor() { public Object execute( String expression, Object value ) { return value + "2"; } } ); String result = rbi.interpolate( "this is a ${test.var}" ); assertEquals( "this is a testVar2", result ); } public void testSimpleSubstitutionWithDefinedExpr() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); assertEquals( "This is a test value.", interpolator.interpolate( "This is a test @{key}." ) ); } public void testEscape() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.setEscapeString( "\\" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( "This is a test \\@{key}." ); assertEquals( "This is a test @{key}.", result ); } public void testEscapeWithLongEscapeStr() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.setEscapeString( "$$" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( "This is a test $$@{key}." ); assertEquals( "This is a test @{key}.", result ); } public void testEscapeWithLongEscapeStrAtStart() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.setEscapeString( "$$" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( "$$@{key} This is a test." ); assertEquals( "@{key} This is a test.", result ); } public void testNotEscapeWithLongEscapeStrAtStart() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.setEscapeString( "$$" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( "@{key} This is a test." ); assertEquals( "value This is a test.", result ); } public void testEscapeNotFailWithNullEscapeStr() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.setEscapeString( null ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( "This is a test @{key}." ); assertEquals( "This is a test value.", result ); } public void testOnlyEscapeExprAtStart() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.setEscapeString( "\\" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( "\\@{key} This is a test." ); assertEquals( "@{key} This is a test.", result ); } public void testNotEscapeExprAtStart() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.setEscapeString( "\\" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( "@{key} This is a test." ); assertEquals( "value This is a test.", result ); } public void testEscapeExprAtStart() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@", "@" ); interpolator.setEscapeString( "\\" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( "\\@key@ This is a test @key@." ); assertEquals( "@key@ This is a test value.", result ); } public void testNPEFree() throws InterpolationException { Properties p = new Properties(); p.setProperty( "key", "value" ); StringSearchInterpolator interpolator = new StringSearchInterpolator( "@{", "}" ); interpolator.setEscapeString( "\\" ); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); String result = interpolator.interpolate( null ); assertEquals( "", result ); } public void testInterruptedInterpolate() throws InterpolationException { Interpolator interpolator = new StringSearchInterpolator(); RecursionInterceptor recursionInterceptor = new SimpleRecursionInterceptor(); final boolean[] error = new boolean[] { false }; interpolator.addValueSource( new ValueSource() { public Object getValue( String expression ) { if ( expression.equals( "key" ) ) { if ( error[ 0 ] ) { throw new IllegalStateException( "broken" ); } return "val"; } else { return null; } } public List getFeedback() { return Collections.EMPTY_LIST; } public void clearFeedback() { } } ); assertEquals( "control case", "-val-" , interpolator.interpolate( "-${key}-", recursionInterceptor ) ); error[ 0 ] = true; try { interpolator.interpolate( "-${key}-", recursionInterceptor ); fail( "should have thrown exception" ); } catch ( IllegalStateException x ) { // right } error[ 0 ] = false; assertEquals( "should not believe there is a cycle here", "-val-", interpolator.interpolate( "-${key}-", recursionInterceptor ) ); } public String getVar() { return "testVar"; } } 000077500000000000000000000000001242026660100343775ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolation/multiMultiDelimiterInterpolatorFilterReaderTest.java000066400000000000000000000273151242026660100457370ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolation/multipackage org.codehaus.plexus.interpolation.multi; /* * The MIT License * * Copyright (c) 2004, The Codehaus * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ import org.codehaus.plexus.interpolation.Interpolator; import org.codehaus.plexus.interpolation.MapBasedValueSource; import org.codehaus.plexus.interpolation.PrefixAwareRecursionInterceptor; import org.codehaus.plexus.interpolation.RecursionInterceptor; import org.codehaus.plexus.interpolation.StringSearchInterpolator; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import junit.framework.TestCase; /** * InterpolatorFilterReaderTest, heavily based on InterpolationFilterReaderTest. Heh, even the test strings remained the * same! * * @author cstamas * */ public class MultiDelimiterInterpolatorFilterReaderTest extends TestCase { /* * Added and commented by jdcasey@03-Feb-2005 because it is a bug in the InterpolationFilterReader. * kenneyw@15-04-2005 fixed the bug. */ public void testShouldNotInterpolateExpressionAtEndOfDataWithInvalidEndToken() throws Exception { Map m = new HashMap(); m.put( "test", "TestValue" ); String testStr = "This is a ${test"; assertEquals( "This is a ${test", interpolate( testStr, m ) ); } /* * kenneyw@14-04-2005 Added test to check above fix. */ public void testShouldNotInterpolateExpressionWithMissingEndToken() throws Exception { Map m = new HashMap(); m.put( "test", "TestValue" ); String testStr = "This is a ${test, really"; assertEquals( "This is a ${test, really", interpolate( testStr, m ) ); } public void testShouldNotInterpolateWithMalformedStartToken() throws Exception { Map m = new HashMap(); m.put( "test", "testValue" ); String foo = "This is a $!test} again"; assertEquals( "This is a $!test} again", interpolate( foo, m ) ); } public void testShouldNotInterpolateWithMalformedEndToken() throws Exception { Map m = new HashMap(); m.put( "test", "testValue" ); String foo = "This is a ${test!} again"; assertEquals( "This is a ${test!} again", interpolate( foo, m ) ); } public void testDefaultInterpolationWithNonInterpolatedValueAtEnd() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "${name} is an ${noun}. ${not.interpolated}"; assertEquals( "jason is an asshole. ${not.interpolated}", interpolate( foo, m ) ); } public void testDefaultInterpolationWithInterpolatedValueAtEnd() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "${name} is an ${noun}"; assertEquals( "jason is an asshole", interpolate( foo, m ) ); } public void testInterpolationWithInterpolatedValueAtEndWithCustomToken() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "@{name} is an @{noun}"; assertEquals( "jason is an asshole", interpolate( foo, m, "@{", "}" ) ); } public void testInterpolationWithInterpolatedValueAtEndWithCustomTokenAndCustomString() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "@name@ is an @noun@"; assertEquals( "jason is an asshole", interpolate( foo, m, "@", "@" ) ); } public void testEscape() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "${name} is an \\${noun}"; assertEquals( "jason is an ${noun}", interpolate( foo, m, "\\" ) ); } public void testEscapeAtStart() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "\\${name} is an \\${noun}"; assertEquals( "${name} is an ${noun}", interpolate( foo, m, "\\" ) ); } public void testEscapeOnlyAtStart() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "\\@name@ is an @noun@"; String result = interpolate( foo, m, "@", "@" ); assertEquals( "@name@ is an asshole", result ); } public void testEscapeOnlyAtStartDefaultToken() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "noun", "asshole" ); String foo = "\\${name} is an ${noun}"; String result = interpolate( foo, m, "${", "}" ); assertEquals( "${name} is an asshole", result ); } public void testShouldDetectRecursiveExpressionPassingThroughTwoPrefixes() throws Exception { List prefixes = new ArrayList(); prefixes.add( "prefix1" ); prefixes.add( "prefix2" ); RecursionInterceptor ri = new PrefixAwareRecursionInterceptor( prefixes, false ); Map context = new HashMap(); context.put( "name", "${prefix2.name}" ); String input = "${prefix1.name}"; StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new MapBasedValueSource( context ) ); MultiDelimiterInterpolatorFilterReader r = new MultiDelimiterInterpolatorFilterReader( new StringReader( input ), interpolator, ri ); r.setInterpolateWithPrefixPattern( false ); r.setEscapeString( "\\" ); StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } assertEquals( input, buf.toString() ); } public void testShouldDetectRecursiveExpressionWithPrefixAndWithout() throws Exception { List prefixes = new ArrayList(); prefixes.add( "prefix1" ); RecursionInterceptor ri = new PrefixAwareRecursionInterceptor( prefixes, false ); Map context = new HashMap(); context.put( "name", "${prefix1.name}" ); String input = "${name}"; StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new MapBasedValueSource( context ) ); MultiDelimiterInterpolatorFilterReader r = new MultiDelimiterInterpolatorFilterReader( new StringReader( input ), interpolator, ri ); r.setInterpolateWithPrefixPattern( false ); r.setEscapeString( "\\" ); StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } assertEquals( "${prefix1.name}", buf.toString() ); } public void testInterpolationWithMultipleTokenTypes() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "otherName", "@name@" ); String foo = "${otherName}"; assertEquals( "jason", interpolateMulti( foo, m, new String[] { "${*}", "@*@" } ) ); } public void testInterpolationWithMultipleTokenTypes_ReversedOrdering() throws Exception { Map m = new HashMap(); m.put( "name", "jason" ); m.put( "otherName", "${name}" ); String foo = "@otherName@"; assertEquals( "jason", interpolateMulti( foo, m, new String[] { "${*}", "@*@" } ) ); } // ---------------------------------------------------------------------- // // ---------------------------------------------------------------------- private String interpolate( String input, Map context ) throws Exception { return interpolate( input, context, null ); } private String interpolate( String input, Map context, String escapeStr ) throws Exception { Interpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new MapBasedValueSource( context ) ); MultiDelimiterInterpolatorFilterReader r = new MultiDelimiterInterpolatorFilterReader( new StringReader( input ), interpolator ); r.setInterpolateWithPrefixPattern( false ); if ( escapeStr != null ) { r.setEscapeString( escapeStr ); } StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } return buf.toString(); } private String interpolate( String input, Map context, String beginToken, String endToken ) throws Exception { StringSearchInterpolator interpolator = new StringSearchInterpolator( beginToken, endToken ); interpolator.addValueSource( new MapBasedValueSource( context ) ); MultiDelimiterInterpolatorFilterReader r = new MultiDelimiterInterpolatorFilterReader( new StringReader( input ), interpolator ); r.addDelimiterSpec( beginToken + "*" + endToken ); r.setInterpolateWithPrefixPattern( false ); r.setEscapeString( "\\" ); StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } return buf.toString(); } private String interpolateMulti( String input, Map context, String[] specs ) throws Exception { MultiDelimiterStringSearchInterpolator interp = new MultiDelimiterStringSearchInterpolator(); interp.addValueSource( new MapBasedValueSource( context ) ); MultiDelimiterInterpolatorFilterReader r = new MultiDelimiterInterpolatorFilterReader( new StringReader( input ), interp ); for ( String spec : specs ) { interp.addDelimiterSpec( spec ); r.addDelimiterSpec( spec ); } r.setInterpolateWithPrefixPattern( false ); r.setEscapeString( "\\" ); StringBuilder buf = new StringBuilder(); int read = -1; char[] cbuf = new char[1024]; while ( ( read = r.read( cbuf ) ) > -1 ) { buf.append( cbuf, 0, read ); } return buf.toString(); } } MultiDelimiterStringSearchInterpolatorTest.java000066400000000000000000000046111242026660100457550ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolation/multipackage org.codehaus.plexus.interpolation.multi; /* * Copyright 2001-2009 Codehaus Foundation. * * 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. */ import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.MapBasedValueSource; import org.codehaus.plexus.interpolation.ValueSource; import org.codehaus.plexus.interpolation.multi.MultiDelimiterStringSearchInterpolator; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; public class MultiDelimiterStringSearchInterpolatorTest extends TestCase { public void testInterpolationWithDifferentDelimiters() throws InterpolationException { Map ctx = new HashMap(); ctx.put( "name", "User" ); ctx.put( "otherName", "@name@" ); String input = "${otherName}"; ValueSource vs = new MapBasedValueSource( ctx ); MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator().addDelimiterSpec( "@" ) .withValueSource( vs ); String result = interpolator.interpolate( input ); assertEquals( ctx.get( "name" ), result ); } public void testSuccessiveInterpolationWithDifferentDelimiters_ReversedDelimiterSequence() throws InterpolationException { Map ctx = new HashMap(); ctx.put( "name", "User" ); ctx.put( "otherName", "${name}" ); String input = "@otherName@"; ValueSource vs = new MapBasedValueSource( ctx ); MultiDelimiterStringSearchInterpolator interpolator = new MultiDelimiterStringSearchInterpolator().addDelimiterSpec( "@" ) .withValueSource( vs ); String result = interpolator.interpolate( input ); assertEquals( ctx.get( "name" ), result ); } } 000077500000000000000000000000001242026660100345135ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolation/objectFieldBasedObjectInterpolatorTest.java000066400000000000000000000230051242026660100437320ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolation/objectpackage org.codehaus.plexus.interpolation.object; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import junit.framework.TestCase; import org.codehaus.plexus.interpolation.PropertiesBasedValueSource; import org.codehaus.plexus.interpolation.StringSearchInterpolator; public class FieldBasedObjectInterpolatorTest extends TestCase { public void testInterpolateStringArray() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); String[] values = { "${key}", "${key2}" }; StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( values, interpolator ); assertEquals( "value", values[0] ); assertEquals( "value2", values[1] ); } public void testInterpolateObjectWithStringArrayField() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); String[] values = { "${key}", "${key2}" }; ObjectWithStringArrayField obj = new ObjectWithStringArrayField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "value", obj.values[0] ); assertEquals( "value2", obj.values[1] ); } public void testInterpolateObjectWithStringListField() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); List values = new ArrayList(); values.add( "${key}" ); values.add( "${key2}" ); ObjectWithListField obj = new ObjectWithListField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "value", obj.values.get( 0 ) ); assertEquals( "value2", obj.values.get( 1 ) ); } public void testInterpolateObjectWithStringListFieldAndOneLiteralValue() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); List values = new ArrayList(); values.add( "key" ); values.add( "${key2}" ); ObjectWithListField obj = new ObjectWithListField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "key", obj.values.get( 0 ) ); assertEquals( "value2", obj.values.get( 1 ) ); } public void testInterpolateObjectWithUnmodifiableStringListField() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); List values = Collections.unmodifiableList( Collections.singletonList( "${key}" ) ); ObjectWithListField obj = new ObjectWithListField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "${key}", obj.values.get( 0 ) ); } public void testInterpolateObjectWithStringArrayListField() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); p.setProperty( "key3", "value3" ); p.setProperty( "key4", "value4" ); List values = new ArrayList(); values.add( new String[] { "${key}", "${key2}" } ); values.add( new String[] { "${key3}", "${key4}" } ); ObjectWithListField obj = new ObjectWithListField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "value", ( (String[]) obj.values.get( 0 ) )[0] ); assertEquals( "value2", ( (String[]) obj.values.get( 0 ) )[1] ); assertEquals( "value3", ( (String[]) obj.values.get( 1 ) )[0] ); assertEquals( "value4", ( (String[]) obj.values.get( 1 ) )[1] ); } public void testInterpolateObjectWithStringToStringMapField() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); Map values = new HashMap(); values.put( "key", "${key}" ); values.put( "key2", "${key2}" ); ObjectWithMapField obj = new ObjectWithMapField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "value", obj.values.get( "key" ) ); assertEquals( "value2", obj.values.get( "key2" ) ); } public void testInterpolateObjectWithStringToStringMapFieldAndOneLiteralValue() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); Map values = new HashMap(); values.put( "key", "val" ); values.put( "key2", "${key2}" ); ObjectWithMapField obj = new ObjectWithMapField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "val", obj.values.get( "key" ) ); assertEquals( "value2", obj.values.get( "key2" ) ); } public void testInterpolateObjectWithUnmodifiableStringToStringMapField() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); Map values = Collections.unmodifiableMap( Collections.singletonMap( "key", "${key}" ) ); ObjectWithMapField obj = new ObjectWithMapField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "${key}", obj.values.get( "key" ) ); } public void testInterpolateObjectWithStringToStringArrayMapField() throws Exception { Properties p = new Properties(); p.setProperty( "key", "value" ); p.setProperty( "key2", "value2" ); p.setProperty( "key3", "value3" ); p.setProperty( "key4", "value4" ); Map values = new HashMap(); values.put( "key", new String[] { "${key}", "${key2}" } ); values.put( "key2", new String[] { "${key3}", "${key4}" } ); ObjectWithMapField obj = new ObjectWithMapField( values ); StringSearchInterpolator interpolator = new StringSearchInterpolator(); interpolator.addValueSource( new PropertiesBasedValueSource( p ) ); new FieldBasedObjectInterpolator().interpolate( obj, interpolator ); assertEquals( "value", ( (String[]) obj.values.get( "key" ) )[0] ); assertEquals( "value2", ( (String[]) obj.values.get( "key" ) )[1] ); assertEquals( "value3", ( (String[]) obj.values.get( "key2" ) )[0] ); assertEquals( "value4", ( (String[]) obj.values.get( "key2" ) )[1] ); } private static final class ObjectWithStringArrayField { private final String[] values; public ObjectWithStringArrayField( String[] values ) { this.values = values; } } private static final class ObjectWithListField { private final List values; public ObjectWithListField( List values ) { this.values = values; } } private static final class ObjectWithMapField { private final Map values; public ObjectWithMapField( Map values ) { this.values = values; } } } plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolation/util/000077500000000000000000000000001242026660100343015ustar00rootroot00000000000000StringUtilsTest.java000066400000000000000000000021271242026660100402160ustar00rootroot00000000000000plexus-interpolation-plexus-interpolation-1.21/src/test/java/org/codehaus/plexus/interpolation/utilpackage org.codehaus.plexus.interpolation.util; /* * Copyright 2001-2008 Codehaus Foundation. * * 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. */ import junit.framework.Assert; import junit.framework.TestCase; public class StringUtilsTest extends TestCase { public void testCapitalizeFirstLetter() throws Exception { Assert.assertEquals( "Abc", StringUtils.capitalizeFirstLetter( "abc" ) ); Assert.assertEquals( "\u00cdce", StringUtils.capitalizeFirstLetter( "\u00edce" ) ); Assert.assertEquals( "X", StringUtils.capitalizeFirstLetter( "x" ) ); } }