/*******************************************************************************
* 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.AbstractLiferayProjectProvider;
import com.liferay.ide.core.ILiferayProject;
import com.liferay.ide.core.LiferayNature;
import com.liferay.ide.maven.core.aether.AetherUtil;
import com.liferay.ide.project.core.ProjectCore;
import com.liferay.ide.project.core.descriptor.UpdateDescriptorVersionOperation;
import com.liferay.ide.project.core.model.NewLiferayProfile;
import com.liferay.ide.project.core.model.ProfileLocation;
import com.liferay.ide.project.core.util.SearchFilesVisitor;
import com.liferay.ide.server.util.ComponentUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.model.Model;
import org.apache.maven.settings.Profile;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.resolution.VersionRangeRequest;
import org.eclipse.aether.resolution.VersionRangeResolutionException;
import org.eclipse.aether.resolution.VersionRangeResult;
import org.eclipse.aether.version.Version;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.embedder.IMaven;
import org.eclipse.m2e.core.internal.IMavenConstants;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.document.DocumentTypeImpl;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
/**
* @author Gregory Amerson
* @author Simon Jiang
* @author Kuo Zhang
* @author Terry Jia
*/
@SuppressWarnings( "restriction" )
public class LiferayMavenProjectProvider extends AbstractLiferayProjectProvider
{
private static final String[] fileNames =
{
"liferay-portlet.xml",
"liferay-display.xml",
"service.xml",
"liferay-hook.xml",
"liferay-layout-templates.xml",
"liferay-look-and-feel.xml",
"liferay-portlet-ext.xml"
};
private static final Pattern publicid_pattern = Pattern.compile(
"-\\//(?:[a-z][a-z]+)\\//(?:[a-z][a-z]+)[\\s+(?:[a-z][a-z0-9_]*)]*\\s+(\\d\\.\\d\\.\\d)\\//(?:[a-z][a-z]+)",
Pattern.CASE_INSENSITIVE | Pattern.DOTALL );
private static final Pattern systemid_pattern = Pattern.compile(
"^http://www.liferay.com/dtd/[-A-Za-z0-9+&@#/%?=~_()]*(\\d_\\d_\\d).dtd", Pattern.CASE_INSENSITIVE |
Pattern.DOTALL );
public LiferayMavenProjectProvider()
{
super( new Class<?>[] { IProject.class } );
}
@Override
public <T> List<T> getData( String key, Class<T> type, Object... params )
{
List<T> retval = null;
if( "profileIds".equals( key ) )
{
final List<T> profileIds = new ArrayList<T>();
try
{
final List<Profile> profiles = MavenPlugin.getMaven().getSettings().getProfiles();
for( final Profile profile : profiles )
{
if( profile.getActivation() != null )
{
if( profile.getActivation().isActiveByDefault() )
{
continue;
}
}
profileIds.add( type.cast( profile.getId() ) );
}
if( params[0] != null && params[0] instanceof File )
{
final File locationDir = (File) params[0];
File pomFile = new File( locationDir, IMavenConstants.POM_FILE_NAME );
if( ! pomFile.exists() && locationDir.getParentFile().exists() )
{
// try one level up for when user is adding new module
pomFile = new File( locationDir.getParentFile(), IMavenConstants.POM_FILE_NAME );
}
if( pomFile.exists() )
{
final IMaven maven = MavenPlugin.getMaven();
Model model = maven.readModel( pomFile );
File parentDir = pomFile.getParentFile();
while( model != null )
{
for( org.apache.maven.model.Profile p : model.getProfiles() )
{
profileIds.add( type.cast( p.getId() ) );
}
parentDir = parentDir.getParentFile();
if( parentDir != null && parentDir.exists() )
{
try
{
model = maven.readModel( new File( parentDir, IMavenConstants.POM_FILE_NAME ) );
}
catch( Exception e)
{
model = null;
}
}
}
}
}
}
catch( CoreException e )
{
LiferayMavenCore.logError( e );
}
retval = profileIds;
}
else if( "liferayVersions".equals( key ) )
{
final List<T> possibleVersions = new ArrayList<T>();
final RepositorySystem system = AetherUtil.newRepositorySystem();
final RepositorySystemSession session = AetherUtil.newRepositorySystemSession( system );
final String groupId = params[0].toString();
final String artifactId = params[1].toString();
final String coords = groupId + ":" + artifactId + ":[6,)";
final Artifact artifact = new DefaultArtifact( coords );
final VersionRangeRequest rangeRequest = new VersionRangeRequest();
rangeRequest.setArtifact( artifact );
rangeRequest.addRepository( AetherUtil.newCentralRepository() );
rangeRequest.addRepository( AetherUtil.newLiferayRepository() );
try
{
final VersionRangeResult rangeResult = system.resolveVersionRange( session, rangeRequest );
final List<Version> versions = rangeResult.getVersions();
for( Version version : versions )
{
final String val = version.toString();
if( ! "6.2.0".equals( val ) )
{
possibleVersions.add( type.cast( val ) );
}
}
retval = possibleVersions;
}
catch( VersionRangeResolutionException e )
{
}
}
else if( "parentVersion".equals( key ) )
{
final List<T> version = new ArrayList<T>();
final File locationDir = (File) params[0];
final File parentPom = new File( locationDir, IMavenConstants.POM_FILE_NAME );
if( parentPom.exists() )
{
try
{
final IMaven maven = MavenPlugin.getMaven();
final Model model = maven.readModel( parentPom );
version.add( type.cast( model.getVersion() ) );
retval = version;
}
catch( CoreException e )
{
LiferayMavenCore.logError( "unable to get parent version", e );
}
}
}
else if( "parentGroupId".equals( key ) )
{
final List<T> groupId = new ArrayList<T>();
final File locationDir = (File) params[0];
final File parentPom = new File( locationDir, IMavenConstants.POM_FILE_NAME );
if( parentPom.exists() )
{
try
{
final IMaven maven = MavenPlugin.getMaven();
final Model model = maven.readModel( parentPom );
groupId.add( type.cast( model.getGroupId() ) );
retval = groupId;
}
catch( CoreException e )
{
LiferayMavenCore.logError( "unable to get parent groupId", e );
}
}
}
else if( "archetypeGAV".equals( key ) )
{
final String frameworkType = (String) params[0];
final String value = LiferayMavenCore.getPreferenceString( "archetype-gav-" + frameworkType, "" );
retval = Collections.singletonList( type.cast( value ) );
}
return retval;
}
private IFile[] getLiferayMetaFiles( IProject project )
{
List<IFile> files = new ArrayList<IFile>();
for( String name : fileNames )
{
files.addAll( new SearchFilesVisitor().searchFiles( project, name ) );
}
return files.toArray( new IFile[files.size()] );
}
private String getNewDoctTypeSetting( String doctypeSetting, String newValue, Pattern p )
{
String newDoctTypeSetting = null;
final Matcher m = p.matcher( doctypeSetting );
if( m.find() )
{
String oldVersionString = m.group( m.groupCount() );
newDoctTypeSetting = doctypeSetting.replace( oldVersionString, newValue );
}
return newDoctTypeSetting;
}
protected String getNewLiferayProfilesPluginVersion( String[] activeProfiles, List<NewLiferayProfile> newLiferayProfiles, String archetypeVersion )
{
org.osgi.framework.Version minVersion = new org.osgi.framework.Version( archetypeVersion.substring( 0, 3 ) );
try
{
final List<Profile> profiles = MavenPlugin.getMaven().getSettings().getProfiles();
org.osgi.framework.Version minNewVersion =
new org.osgi.framework.Version( archetypeVersion.substring( 0, 3 ) );
org.osgi.framework.Version minExistedVersion =
new org.osgi.framework.Version( archetypeVersion.substring( 0, 3 ) );
for( final String activeProfile : activeProfiles )
{
for( final NewLiferayProfile newProfile : newLiferayProfiles )
{
if( activeProfile.equals( newProfile.getId().content() ) )
{
final String liferayVersion = newProfile.getLiferayVersion().content();
final org.osgi.framework.Version shortLiferayVersion =
new org.osgi.framework.Version( liferayVersion.substring( 0, 3 ) );
final org.osgi.framework.Version shortPluginVersion =
new org.osgi.framework.Version( archetypeVersion.substring( 0, 3 ) );
minNewVersion = shortLiferayVersion.compareTo( shortPluginVersion ) < 0
? shortLiferayVersion : shortPluginVersion;
}
}
minVersion = minVersion.compareTo( minNewVersion ) < 0 ? minVersion : minNewVersion;
for( final Profile existProfile : profiles )
{
if( activeProfile.equals( existProfile.getId() ) )
{
final Properties properties = existProfile.getProperties();
final String liferayVersion = properties.getProperty( "liferay.version" );
final String pluginVersion = properties.getProperty( "liferay.maven.plugin.version" );
if( pluginVersion != null && liferayVersion != null )
{
final org.osgi.framework.Version shortLiferayVersion =
new org.osgi.framework.Version( liferayVersion.substring( 0, 3 ) );
final org.osgi.framework.Version shortPluginVersion =
new org.osgi.framework.Version( pluginVersion.substring( 0, 3 ) );
minExistedVersion = shortLiferayVersion.compareTo( shortPluginVersion ) < 0
? shortLiferayVersion : shortPluginVersion;
}
}
}
minVersion = minVersion.compareTo( minExistedVersion ) < 0 ? minVersion : minExistedVersion;
}
}
catch(Exception e)
{
}
return minVersion.toString();
}
protected List<NewLiferayProfile> getNewProfilesToSave(
String[] activeProfiles, List<NewLiferayProfile> newLiferayProfiles, ProfileLocation location )
{
List<NewLiferayProfile> profilesToSave = new ArrayList<NewLiferayProfile>();
for( String activeProfile : activeProfiles )
{
for( NewLiferayProfile newProfile : newLiferayProfiles )
{
if( activeProfile.equals( newProfile.getId().content() ) &&
newProfile.getProfileLocation().content().equals( location ) )
{
profilesToSave.add( newProfile );
}
}
}
return profilesToSave;
}
@Override
public ILiferayProject provide( Object adaptable )
{
if( adaptable instanceof IProject )
{
final IProject project = (IProject) adaptable;
try
{
if( MavenUtil.isMavenProject( project ) )
{
final boolean hasLiferayNature = LiferayNature.hasNature( project );
final boolean hasLiferayFacet = ComponentUtil.hasLiferayFacet( project );
if( hasLiferayNature && hasLiferayFacet )
{
return new FacetedMavenBundleProject( project );
}
else if( hasLiferayFacet )
{
return new FacetedMavenProject( project );
}
else if( hasLiferayNature )
{
return new MavenBundlePluginProject( project );
}
else
{
// return dummy maven project that can't lookup docroot resources
return new LiferayMavenProject( project )
{
@Override
public IFile getDescriptorFile( String name )
{
return null;
}
@Override
public IFolder[] getSourceFolders()
{
return null;
}
};
}
}
}
catch( CoreException e )
{
LiferayMavenCore.logError(
"Unable to create ILiferayProject from maven project " + project.getName(), e );
}
}
return null;
}
protected void updateDtdVersion( IProject project, String dtdVersion, String archetypeVesion )
{
final String tmpPublicId = dtdVersion;
final String tmpSystemId = dtdVersion.replaceAll( "\\.", "_" );
IStructuredModel editModel = null;
final IFile[] metaFiles = getLiferayMetaFiles( project );
for( IFile file : metaFiles )
{
try
{
editModel = StructuredModelManager.getModelManager().getModelForEdit( file );
if( editModel != null && editModel instanceof IDOMModel )
{
final IDOMDocument xmlDocument = ( (IDOMModel) editModel ).getDocument();
final DocumentTypeImpl docType = (DocumentTypeImpl) xmlDocument.getDoctype();
final String publicId = docType.getPublicId();
final String newPublicId = getNewDoctTypeSetting( publicId, tmpPublicId, publicid_pattern );
if( newPublicId != null )
{
docType.setPublicId( newPublicId );
}
final String systemId = docType.getSystemId();
final String newSystemId = getNewDoctTypeSetting( systemId, tmpSystemId, systemid_pattern );
if( newSystemId != null )
{
docType.setSystemId( newSystemId );
}
editModel.save();
}
}
catch( Exception e )
{
final IStatus error =
ProjectCore.createErrorStatus(
"Unable to upgrade deployment meta file for " + file.getName(), e );
ProjectCore.logError( error );
}
finally
{
if ( editModel != null )
{
editModel.releaseFromEdit();
}
}
}
ProjectCore.operate( project, UpdateDescriptorVersionOperation.class, archetypeVesion, dtdVersion );
}
}