package com.perforce.p4maven.dev;
/*
* 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.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.Properties;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* This goal creates/updates a eclipse workspace to comply with Maven development code styling rules for Java and XML.
* It also hooks up the local Maven distribution ( ie the one that runs this goal) with M2Eclipse.
*/
@Mojo( name = "configure-eclipse-workspace", requiresProject = false, threadSafe = true )
public class ConfigureEclipseWorkspaceMojo
extends AbstractMojo
{
private static final String HTML_EDITOR_CONFIG_PATH =
".metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.css.core.prefs";
private static final String CSS_EDITOR_CONFIG_PATH =
".metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.html.core.prefs";
private static final String XML_EDITOR_CONFIG_PATH =
".metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.xml.core.prefs";
private static final String JDT_UI_CONFIG_PATH =
".metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs";
private static final String M2E_CORE_CONFIG_PATH =
".metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.m2e.core.prefs";
private static final String EDITOR_LINEWIDTH_KEY = "lineWidth";
private static final String EDITOR_INDENTATIONCHAR_KEY = "indentationChar";
private static final String EDITOR_INDENTATIONSIZE = "indentationSize";
/**
* Directory which hosts the eclipse workspace directory ( ie .metadata )
*
* @Parameter default-value = "."
*/
@Parameter( property = "workspaceDirectory", defaultValue = "." )
private File workspaceDirectory;
/**
* Eclipse Java code formatter file. Default is Maven code formatter
*
* @Parameter
*/
@Parameter( property = "javaFormatterLocation", defaultValue = "http://maven.apache.org/developers/maven-eclipse-codestyle.xml" )
private String javaFormatterLocation = "http://maven.apache.org/developers/maven-eclipse-codestyle.xml";
public void execute()
throws MojoExecutionException, MojoFailureException
{
setupHtmlEditorSettings();
setupCssEditorSettings();
setupXmlEditorSettings();
setupJavaFormatter();
setupM2Eclispe();
}
private void setupM2Eclispe()
{
File configFile = new File( workspaceDirectory, M2E_CORE_CONFIG_PATH );
File mvnHome = new File( System.getProperty( "maven.home" ) );
File settingsXml = new File( mvnHome, "conf/settings.xml" );
try
{
Properties props = loadPropertiesFromFile( configFile );
props.put( "eclipse.m2.defaultRuntime", mvnHome.getAbsolutePath() );
props.put( "eclipse.m2.globalSettingsFile", settingsXml.getAbsolutePath() );
props.put( "eclipse.m2.runtimes", mvnHome.getAbsolutePath() );
props.put( "eclipse.m2.defaultPomEditorPage", "true" );
props.put( "eclipse.preferences.version", "1" );
savePropertiesFromFile( configFile, props );
}
catch ( IOException e )
{
this.getLog().warn( "Unable to setup m2eclipse preference", e );
}
}
private void setupJavaFormatter()
throws MojoExecutionException, MojoFailureException
{
File tmpFile = null;
File configFile = new File( workspaceDirectory, JDT_UI_CONFIG_PATH );
try
{
tmpFile = File.createTempFile( "mojodev", "tmp" );
FileUtils.copyURLToFile( new URL( javaFormatterLocation ), tmpFile );
String formatterContent = FileUtils.fileRead( tmpFile );
Properties props = loadPropertiesFromFile( configFile );
props.setProperty( "formatter_profile", "_" + this.loadDefaultProfileName( tmpFile ) );
props.setProperty( "formatter_settings_version", "12" );
props.setProperty( "org.eclipse.jdt.ui.formatterprofiles", formatterContent );
savePropertiesFromFile( configFile, props );
}
catch ( IOException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
finally
{
if ( tmpFile != null )
{
tmpFile.delete();
}
}
}
private static final String ELT_PROFILE = "profile";
private String loadDefaultProfileName( File file )
throws MojoExecutionException
{
Reader reader = null;
try
{
reader = new InputStreamReader( new FileInputStream( file ) );
Xpp3Dom dom = Xpp3DomBuilder.build( reader );
Xpp3Dom[] existingProfiles = dom.getChildren( ELT_PROFILE );
if ( existingProfiles.length != 0 )
{
Xpp3Dom firstProfile = existingProfiles[0];
return firstProfile.getAttribute( "name" );
}
else
{
throw new MojoExecutionException( "Unable to discover java formatter profile name" );
}
}
catch ( XmlPullParserException e )
{
throw new MojoExecutionException( "Unable to discover java formatter profile name", e );
}
catch ( IOException e )
{
throw new MojoExecutionException( "Unable to discover java formatter profile name", e );
}
finally
{
IOUtil.close( reader );
}
}
private void setupHtmlEditorSettings()
throws MojoExecutionException, MojoFailureException
{
File configFile = new File( workspaceDirectory, HTML_EDITOR_CONFIG_PATH );
try
{
Properties props = loadPropertiesFromFile( configFile );
props.setProperty( EDITOR_LINEWIDTH_KEY, "120" );
props.setProperty( EDITOR_INDENTATIONCHAR_KEY, "space" );
props.setProperty( EDITOR_INDENTATIONSIZE, "2" );
savePropertiesFromFile( configFile, props );
}
catch ( IOException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
private void setupXmlEditorSettings()
throws MojoExecutionException, MojoFailureException
{
File configFile = new File( workspaceDirectory, XML_EDITOR_CONFIG_PATH );
try
{
Properties props = loadPropertiesFromFile( configFile );
props.setProperty( EDITOR_LINEWIDTH_KEY, "120" );
props.setProperty( EDITOR_INDENTATIONCHAR_KEY, "space" );
props.setProperty( EDITOR_INDENTATIONSIZE, "2" );
savePropertiesFromFile( configFile, props );
}
catch ( IOException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
private void setupCssEditorSettings()
throws MojoExecutionException, MojoFailureException
{
File configFile = new File( workspaceDirectory, CSS_EDITOR_CONFIG_PATH );
try
{
Properties props = loadPropertiesFromFile( configFile );
props.setProperty( EDITOR_LINEWIDTH_KEY, "120" );
props.setProperty( EDITOR_INDENTATIONCHAR_KEY, "space" );
props.setProperty( EDITOR_INDENTATIONSIZE, "2" );
savePropertiesFromFile( configFile, props );
}
catch ( IOException e )
{
throw new MojoExecutionException( e.getMessage(), e );
}
}
private static Properties loadPropertiesFromFile( File file )
throws IOException
{
if ( !file.exists() )
{
return new Properties();
}
FileInputStream is = null;
try
{
is = new FileInputStream( file );
Properties props = new Properties();
props.load( is );
return props;
}
finally
{
IOUtil.close( is );
}
}
private static void savePropertiesFromFile( File file, Properties properties )
throws IOException
{
file.getParentFile().mkdirs();
FileOutputStream fs = null;
try
{
fs = new FileOutputStream( file );
properties.store( fs, null );
}
finally
{
IOUtil.close( fs );
}
}
}