/*
* Copyright 2007 the original author or authors.
*
* 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.
*/
package org.grails.maven.plugin.tools;
import groovy.lang.GroovyClassLoader;
import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.groovy.grails.plugins.AstPluginDescriptorReader;
import org.codehaus.groovy.grails.plugins.GrailsPluginInfo;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.IOUtil;
import java.io.*;
import java.util.Date;
import java.util.Properties;
/**
* @author <a href="mailto:aheritier@gmail.com">Arnaud HERITIER</a>
* @version $Id$
* @plexus.component role="org.grails.maven.plugin.tools.GrailsServices"
* @since 0.1
*/
public class DefaultGrailsServices extends AbstractLogEnabled implements GrailsServices {
private static final String FILE_SUFFIX = "GrailsPlugin.groovy";
private File _basedir;
/**
* Converts foo-bar into FooBar. Empty and null strings are returned as-is.
*
* @param name The lower case hyphen separated name
* @return The class name equivalent.
*/
public static String getClassNameForLowerCaseHyphenSeparatedName(String name) {
// Handle null and empty strings.
if (name == null || name.length() == 0) return name;
if (name.indexOf('-') == -1) {
return name.substring(0,1).toUpperCase() + name.substring(1);
}
StringBuilder buf = new StringBuilder();
String[] tokens = name.split("-");
for (String token : tokens) {
if (token == null || token.length() == 0) continue;
buf.append(token.substring(0, 1).toUpperCase())
.append(token.substring(1));
}
return buf.toString();
}
/**
* The regular expression used to find camel case boundaries with a string.
*/
private static final String CAMEL_CASE_CONVERSION = "([a-z0-9])(?=[A-Z])";
/**
* Converts FooBar into foo-bar. Empty and null strings are returned as-is.
*
* @param name The lower case hyphen separated name
* @return The class name equivalent.
*/
public static String getLowerCaseHyphenSeparatedName(String name) {
if (name == null || name.length() == 0) return name;
return name.replaceAll(CAMEL_CASE_CONVERSION, "$1-").toLowerCase();
}
// private List _dependencyPaths;
private File getBasedir() {
if (_basedir != null) {
return _basedir;
}
throw new RuntimeException("The basedir has to be set before any of the service methods are invoked.");
}
// -----------------------------------------------------------------------
// GrailsServices Implementation
// -----------------------------------------------------------------------
public void setBasedir(final File basedir) {
this._basedir = basedir;
}
public GrailsProject readProjectDescriptor() throws MojoExecutionException {
// Load existing Grails properties
FileInputStream fis = null;
try {
final Properties properties = new Properties();
fis = new FileInputStream(new File(getBasedir(), "application.properties"));
properties.load(fis);
final GrailsProject grailsProject = new GrailsProject();
grailsProject.setAppGrailsVersion(properties.getProperty("app.grails.version"));
grailsProject.setAppName(properties.getProperty("app.name"));
grailsProject.setAppVersion(properties.getProperty("app.version"));
return grailsProject;
} catch (final IOException e) {
throw new MojoExecutionException("Unable to read grails project descriptor.", e);
} finally {
IOUtil.close(fis);
}
}
public void writeProjectDescriptor(final File projectDir, final GrailsProject grailsProjectDescriptor) throws MojoExecutionException {
final String description = "Grails Descriptor updated by grails-maven-plugin on " + new Date();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File(projectDir, "application.properties"));
final Properties properties = new Properties();
properties.setProperty("app.grails.version", grailsProjectDescriptor.getAppGrailsVersion());
properties.setProperty("app.name", grailsProjectDescriptor.getAppName());
properties.setProperty("app.version", grailsProjectDescriptor.getAppVersion());
properties.store(fos, description);
} catch (final IOException e) {
throw new MojoExecutionException("Unable to write grails project descriptor.", e);
} finally {
IOUtil.close(fos);
}
}
public GrailsPluginProject readGrailsPluginProject() throws MojoExecutionException {
final GrailsPluginProject pluginProject = new GrailsPluginProject();
final File[] files = getBasedir().listFiles(new FilenameFilter() {
public boolean accept(final File file, final String s) {
return s.endsWith(FILE_SUFFIX) && s.length() > FILE_SUFFIX.length();
}
});
if(files == null || files.length != 1) {
throw new MojoExecutionException("Could not find a plugin descriptor. Expected to find exactly one file " +
"called FooGrailsPlugin.groovy in '" + getBasedir().getAbsolutePath() + "'.");
}
final File descriptor = files[0];
pluginProject.setFileName(descriptor);
final String className = descriptor.getName().substring(0, descriptor.getName().length() - ".groovy".length());
final String pluginName = getLowerCaseHyphenSeparatedName(getLogicalName(className, "GrailsPlugin"));
pluginProject.setPluginName(pluginName);
final GroovyClassLoader classLoader = new GroovyClassLoader();
final AstPluginDescriptorReader reader = new AstPluginDescriptorReader(classLoader);
final GrailsPluginInfo info = reader.readPluginInfo(new org.codehaus.groovy.grails.io.support.FileSystemResource(descriptor));
final String version = info.getVersion();
if (version == null || version.trim().length() == 0) {
throw new MojoExecutionException("Plugin does not have a version!");
}
pluginProject.setVersion(version);
return pluginProject;
}
/**
* Retrieves the logical name of the class without the trailing name
* @param name The name of the class
* @param trailingName The trailing name
* @return The logical name
*/
public static String getLogicalName(String name, String trailingName) {
if (trailingName == null || trailingName.length() == 0) {
return getShortName(name);
}
String shortName = getShortName(name);
if (shortName.indexOf(trailingName) == - 1) {
return name;
}
return shortName.substring(0, shortName.length() - trailingName.length());
}
/**
* Returns the class name without the package prefix.
*
* @param className The class name to get a short name for
* @return The short name of the class
*/
public static String getShortName(String className) {
int i = className.lastIndexOf(".");
if (i > -1) {
className = className.substring(i + 1, className.length());
}
return className;
}
}