blob: ee72ec2882d5b93a48100e9a08500166f68d9386 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Sonatype, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.m2e.wtp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Set;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.embedder.IMaven;
import org.eclipse.m2e.core.internal.IMavenConstants;
import org.eclipse.m2e.core.internal.MavenPluginActivator;
import org.eclipse.m2e.core.internal.markers.IMavenMarkerManager;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.core.project.IMavenProjectRegistry;
import org.eclipse.m2e.wtp.earmodules.EarModule;
import org.eclipse.m2e.wtp.internal.Messages;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.navigator.CommonNavigator;
/**
* Deployment Descriptor Management based on maven-ear-plugin invocation
*
* @provisional This class has been added as part of a work in progress.
* It is not guaranteed to work or remain the same in future releases.
* For more information contact <a href="mailto:m2e-wtp-dev@eclipse.org">m2e-wtp-dev@eclipse.org</a>.
*
* @author Fred Bricon
* @author Snjezana Peco
*/
@SuppressWarnings("restriction")
public class MavenDeploymentDescriptorManagement implements DeploymentDescriptorManagement {
private static final VersionRange VALID_EAR_PLUGIN_RANGE;
static {
try {
VALID_EAR_PLUGIN_RANGE = VersionRange.createFromVersionSpec("[2.4.3,)"); //$NON-NLS-1$
} catch(InvalidVersionSpecificationException ex) {
//Can't happen
throw new RuntimeException("Unable to create ear plugin version range from [2.4.3,)", ex); //$NON-NLS-1$
}
}
/**
* Executes ear:generate-application-xml goal to generate application.xml (and jboss-app.xml if needed). Existing
* files will be overwritten.
*
* @throws CoreException
*/
@Override
public void updateConfiguration(IProject project, MavenProject mavenProject, EarPluginConfiguration plugin,
boolean useBuildDirectory, IProgressMonitor monitor) throws CoreException {
IMavenProjectRegistry projectManager = MavenPlugin.getMavenProjectRegistry();
IMavenProjectFacade mavenFacade = projectManager.getProject(project);
IMavenMarkerManager markerManager = MavenPluginActivator.getDefault().getMavenMarkerManager();
IFile pomResource = project.getFile(IMavenConstants.POM_FILE_NAME);
markerManager.deleteMarkers(pomResource, MavenWtpConstants.WTP_MARKER_GENERATE_APPLICATIONXML_ERROR);
//Create a maven request + session
IMaven maven = MavenPlugin.getMaven();
MavenExecutionRequest request = projectManager.createExecutionRequest(pomResource, mavenFacade.getResolverConfiguration(), monitor);
MavenSession session = maven.createSession(request, mavenProject);
MavenExecutionPlan executionPlan = maven.calculateExecutionPlan(session, mavenProject, Collections.singletonList("ear:generate-application-xml"), true, monitor); //$NON-NLS-1$
MojoExecution genConfigMojo = getExecution(executionPlan, "maven-ear-plugin", "generate-application-xml"); //$NON-NLS-1$ //$NON-NLS-2$
if(genConfigMojo == null) {
//TODO Better error management
return;
}
//Let's force the generated config files location
Xpp3Dom configuration = genConfigMojo.getConfiguration();
if(configuration == null) {
configuration = new Xpp3Dom("configuration"); //$NON-NLS-1$
genConfigMojo.setConfiguration(configuration);
}
File tempDirectory;
try {
tempDirectory = getTempDirectory();
} catch(IOException ex) {
IStatus status = new Status(IStatus.ERROR, MavenWtpPlugin.ID, ex.getLocalizedMessage(), ex);
throw new CoreException(status);
}
// Some old maven-ear-plugin have a dependency on an old plexus-util version that prevents
// using workdirectory == generatedDescriptorLocation, so we keep them separated
File generatedDescriptorLocation = new File(tempDirectory, "generatedDescriptorLocation"); //$NON-NLS-1$
File workDirectory = new File(tempDirectory, "workDirectory"); //$NON-NLS-1$
Xpp3Dom workDirectoryDom = configuration.getChild("workDirectory"); //$NON-NLS-1$
if(workDirectoryDom == null) {
workDirectoryDom = new Xpp3Dom("workDirectory"); //$NON-NLS-1$
configuration.addChild(workDirectoryDom);
}
workDirectoryDom.setValue(workDirectory.getAbsolutePath());
Xpp3Dom genDescriptorLocationDom = configuration.getChild("generatedDescriptorLocation"); //$NON-NLS-1$
if(genDescriptorLocationDom == null) {
genDescriptorLocationDom = new Xpp3Dom("generatedDescriptorLocation"); //$NON-NLS-1$
configuration.addChild(genDescriptorLocationDom);
}
genDescriptorLocationDom.setValue(generatedDescriptorLocation.getAbsolutePath());
// Fix for http://jira.codehaus.org/browse/MEAR-116?focusedCommentId=232316&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_232316
// affecting maven-ear-plugin version < 2.4.3
if(!VALID_EAR_PLUGIN_RANGE.containsVersion(new DefaultArtifactVersion(genConfigMojo.getVersion()))) {
overrideModules(configuration, plugin.getAllEarModules());
}
//Execute our modified mojo
maven.execute(session, genConfigMojo, monitor);
if (session.getResult().hasExceptions()){
markerManager.addMarkers(mavenFacade.getPom(), MavenWtpConstants.WTP_MARKER_GENERATE_APPLICATIONXML_ERROR, session.getResult());
}
//Copy generated files to their final location
File[] files = generatedDescriptorLocation.listFiles();
//MECLIPSEWTP-56 : application.xml should not be generated in the source directory
IFolder targetFolder;
IFolder earResourcesFolder = getEarResourcesDir(project, mavenProject, monitor);
if (useBuildDirectory) {
targetFolder = earResourcesFolder;
} else {
targetFolder = project.getFolder(plugin.getEarContentDirectory(project));
if (earResourcesFolder.exists() && earResourcesFolder.isAccessible()) {
earResourcesFolder.delete(true, monitor);
}
}
IFolder metaInfFolder = targetFolder.getFolder("/META-INF/"); //$NON-NLS-1$
if (files != null && files.length > 0) {
for (File file:files) {
if (!metaInfFolder.exists()) {
ProjectUtils.createFolder(metaInfFolder, monitor);
}
InputStream is = null;
try {
is = new FileInputStream(file);
IFile targetResource = metaInfFolder.getFile(file.getName());
if (targetResource.exists()) {
targetResource.setContents(is, IResource.FORCE, monitor);
} else {
targetResource.create(is, true, monitor);
}
} catch (FileNotFoundException ex) {
IStatus status = new Status(IStatus.ERROR, MavenWtpPlugin.ID, IStatus.ERROR, ex.getMessage(), ex);
throw new CoreException(status);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ex) {
// ignore
}
}
}
}
}
deleteDirectory(generatedDescriptorLocation);
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (PlatformUI.isWorkbenchRunning()) {
IViewPart view = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(IPageLayout.ID_PROJECT_EXPLORER);
if (view instanceof CommonNavigator) {
CommonNavigator navigator = (CommonNavigator) view;
navigator.getCommonViewer().refresh();
}
}
}
});
}
private IFolder getEarResourcesDir(IProject project, MavenProject mavenProject, IProgressMonitor monitor)
throws CoreException {
String appResourcesDir = ProjectUtils.getM2eclipseWtpFolder(mavenProject, project).toPortableString()+Path.SEPARATOR+MavenWtpConstants.EAR_RESOURCES_FOLDER;
IFolder appResourcesFolder = project.getFolder(appResourcesDir);
if (!appResourcesFolder.exists()) {
ProjectUtils.createFolder(appResourcesFolder, monitor);
}
if (!appResourcesFolder.isDerived()) {
appResourcesFolder.setDerived(true, monitor);
}
return appResourcesFolder;
}
private void overrideModules(Xpp3Dom configuration, Set<EarModule> earModules) {
Xpp3Dom modules = configuration.getChild("modules"); //$NON-NLS-1$
if(modules == null) {
modules = new Xpp3Dom("modules"); //$NON-NLS-1$
configuration.addChild(modules);
}
//TODO find a more elegant way to clear the modules
while(modules.getChildCount() > 0) {
modules.removeChild(0);
}
//Recreate the module's children, forcing the uri.
for(EarModule earModule : earModules) {
modules.addChild(earModule.getAsDom());
}
}
private File getTempDirectory() throws IOException {
File tempDir = new File(System.getProperty("java.io.tmpdir")); //$NON-NLS-1$
File dir = new File(tempDir, ".mavenDeploymentDescriptorManagement"); //$NON-NLS-1$
if(dir.exists()) {
if(dir.isFile()) {
if(!dir.delete()) {
throw new IOException(NLS.bind(Messages.MavenDeploymentDescriptorManagement_Error_Deleting_Temp_Folder, dir.getAbsolutePath()));
}
} else if(!deleteDirectory(dir)) {
throw new IOException(NLS.bind(Messages.MavenDeploymentDescriptorManagement_Error_Deleting_Temp_Folder, dir.getAbsolutePath()));
}
}
dir.mkdir();
return dir;
}
private static boolean deleteDirectory(File path) {
if(path.exists()) {
File[] files = path.listFiles();
for(int i = 0; i < files.length; i++ ) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
} else {
files[i].delete();
}
}
}
return (path.delete());
}
private MojoExecution getExecution(MavenExecutionPlan executionPlan, String artifactId, String goal) throws CoreException {
for(MojoExecution execution : executionPlan.getMojoExecutions()) {
if(artifactId.equals(execution.getArtifactId()) && goal.equals(execution.getGoal())) {
return execution;
}
}
return null;
}
}