blob: 2e5da9710432c21d951ced1e48a0662feaf3b96d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 RCP Vision (http://www.rcp-vision.com) and others.
* 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
*
* Contributors:
* Vincenzo Caselli - Initial contribution and API
*******************************************************************************/
package org.eclipse.emf.parsley.web.tools;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.parsley.web.tools.ParsleyWebFacetInstallConfig.PERSISTENCE_OPTION;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jst.j2ee.web.componentcore.util.WebArtifactEdit;
import org.eclipse.jst.j2ee.webapplication.WebApp;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.common.componentcore.internal.ComponentcoreFactory;
import org.eclipse.wst.common.componentcore.internal.ProjectComponents;
import org.eclipse.wst.common.componentcore.internal.ReferencedComponent;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.internal.WorkbenchComponent;
import org.eclipse.wst.common.project.facet.core.IDelegate;
import org.eclipse.wst.common.project.facet.core.IProjectFacetVersion;
import org.eclipse.xtext.ui.XtextProjectHelper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import com.google.common.base.Strings;
/**
* Wizard class for execution of actions for the core Parsley-JEE project creation
*
* @author Vincenzo Caselli
*
*/
public class ParsleyWebFacetInstallDelegate implements IDelegate {
@Override
public void execute(final IProject iProject, final IProjectFacetVersion fv, final Object config, final IProgressMonitor monitor) throws CoreException {
monitor.beginTask("Processing EMF Parsley Web facet", 2);
final ParsleyWebFacetInstallConfig wizardUserOptions = (ParsleyWebFacetInstallConfig) config;
setWebModuleDependencies(iProject, monitor, wizardUserOptions);
final IFolder webInfLib = Utils.getFolder(iProject, "WEB-INF/lib");
// Utils.copyFromPluginToWorkspace(org.eclipse.emf.parsley.hwt.Activator.getDefault().getBundle(),
// new Path("/target/org.eclipse.emf.parsley.hwt-0.0.1-SNAPSHOT.jar"),
// webInfLib.getFile("org.eclipse.emf.parsley.hwt.jar"));
// Utils.copyFromPluginToWorkspace(org.eclipse.emf.parsley.web.servlets.Activator.getDefault().getBundle(), new Path("/target/org.eclipse.emf.parsley.web.servlets-0.0.1-SNAPSHOT.jar"),
// webInfLib.getFile("emf.parsley.web-core.jar"));
Utils.copyFile(iProject, monitor, "/templates/pom.xml", iProject.getFile("pom.xml"), new Properties());
addProjectNature(iProject, monitor, XtextProjectHelper.NATURE_ID);
addProjectNature(iProject, monitor, "org.eclipse.m2e.core.maven2Nature"); //TODO should take it from a predefined Maven plugin constant
Properties replaceStrings;
String projectName = iProject.getName();
IPackageFragment pack = JavaCore.create(iProject).getPackageFragmentRoot(iProject.getFolder("src")).createPackageFragment(projectName, true, monitor);
IFolder folder = iProject.getFolder(pack.getPath().removeFirstSegments(1));
replaceStrings = new Properties();
replaceStrings.setProperty("org.eclipse.emf.parsley.web.tools.servlets", projectName);
Utils.copyFile(iProject, monitor, "/templates/module.parsley", iProject.getFolder("src").getFile("module.parsley"), replaceStrings);
replaceStrings = new Properties();
replaceStrings.setProperty("org.eclipse.emf.parsley.web.tools.templates", projectName);
Utils.copyFile(iProject, monitor, "/templates/ParsleyWebGuiceModule.java", folder.getFile("ParsleyWebGuiceModule.java"), replaceStrings);
replaceStrings = new Properties();
replaceStrings.setProperty("org.eclipse.emf.parsley.web.tools.templates", projectName);
Utils.copyFile(iProject, monitor, "/templates/ParsleyGuiceServletContextListener.java", folder.getFile("ParsleyGuiceServletContextListener.java"), replaceStrings);
replaceStrings = new Properties();
replaceStrings.setProperty("org.eclipse.emf.parsley.web.tools.templates", projectName);
Utils.copyFile(iProject, monitor, "/templates/ParsleyContextListener.java", folder.getFile("ParsleyContextListener.java"), replaceStrings);
setupWebInfXml(iProject);
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.CLEAN_BUILD, monitor);
monitor.done();
}
private void setWebModuleDependencies(final IProject iProject, final IProgressMonitor monitor, ParsleyWebFacetInstallConfig wizardUserOptions) {
Set<String> pluginJarSet = getPluginJarSet(wizardUserOptions);
Map<String, Object> pluginInstalledPathMap = getInstalledPluginPathMap(pluginJarSet, monitor);
StructureEdit se = StructureEdit.getStructureEditForWrite(iProject);
ProjectComponents root = se.getComponentModelRoot();
WorkbenchComponent firstComponent = (WorkbenchComponent) root.getComponents().get(0);
addDependentModules(iProject, pluginInstalledPathMap, firstComponent, wizardUserOptions, monitor);
addMavenDependentModule(iProject, "guice-servlet-4.0.jar", "com/google/inject/extensions/guice-servlet/4.0", firstComponent, monitor);
addMavenDependentModule(iProject, "json-simple-1.1.1.jar", "com/googlecode/json-simple/json-simple/1.1.1", firstComponent, monitor);
se.save(monitor);
}
private void addProjectNature(final IProject iProject, final IProgressMonitor monitor, String natureId) throws CoreException {
IProjectDescription description = iProject.getDescription();
String[] currentNatures = description.getNatureIds();
String[] newNatures = Arrays.copyOf(currentNatures, currentNatures.length + 1);
newNatures[currentNatures.length] = natureId;
description.setNatureIds(newNatures);
iProject.setDescription(description, monitor);
}
private Set<String> getPluginJarSet(final ParsleyWebFacetInstallConfig wizardUserOptions) {
return new LinkedHashSet<String>() {
{
add("com.google.guava");
add("com.google.inject");
add("javax.inject");
add("javax.persistence");
add("org.apache.commons.logging");
add("org.apache.log4j");
add("org.eclipse.jface");
add("org.eclipse.core.commands");
add("org.eclipse.core.databinding");
add("org.eclipse.core.databinding.observable");
add("org.eclipse.core.databinding.property");
add("org.eclipse.jface.databinding");
add("org.eclipse.ui.workbench");
add("org.eclipse.equinox.common");
add("org.eclipse.ui.views");
add("org.eclipse.ui.forms");
// add("org.eclipse.swt.win32.win32.x86_64");
add("org.eclipse.emf");
add("org.eclipse.emf.common");
add("org.eclipse.emf.common.ui");
add("org.eclipse.emf.databinding");
add("org.eclipse.emf.ecore");
add("org.eclipse.emf.ecore.edit");
add("org.eclipse.emf.ecore.xmi");
add("org.eclipse.emf.edit");
add("org.eclipse.emf.edit.ui");
add("org.eclipse.equinox.registry");
add("org.eclipse.emf.parsley.common");
add("org.eclipse.emf.parsley.runtime.common");
add("org.eclipse.emf.parsley.web.servlets");
if (wizardUserOptions.getPersistenceOption().equals(PERSISTENCE_OPTION.TENEO)) {
// Just in case Teneo is installed, then its needed plugins are referenced
// in plugins
add("org.eclipse.emf.teneo.hibernate.mapper");
add("org.eclipse.emf.teneo.annotations");
add("org.eclipse.emf.teneo.hibernate");
add("org.eclipse.emf.teneo");
// Deps of org.hibernate
add("antlr");
add("hibernate-commons-annotations");
add("hibernate-core");
add("jboss-logging");
add("jboss-transaction-api_1.2_spec");
// Deps of org.eclipse.m2e.archetype.common
add("dom4j");
}
}
};
}
private Map<String, Object> getInstalledPluginPathMap(Set<String> pluginJarSet, final IProgressMonitor monitor) {
Map<String, Object> map = new HashMap<String, Object>();
try {
BundleContext ctx = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
Bundle[] bundles = ctx.getBundles();
for (Bundle bundle : bundles) {
String pluginId = bundle.getSymbolicName();
// if (bundle.getLocation().indexOf("/plugins/") > -1 && pluginId.indexOf("parsley") > -1) {
if (bundle.getLocation().indexOf("/plugins/") > -1 ) {
if (pluginJarSet.contains(pluginId)) {
map.put(pluginId, bundle);
logAdded(pluginId, "plugins", bundle.getLocation());
} else {
Dictionary<String, String> deps = bundle.getHeaders();
Enumeration<String> keysEnum = deps.keys();
while (keysEnum.hasMoreElements()) {
String depKey = keysEnum.nextElement();
String depsValues = deps.get(depKey);
// System.out.println("\t\t" + depKey + ": " + depsValues);
if ("Embedded-Artifacts".equals(depKey)) {
String[] depsArray = depsValues.split(";");
/*
* Structure has the following pattern:
*
* archetype-common-2.3.jar, g="org.apache.maven.archetype",
* a="archetype-common", v="2.3",
*
* dom4j-1.6.1.jar, g="dom4j", a="dom4j", v="1.6.1",
*/
for (int j = 0; j < depsArray.length; j++) {
// System.out.println("depsArray[" + j + "] = " + depsArray[j]);
if (depsArray[j].startsWith("a=\"")) {
String depId = depsArray[j].substring(3, depsArray[j].length() - 1);
// System.out.println(depId);
if (pluginJarSet.contains(depId)) {
String depIdWithVersion = depsArray[j - 2].split(",")[1];
map.put(depIdWithVersion, bundle.getSymbolicName() + "_" + bundle.getVersion() + "/" + depIdWithVersion);
logAdded(depIdWithVersion, "Embedded-Artifacts", bundle.getSymbolicName() + "_" + bundle.getVersion() + "/" + depIdWithVersion);
break;
}
}
}
// System.out.println(depsArray);
break;
}
if ("Bundle-ClassPath".equals(depKey)) {
if (!depsValues.equals(".")) {
String[] depsArray = depsValues.split(",");
// System.out.println(depsValues);
/*
* Structure has the following pattern:
*
* antlr-2.7.7.jar,c3p0-0.9.2.1.jar,dom4j-1.6.1.jar,ehcache-core
* -2.4 .3.jar, ...
*/
for (int j = 0; j < depsArray.length; j++) {
// System.out.println("depsArray[" + j + "] = " +
// depsArray[j]);
if (!depsArray[j].equals(".") && depsArray[j].lastIndexOf(".jar") > -1) {
String depId = depsArray[j].substring(0, depsArray[j].lastIndexOf(".jar"));
// System.out.println(depId);
depId = stripVersionIfExists(depId);
// String depId = depsArray[j].substring(0,
// depsArray[j].lastIndexOf("-"));
// System.out.println(depId);
if (pluginJarSet.contains(depId)) {
map.put(depsArray[j], bundle.getSymbolicName() + "_" + bundle.getVersion() + "/" + depsArray[j]);
logAdded(depsArray[j], "Bundle-ClassPath", bundle.getSymbolicName() + "_" + bundle.getVersion() + "/" + depsArray[j]);
}
}
}
// System.out.println(depsArray);
}
break;
}
}
}
// Enumeration<String> keys = bundle.getHeaders().keys();
// while (keys.hasMoreElements()) {
// String key = keys.nextElement();
// System.out.println(key + "\t\t" + bundle.getHeaders().get(key));
// }
}
}
monitor.worked(1);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return map;
}
private void logAdded(String pluginId, String from, String location) {
System.out.println("Added " + Strings.padEnd(pluginId, 50, ' ') + from + "\t\t" + location);
}
private String stripVersionIfExists(String depId) {
int posLastDot = depId.lastIndexOf('.');
int posLastDash = depId.lastIndexOf('-');
if (posLastDot > -1 && posLastDash > -1) {
return depId.substring(0, posLastDash);
}
return depId;
}
private void addDependentModules(IProject iProject, Map<String, Object> pluginInstalledPathMap, WorkbenchComponent firstComponent, ParsleyWebFacetInstallConfig wizardUserOptions,
IProgressMonitor monitor) {
for (String pluginId : pluginInstalledPathMap.keySet()) {
Object obj = pluginInstalledPathMap.get(pluginId);
String archiveName;
String bundleIdVersionJar;
String bundleUri = null;
if (obj instanceof Bundle) {
Bundle bundle = (Bundle) obj;
// System.out.println(bundle.getLocation());
if (("org.eclipse.emf.parsley.common".equals(pluginId) || "org.eclipse.emf.parsley.runtime.common".equals(pluginId))
&& !bundle.getLocation().endsWith(".jar")) {
checkForImportedPlugins(pluginId, bundle);
//EMF Parsley Project development case
bundleUri = "module:/resource/"+pluginId+"/"+pluginId;
//archiveName="org.eclipse.emf.parsley.runtime.common.jar"
//"module:/resource/org.eclipse.emf.parsley.runtime.common/org.eclipse.emf.parsley.runtime.common"
}
// bundleIdVersionJar = bundle.getSymbolicName() + "_" + bundle.getVersion() + ".jar";
bundleIdVersionJar = bundle.getLocation().substring("reference:/file:".length());
archiveName = bundle.getSymbolicName() + ".jar";
} else {
// String => Bundle dependency
bundleIdVersionJar = (String) obj;
archiveName = pluginId;
}
ReferencedComponent refC = ComponentcoreFactory.eINSTANCE.createReferencedComponent();
URI uri;
//"module:/classpath/lib/C:/Users/Vincenzo/.p2/pool/plugins/org.apache.batik.pdf_1.6.0.v201105071520.jar"
if (bundleUri!=null) {
//EMF Parsley Project development case
uri = URI.createURI(bundleUri);
} else {
// uri = URI.createURI("module:/classpath/var/ECLIPSE_HOME/plugins/" + bundleIdVersionJar);
uri = URI.createURI("module:/classpath/lib/" + bundleIdVersionJar);
}
refC.setHandle(uri);
refC.setArchiveName(archiveName);
Path newPath = new Path("/WEB-INF/lib");
refC.setRuntimePath(newPath);
firstComponent.getReferencedComponents().add(refC);
}
}
private void checkForImportedPlugins(final String pluginId, final Bundle bundle) {
IProject[] workspaceProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
boolean found = false;
for (IProject iProject : workspaceProjects) {
if (iProject.getName().equals(pluginId) && iProject.isOpen()) {
found = true;
break;
}
}
if (!found) {
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
String importPath = bundle.getLocation().substring("reference:file:".length()+1);
MessageDialog.openError(null, "Error", "Please import (or open) plugin '"+pluginId+"' from EMF Parsley first instance environment!\n"
+ "Path: "+importPath);
}
});
}
}
// private void addModelDependentModule(IProject iProject, String modelPlugin,
// WorkbenchComponent firstComponent, IProgressMonitor monitor) {
// ReferencedComponent refC = ComponentcoreFactory.eINSTANCE.createReferencedComponent();
// URI uri = URI.createURI("module:/resource/" + modelPlugin + "/" + modelPlugin);
// refC.setHandle(uri);
// refC.setArchiveName(modelPlugin + ".jar");
// Path newPath = new Path("/WEB-INF/lib");
// refC.setRuntimePath(newPath);
// firstComponent.getReferencedComponents().add(refC);
// }
private void addMavenDependentModule(IProject iProject, String jarName, String jarPathInMavenRepo, WorkbenchComponent firstComponent, IProgressMonitor monitor) {
ReferencedComponent refC = ComponentcoreFactory.eINSTANCE.createReferencedComponent();
URI uri = URI.createURI("module:/classpath/var/M2_REPO/" + jarPathInMavenRepo + "/" + jarName);
refC.setHandle(uri);
refC.setArchiveName(jarName);
Path newPath = new Path("/WEB-INF/lib");
refC.setRuntimePath(newPath);
firstComponent.getReferencedComponents().add(refC);
}
private void setupWebInfXml(final IProject iProject) {
final WebArtifactEdit artifact = WebArtifactEdit.getWebArtifactEditForWrite(iProject);
final WebApp webAppRoot = artifact.getWebApp();
try {
Utils.registerServlet(iProject, webAppRoot, "JsonTableServlet", "org.eclipse.emf.parsley.web.servlets.JsonTableServlet", "/JsonTableServlet");
Utils.registerServlet(iProject, webAppRoot, "JsonDetailsServlet", "org.eclipse.emf.parsley.web.servlets.JsonDetailsServlet", "/JsonDetailsServlet");
Utils.registerServlet(iProject, webAppRoot, "JsonSaveServlet", "org.eclipse.emf.parsley.web.servlets.JsonSaveServlet", "/JsonSaveServlet");
artifact.saveIfNecessary(null);
} finally {
artifact.dispose();
}
}
}