/******************************************************************************* * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * *******************************************************************************/ package com.liferay.ide.maven.core; import com.liferay.ide.core.util.CoreUtil; import com.liferay.ide.project.core.IPortletFramework; import com.liferay.ide.project.core.NewLiferayProjectProvider; import com.liferay.ide.project.core.model.NewLiferayPluginProjectOp; import com.liferay.ide.project.core.model.NewLiferayPluginProjectOpMethods; import com.liferay.ide.project.core.model.NewLiferayProfile; import com.liferay.ide.project.core.model.PluginType; import com.liferay.ide.project.core.model.ProfileLocation; import com.liferay.ide.project.core.model.ProjectName; import com.liferay.ide.theme.core.util.ThemeUtil; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.List; import java.util.Properties; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.FileUtils; import org.apache.maven.archetype.catalog.Archetype; import org.apache.maven.archetype.exception.UnknownArchetype; import org.apache.maven.archetype.metadata.RequiredProperty; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.cli.configuration.SettingsXmlConfigurationProcessor; import org.apache.maven.model.Model; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.embedder.IMaven; import org.eclipse.m2e.core.embedder.IMavenConfiguration; import org.eclipse.m2e.core.internal.IMavenConstants; import org.eclipse.m2e.core.internal.MavenPluginActivator; import org.eclipse.m2e.core.internal.archetype.ArchetypeManager; import org.eclipse.m2e.core.project.IMavenProjectFacade; import org.eclipse.m2e.core.project.IMavenProjectRegistry; import org.eclipse.m2e.core.project.IProjectConfigurationManager; import org.eclipse.m2e.core.project.MavenUpdateRequest; import org.eclipse.m2e.core.project.ProjectImportConfiguration; import org.eclipse.m2e.core.project.ResolverConfiguration; import org.eclipse.sapphire.ElementList; import org.eclipse.sapphire.platform.PathBridge; import org.eclipse.wst.sse.core.StructuredModelManager; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; import org.w3c.dom.Document; /** * @author Gregory Amerson * @author Simon Jiang * @author Kuo Zhang * @author Terry Jia */ @SuppressWarnings( "restriction" ) public class NewMavenPluginProjectProvider extends LiferayMavenProjectProvider implements NewLiferayProjectProvider<NewLiferayPluginProjectOp> { @Override public IStatus createNewProject( NewLiferayPluginProjectOp op, IProgressMonitor monitor ) throws CoreException { ElementList<ProjectName> projectNames = op.getProjectNames(); IStatus retval = null; final IMavenConfiguration mavenConfiguration = MavenPlugin.getMavenConfiguration(); final IMavenProjectRegistry mavenProjectRegistry = MavenPlugin.getMavenProjectRegistry(); final IProjectConfigurationManager projectConfigurationManager = MavenPlugin.getProjectConfigurationManager(); final String groupId = op.getGroupId().content(); final String artifactId = op.getProjectName().content(); final String version = op.getArtifactVersion().content(); final String javaPackage = op.getGroupId().content(); final String activeProfilesValue = op.getActiveProfilesValue().content(); final IPortletFramework portletFramework = op.getPortletFramework().content( true ); final String frameworkName = NewLiferayPluginProjectOpMethods.getFrameworkName( op ); IPath location = PathBridge.create( op.getLocation().content() ); // for location we should use the parent location if( location.lastSegment().equals( artifactId ) ) { // use parent dir since maven archetype will generate new dir under this location location = location.removeLastSegments( 1 ); } final String archetypeArtifactId = op.getArchetype().content( true ); final Archetype archetype = new Archetype(); final String[] gav = archetypeArtifactId.split( ":" ); final String archetypeVersion = gav[gav.length - 1]; archetype.setGroupId( gav[0] ); archetype.setArtifactId( gav[1] ); archetype.setVersion( archetypeVersion ); final ArchetypeManager archetypeManager = MavenPluginActivator.getDefault().getArchetypeManager(); final ArtifactRepository remoteArchetypeRepository = archetypeManager.getArchetypeRepository( archetype ); final Properties properties = new Properties(); try { final List<?> archProps = archetypeManager.getRequiredProperties( archetype, remoteArchetypeRepository, monitor ); if( !CoreUtil.isNullOrEmpty( archProps ) ) { for( Object prop : archProps ) { if( prop instanceof RequiredProperty ) { final RequiredProperty rProp = (RequiredProperty) prop; if( op.getPluginType().content().equals( PluginType.theme ) ) { final String key = rProp.getKey(); if( key.equals( "themeParent" ) ) { properties.put( key, op.getThemeParent().content( true ) ); } else if( key.equals( "themeType" ) ) { properties.put( key, ThemeUtil.getTemplateExtension( op.getThemeFramework().content( true ) ) ); } } else { properties.put( rProp.getKey(), rProp.getDefaultValue() ); } } } } } catch( UnknownArchetype e1 ) { LiferayMavenCore.logError( "Unable to find archetype required properties", e1 ); } final ResolverConfiguration resolverConfig = new ResolverConfiguration(); if( ! CoreUtil.isNullOrEmpty( activeProfilesValue ) ) { resolverConfig.setSelectedProfiles( activeProfilesValue ); } final ProjectImportConfiguration configuration = new ProjectImportConfiguration( resolverConfig ); final List<IProject> newProjects = projectConfigurationManager.createArchetypeProjects( location, archetype, groupId, artifactId, version, javaPackage, properties, configuration, monitor ); if( !CoreUtil.isNullOrEmpty( newProjects ) ) { for( IProject project : newProjects ) { projectNames.insert().setName( project.getName() ); } } if( CoreUtil.isNullOrEmpty( newProjects ) ) { retval = LiferayMavenCore.createErrorStatus( "New project was not created due to unknown error" ); } else { final IProject firstProject = newProjects.get( 0 ); // add new profiles if it was specified to add to project or parent poms if( ! CoreUtil.isNullOrEmpty( activeProfilesValue ) ) { final String[] activeProfiles = activeProfilesValue.split( "," ); // find all profiles that should go in user settings file final List<NewLiferayProfile> newUserSettingsProfiles = getNewProfilesToSave( activeProfiles, op.getNewLiferayProfiles(), ProfileLocation.userSettings ); if( newUserSettingsProfiles.size() > 0 ) { final String userSettingsFile = mavenConfiguration.getUserSettingsFile(); String userSettingsPath = null; if( CoreUtil.isNullOrEmpty( userSettingsFile ) ) { userSettingsPath = SettingsXmlConfigurationProcessor.DEFAULT_USER_SETTINGS_FILE.getAbsolutePath(); } else { userSettingsPath = userSettingsFile; } try { // backup user's settings.xml file final File settingsXmlFile = new File( userSettingsPath ); final File backupFile = getBackupFile( settingsXmlFile ); FileUtils.copyFile( settingsXmlFile, backupFile ); final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); final DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); final Document pomDocument = docBuilder.parse( settingsXmlFile.getCanonicalPath() ); for( NewLiferayProfile newProfile : newUserSettingsProfiles ) { MavenUtil.createNewLiferayProfileNode( pomDocument, newProfile ); } TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource( pomDocument ); StreamResult result = new StreamResult( settingsXmlFile ); transformer.transform(source, result); } catch( Exception e ) { LiferayMavenCore.logError( "Unable to save new Liferay profile to user settings.xml.", e ); } } // find all profiles that should go in the project pom final List<NewLiferayProfile> newProjectPomProfiles = getNewProfilesToSave( activeProfiles, op.getNewLiferayProfiles(), ProfileLocation.projectPom ); // only need to set the first project as nested projects should pickup the parent setting final IMavenProjectFacade newMavenProject = mavenProjectRegistry.getProject( firstProject ); final IFile pomFile = newMavenProject.getPom(); IDOMModel domModel = null; try { domModel = (IDOMModel) StructuredModelManager.getModelManager().getModelForEdit( pomFile ); for( final NewLiferayProfile newProfile : newProjectPomProfiles ) { MavenUtil.createNewLiferayProfileNode( domModel.getDocument(), newProfile ); } domModel.save(); } catch( IOException e ) { LiferayMavenCore.logError( "Unable to save new Liferay profiles to project pom.", e ); } finally { if( domModel != null ) { domModel.releaseFromEdit(); } } for( final IProject project : newProjects ) { try { projectConfigurationManager.updateProjectConfiguration( new MavenUpdateRequest( project, mavenConfiguration.isOffline(), true ), monitor ); } catch( Exception e ) { LiferayMavenCore.logError( "Unable to update configuration for " + project.getName(), e ); } } final String pluginVersion = getNewLiferayProfilesPluginVersion( activeProfiles, op.getNewLiferayProfiles(), archetypeVersion ); final String archVersion = MavenUtil.getMajorMinorVersionOnly( archetypeVersion ); updateDtdVersion( firstProject, pluginVersion, archVersion ); } if( op.getPluginType().content().equals( PluginType.portlet ) ) { final String portletName = op.getPortletName().content( false ); retval = portletFramework.postProjectCreated( firstProject, frameworkName, portletName, monitor ); } } if( retval == null ) { retval = Status.OK_STATUS; } return retval; } private File getBackupFile( final File file ) { final String suffix = new SimpleDateFormat( "yyyyMMddhhmmss" ).format( Calendar.getInstance().getTime() ); return new File( file.getParentFile(), file.getName() + "." + suffix ); } @Override public IStatus validateProjectLocation( String projectName, IPath path ) { IStatus retval = Status.OK_STATUS; // if the path is a folder and it has a pom.xml that is a package type of 'pom' then this is a valid location //if projectName is null or empty , don't need to check , just return if( CoreUtil.isNullOrEmpty(projectName) ) return retval; final File dir = path.toFile(); if( dir.exists() ) { final File pomFile = path.append( IMavenConstants.POM_FILE_NAME ).toFile(); if( pomFile.exists() ) { final IMaven maven = MavenPlugin.getMaven(); try { final Model result = maven.readModel( pomFile ); if( ! "pom".equals( result.getPackaging() ) ) { retval = LiferayMavenCore.createErrorStatus( "\"" + pomFile.getParent() + "\" contains a non-parent maven project." ); } else { final String name = result.getName(); if( projectName.equals( name ) ) { retval = LiferayMavenCore.createErrorStatus( "The project name \"" + projectName + "\" can't be the same as the parent." ); } else { final IPath newProjectPath = path.append( projectName ); retval = validateProjectLocation( projectName, newProjectPath ); } } } catch( CoreException e ) { retval = LiferayMavenCore.createErrorStatus( "Invalid project location.", e ); LiferayMavenCore.log( retval ); } } else { final File[] files = dir.listFiles(); if( files.length > 0 ) { retval = LiferayMavenCore.createErrorStatus( "Project location is not empty or a parent pom." ); } } } return retval; } }