001    /*
002     * Copyright (C) 2006-2007 the original author or authors.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.codehaus.gmaven.plugin.execute;
018    
019    //
020    // NOTE: Nicked from maven-core and massaged to resolve properties for Groovy executions.
021    //       Needed to have this delegate to Map.get() instead of Properties.getProperty()
022    //       to get objects in properties to resolve correctly when chained together.
023    //
024    
025    import org.apache.maven.execution.MavenSession;
026    import org.apache.maven.plugin.MojoExecution;
027    import org.apache.maven.plugin.descriptor.MojoDescriptor;
028    import org.apache.maven.project.MavenProject;
029    import org.apache.maven.project.path.PathTranslator;
030    import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
031    import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
032    import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
033    import org.codehaus.plexus.util.introspection.ReflectionValueExtractor;
034    
035    import java.io.File;
036    
037    /**
038     * Custom expresion evaluation for Groovy executions.
039     *
040     * @version $Id: ExpressionEvaluatorImpl.java 8 2009-07-16 09:15:04Z user57 $
041     * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
042     */
043    public class ExpressionEvaluatorImpl
044        implements ExpressionEvaluator
045    {
046        private final MavenSession context;
047    
048        private final MojoExecution mojoExecution;
049    
050        private final MavenProject project;
051    
052        private final PathTranslator pathTranslator;
053    
054        private final String basedir;
055    
056        public ExpressionEvaluatorImpl(final MavenSession context, final MavenProject project) {
057            this.context = context;
058            this.mojoExecution = new MojoExecution(new MojoDescriptor());
059            this.pathTranslator = lookupPathTranslator();
060            this.project = project;
061            this.basedir = lookupBasedir();
062        }
063    
064        private PathTranslator lookupPathTranslator() {
065            try {
066                return (PathTranslator)context.lookup(PathTranslator.ROLE);
067            }
068            catch (ComponentLookupException e) {
069                throw new RuntimeException(e);
070            }
071        }
072    
073        private String lookupBasedir() {
074            String basedir = null;
075    
076            if (project != null) {
077                File projectFile = project.getFile();
078    
079                // this should always be the case for non-super POM instances...
080                if (projectFile != null) {
081                    basedir = projectFile.getParentFile().getAbsolutePath();
082                }
083            }
084    
085            if (basedir == null) {
086                basedir = System.getProperty("user.dir");
087            }
088    
089            return basedir;
090        }
091        
092        public Object evaluate(final String expr) throws ExpressionEvaluationException {
093            try {
094                return doEvaluate(expr);
095            }
096            catch (Exception e) {
097                throw new ExpressionEvaluationException("Error evaluating plugin parameter expression: " + expr, e);
098            }
099        }
100    
101        private Object doEvaluate(String expr) throws Exception {
102            if (expr == null) {
103                return null;
104            }
105    
106            String expression = stripTokens(expr);
107            if (expression.equals(expr)) {
108                int index = expr.indexOf("${");
109                if (index >= 0) {
110                    int lastIndex = expr.indexOf("}", index);
111                    if (lastIndex >= 0) {
112                        String retVal = expr.substring(0, index);
113    
114                        if (index > 0 && expr.charAt(index - 1) == '$') {
115                            retVal += expr.substring(index + 1, lastIndex + 1);
116                        }
117                        else {
118                            retVal += doEvaluate(expr.substring(index, lastIndex + 1));
119                        }
120    
121                        retVal += doEvaluate(expr.substring(lastIndex + 1));
122                        return retVal;
123                    }
124                }
125    
126                // Was not an expression
127                if (expression.indexOf("$$") > -1) {
128                    return expression.replaceAll("\\$\\$", "\\$");
129                }
130                else {
131                    return expression;
132                }
133            }
134    
135            Object value = evaluateSpecials(expression);
136    
137            if (value == null) {
138                value = resolveProperties(expression);
139            }
140    
141            if (value instanceof String) {
142                String val = (String) value;
143    
144                int exprStartDelimiter = val.indexOf("${");
145    
146                if (exprStartDelimiter >= 0) {
147                    if (exprStartDelimiter > 0) {
148                        value = val.substring(0, exprStartDelimiter) + doEvaluate(val.substring(exprStartDelimiter));
149                    }
150                    else {
151                        value = doEvaluate(val.substring(exprStartDelimiter));
152                    }
153                }
154            }
155    
156            return value;
157        }
158    
159        private Object resolveProperties(final String expression) {
160            assert project != null;
161            assert project.getProperties() != null;
162    
163            return project.getProperties().get(expression);
164        }
165    
166        private Object evaluateSpecials(final String expression) throws Exception {
167            Object value = null;
168    
169            if ("localRepository".equals(expression)) {
170                value = context.getLocalRepository();
171            }
172            else if ("session".equals(expression)) {
173                value = context;
174            }
175            else if ("reactorProjects".equals(expression)) {
176                value = context.getSortedProjects();
177            }
178            else if ("reports".equals(expression)) {
179                value = mojoExecution.getReports();
180            }
181            else if ("project".equals(expression)) {
182                value = project;
183            }
184            else if ("executedProject".equals(expression)) {
185                value = project.getExecutionProject();
186            }
187            else if (expression.startsWith("project")) {
188                value = evaluateInContext(expression, project);
189            }
190            else if (expression.startsWith("plugin")) {
191                value = evaluateInContext(expression, mojoExecution.getMojoDescriptor().getPluginDescriptor());
192            }
193            else if ("settings".equals(expression)) {
194                value = context.getSettings();
195            }
196            else if (expression.startsWith("settings")) {
197                value = evaluateInContext(expression, context.getSettings());
198            }
199            else if ("basedir".equals(expression)) {
200                value = basedir;
201            }
202            else if (expression.startsWith("basedir")) {
203                int pathSeparator = expression.indexOf("/");
204    
205                if (pathSeparator > 0) {
206                    value = basedir + expression.substring(pathSeparator);
207                }
208                else {
209                    throw new ExpressionEvaluationException("Unrecognized expression: " + expression);
210                }
211            }
212    
213            return value;
214        }
215    
216        private Object evaluateInContext(final String expression, final Object context) throws Exception {
217            Object value;
218    
219            int pathSeparator = expression.indexOf("/");
220            if (pathSeparator > 0) {
221                String pathExpression = expression.substring(0, pathSeparator);
222                value = ReflectionValueExtractor.evaluate(pathExpression, context);
223                value = value + expression.substring(pathSeparator);
224            }
225            else {
226                value = ReflectionValueExtractor.evaluate(expression.substring(1), context);
227            }
228    
229            return value;
230        }
231    
232        private String stripTokens(String expr) {
233            if (expr.startsWith("${") && expr.indexOf("}") == expr.length() - 1) {
234                expr = expr.substring(2, expr.length() - 1);
235            }
236            return expr;
237        }
238    
239        public File alignToBaseDirectory(final File file) {
240            File basedir;
241    
242            if (project != null && project.getFile() != null) {
243                basedir = project.getFile().getParentFile();
244            }
245            else {
246                basedir = new File(".").getAbsoluteFile().getParentFile();
247            }
248    
249            return new File(pathTranslator.alignToBaseDirectory(file.getPath(), basedir));
250        }
251    }