Commit 361ac3c5 authored by Romain Bioteau's avatar Romain Bioteau Committed by GitHub

feat(groovy) allow packages for custom scripts (#1427)

parent 5c49cbad
......@@ -5,26 +5,25 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2.0 of the License, or
* (at your option) any later version.
*
* This program 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.bonitasoft.studio.groovy.ui.providers;
import java.io.File;
import java.util.List;
import java.util.Objects;
import org.bonitasoft.studio.common.ExpressionConstants;
import org.bonitasoft.studio.common.FragmentTypes;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.common.repository.RepositoryManager;
import org.bonitasoft.studio.common.repository.model.IRepositoryFileStore;
import org.bonitasoft.studio.configuration.extension.IConfigurationSynchronizer;
import org.bonitasoft.studio.groovy.repository.GroovyFileStore;
import org.bonitasoft.studio.groovy.repository.GroovyRepositoryStore;
import org.bonitasoft.studio.model.configuration.Configuration;
import org.bonitasoft.studio.model.configuration.ConfigurationFactory;
......@@ -34,92 +33,102 @@ import org.bonitasoft.studio.model.configuration.FragmentContainer;
import org.bonitasoft.studio.model.expression.Expression;
import org.bonitasoft.studio.model.expression.ExpressionPackage;
import org.bonitasoft.studio.model.process.AbstractProcess;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
/**
* @author Romain Bioteau
*
*/
public abstract class AbstractGroovyScriptConfigurationSynchronizer implements IConfigurationSynchronizer {
/* (non-Javadoc)
* @see org.bonitasoft.studio.configuration.extension.IConfigurationSynchronizer#synchronize(org.bonitasoft.studio.model.configuration.Configuration, org.bonitasoft.studio.model.process.AbstractProcess, org.eclipse.emf.common.command.CompoundCommand, org.eclipse.emf.edit.domain.EditingDomain)
*/
@Override
public void synchronize(Configuration configuration, AbstractProcess process, CompoundCommand cc, EditingDomain editingDomain) {
GroovyRepositoryStore store = (GroovyRepositoryStore) RepositoryManager.getInstance().getRepositoryStore(GroovyRepositoryStore.class) ;
addNewPackage(configuration,process, store, cc, editingDomain) ;
removeDeletedPackage(configuration, store, cc, editingDomain) ;
public void synchronize(Configuration configuration, AbstractProcess process, CompoundCommand cc,
EditingDomain editingDomain) {
GroovyRepositoryStore store = (GroovyRepositoryStore) RepositoryManager.getInstance()
.getRepositoryStore(GroovyRepositoryStore.class);
addNewPackage(configuration, process, store, cc, editingDomain);
removeDeletedPackage(configuration, store, cc, editingDomain);
}
private void addNewPackage(Configuration configuration,AbstractProcess process, GroovyRepositoryStore store,CompoundCommand cc, EditingDomain editingDomain) {
List<GroovyFileStore> fileStores = store.getChildren() ;
FragmentContainer groovyContainer = getContainer(configuration) ;
Assert.isNotNull(groovyContainer) ;
private void addNewPackage(Configuration configuration, AbstractProcess process, GroovyRepositoryStore store,
CompoundCommand cc, EditingDomain editingDomain) {
IFolder srcFolder = store.getResource();
FragmentContainer groovyContainer = getContainer(configuration);
Assert.isNotNull(groovyContainer);
for(IRepositoryFileStore fileStore : fileStores){
String name = fileStore.getName() ;
boolean exists = false ;
for(Fragment f : groovyContainer.getFragments()){
if(f.getValue().equals(name)){
exists = true ;
break ;
}
}
if(!exists){
Fragment newFragment = ConfigurationFactory.eINSTANCE.createFragment() ;
newFragment.setType(FragmentTypes.GROOVY_SCRIPT) ;
newFragment.setKey(name) ;
newFragment.setValue(name) ;
List<Expression> expressions = ModelHelper.getAllItemsOfType(process, ExpressionPackage.Literals.EXPRESSION) ;
newFragment.setExported(false) ;
if(name.indexOf(".") != -1){
name = name.substring(0, name.lastIndexOf(".")) ;
}
try {
srcFolder.accept(new IResourceVisitor() {
for(Expression exp : expressions){
if(exp.getType() != null && exp.getType().equals(ExpressionConstants.SCRIPT_TYPE)){
if(exp.getContent() != null && exp.getContent().contains(name)){
newFragment.setExported(true) ;
break ;
@Override
public boolean visit(IResource resource) throws CoreException {
if (Objects.equals("groovy", resource.getFileExtension())) {
boolean exists = false;
for (Fragment f : groovyContainer.getFragments()) {
if (f.getValue().equals(toPath(srcFolder, resource))) {
exists = true;
break;
}
}
if (!exists) {
Fragment newFragment = ConfigurationFactory.eINSTANCE.createFragment();
newFragment.setType(FragmentTypes.GROOVY_SCRIPT);
String path = toPath(srcFolder, resource);
newFragment.setKey(path);
newFragment.setValue(path);
List<Expression> expressions = ModelHelper.getAllItemsOfType(process,
ExpressionPackage.Literals.EXPRESSION);
newFragment.setExported(false);
String qualifiedName = path.replaceAll(File.separator, ".").substring(0,
path.lastIndexOf(".groovy"));
for (Expression exp : expressions) {
if (exp.getType() != null && exp.getType().equals(ExpressionConstants.SCRIPT_TYPE)) {
if (exp.getContent() != null && exp.getContent().contains(qualifiedName)) {
newFragment.setExported(true);
break;
}
}
}
cc.append(AddCommand.create(editingDomain, groovyContainer,
ConfigurationPackage.Literals.FRAGMENT_CONTAINER__FRAGMENTS, newFragment));
}
return false;
}
return true;
}
cc.append(AddCommand.create(editingDomain,groovyContainer,ConfigurationPackage.Literals.FRAGMENT_CONTAINER__FRAGMENTS, newFragment)) ;
}
});
} catch (CoreException e) {
BonitaStudioLog.error(e);
}
}
protected abstract FragmentContainer getContainer(Configuration configuration) ;
protected abstract FragmentContainer getContainer(Configuration configuration);
protected String toPath(IFolder srcFolder, IResource resource) {
return resource.getLocation().makeRelativeTo(srcFolder.getLocation()).toString();
}
private void removeDeletedPackage(Configuration configuration, GroovyRepositoryStore store,CompoundCommand cc, EditingDomain editingDomain) {
List<GroovyFileStore> fileStores = store.getChildren() ;
FragmentContainer container = getContainer(configuration) ;
for(Fragment f : container.getFragments()){
boolean exists = false ;
for(IRepositoryFileStore fileStore : fileStores){
if(f.getValue().equals(fileStore.getName())){
exists = true ;
break ;
}
}
if(!exists){
cc.append(RemoveCommand.create(editingDomain, container, ConfigurationPackage.Literals.FRAGMENT_CONTAINER__FRAGMENTS, f)) ;
private void removeDeletedPackage(Configuration configuration, GroovyRepositoryStore store, CompoundCommand cc,
EditingDomain editingDomain) {
IFolder srcFolder = store.getResource();
FragmentContainer container = getContainer(configuration);
for (Fragment f : container.getFragments()) {
IResource member = srcFolder.findMember(Path.fromOSString(f.getValue()));
if (!member.exists()) {
cc.append(RemoveCommand.create(editingDomain, container,
ConfigurationPackage.Literals.FRAGMENT_CONTAINER__FRAGMENTS, f));
}
}
}
@Override
public String getFragmentContainerId() {
return FragmentTypes.GROOVY_SCRIPT ;
return FragmentTypes.GROOVY_SCRIPT;
}
}
......@@ -22,12 +22,14 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.wizards.NewElementWizard;
import org.eclipse.jface.viewers.IStructuredSelection;
public class NewGroovyClassWizard extends NewElementWizard {
......@@ -50,7 +52,14 @@ public class NewGroovyClassWizard extends NewElementWizard {
IFolder srcFolder = RepositoryManager.getInstance().getRepositoryStore(GroovyRepositoryStore.class).getResource();
fPage.setPackageFragmentRoot(project.getPackageFragmentRoot(
srcFolder), false);
fPage.setPackageFragment(srcFolder.getAdapter(IPackageFragment.class), false);
IStructuredSelection selection = getSelection();
Object firstElement = selection.getFirstElement();
if (firstElement instanceof IAdaptable && ((IAdaptable) firstElement).getAdapter(IPackageFragment.class) != null) {
fPage.setPackageFragment(((IAdaptable) firstElement).getAdapter(IPackageFragment.class), true);
} else {
fPage.setPackageFragment(srcFolder.getAdapter(IPackageFragment.class), true);
}
}
@Override
......
......@@ -20,8 +20,10 @@ import static com.google.common.io.Files.toByteArray;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import javax.inject.Inject;
......@@ -32,9 +34,9 @@ import org.bonitasoft.studio.common.FragmentTypes;
import org.bonitasoft.studio.common.ProjectUtil;
import org.bonitasoft.studio.common.emf.tools.ModelHelper;
import org.bonitasoft.studio.common.extension.BARResourcesProvider;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.common.repository.Repository;
import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.common.repository.RepositoryManager;
import org.bonitasoft.studio.common.repository.jdt.CreateJarOperation;
import org.bonitasoft.studio.groovy.GroovyPlugin;
import org.bonitasoft.studio.groovy.Messages;
......@@ -46,43 +48,29 @@ import org.bonitasoft.studio.model.configuration.ConfigurationPackage;
import org.bonitasoft.studio.model.configuration.Fragment;
import org.bonitasoft.studio.model.configuration.FragmentContainer;
import org.bonitasoft.studio.model.process.AbstractProcess;
import org.codehaus.groovy.eclipse.core.compiler.GroovySnippetCompiler;
import org.codehaus.groovy.eclipse.core.model.GroovyProjectFacade;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.osgi.util.NLS;
/**
* @author Romain Bioteau
*/
public class GroovyScriptBarResourceProvider implements BARResourcesProvider {
private static final String EXTERNAL_LIB_BAR_LOCATION = BARResourcesProvider.FORMS_FOLDER_IN_BAR + "/lib/";
@Inject
private RepositoryAccessor repositoryAccessor;
/*
* (non-Javadoc)
* @see
* org.bonitasoft.studio.common.extension.BARResourcesProvider#getResourcesForConfiguration(org.bonitasoft.studio.model.
* process.AbstractProcess,
* org.bonitasoft.studio.model.configuration.Configuration, org.bonitasoft.engine.bpm.model.DesignProcessDefinition,
* java.util.Map)
*/
@Override
public void addResourcesForConfiguration(final BusinessArchiveBuilder builder, final AbstractProcess process,
final Configuration configuration) throws Exception {
if (configuration != null) {
addGroovyScriptDependenciesToClasspath(builder, configuration, configuration.getProcessDependencies());
addGroovyScriptDependenciesToExternalLib(builder, configuration, configuration.getApplicationDependencies());
}
addProvidedScriptsToClasspath(builder);
}
......@@ -112,28 +100,31 @@ public class GroovyScriptBarResourceProvider implements BARResourcesProvider {
protected void addGroovyCompilationUnitToClasspath(final BusinessArchiveBuilder builder,
final Set<ICompilationUnit> compilationUnits,
final String exportedProvidedJarName) throws InvocationTargetException, InterruptedException, IOException {
final IJavaProject javaProject = RepositoryManager.getInstance().getCurrentRepository().getJavaProject();
final GroovySnippetCompiler compiler = new GroovySnippetCompiler(new GroovyProjectFacade(javaProject));
for (ICompilationUnit compilationUnit : compilationUnits) {
CompilationResult compileForErrors;
List<IMarker> errorMarkers = new ArrayList<>();
try {
compileForErrors = compiler.compileForErrors(compilationUnit.getSource(), null);
CategorizedProblem[] errors = compileForErrors.getErrors();
if (errors != null && errors.length > 0) {
MultiStatus errorStatus = new MultiStatus(GroovyPlugin.PLUGIN_ID, 0, "", null);
for (CategorizedProblem e : errors) {
errorStatus.add(new Status(IStatus.ERROR, GroovyPlugin.PLUGIN_ID,
String.format("%s (line %s, col %s): %s", compilationUnit.getElementName(),
e.getSourceLineNumber(),
e.getSourceStart(), e.getMessage())));
throw new JarExportFailedException(
Messages.errorBuildingJarForGroovyScriptsForProcess + " ",
errorStatus);
IMarker[] markers = compilationUnit.getResource().findMarkers(null, true, IResource.DEPTH_ZERO);
if (markers != null) {
for (IMarker marker : markers) {
if (Objects.equals(marker.getAttribute(IMarker.SEVERITY), IMarker.SEVERITY_ERROR)) {
errorMarkers.add(marker);
}
}
if (!errorMarkers.isEmpty()) {
MultiStatus errorStatus = new MultiStatus(GroovyPlugin.PLUGIN_ID, 0, "", null);
for (IMarker e : errorMarkers) {
errorStatus.add(new Status(IStatus.ERROR, GroovyPlugin.PLUGIN_ID,
String.format("%s (line %s, col %s): %s", compilationUnit.getElementName(),
e.getAttribute(IMarker.LINE_NUMBER),
e.getAttribute(IMarker.CHAR_START), e.getAttribute(IMarker.MESSAGE))));
throw new JarExportFailedException(
Messages.errorBuildingJarForGroovyScriptsForProcess + " ",
errorStatus);
}
}
}
} catch (JavaModelException e) {
throw new InvocationTargetException(e);
} catch (CoreException e1) {
BonitaStudioLog.error(e1);
}
}
......@@ -161,30 +152,6 @@ public class GroovyScriptBarResourceProvider implements BARResourcesProvider {
}
}
protected void addGroovyScriptDependenciesToExternalLib(
final BusinessArchiveBuilder builder,
final Configuration configuration,
final List<FragmentContainer> containers) throws InvocationTargetException, InterruptedException, IOException {
final Set<ICompilationUnit> compilationUnits = collectCompilationUnits(configuration, containers);
final String exportedJarName = GroovyRepositoryStore.EXPORTED_JAR_NAME;
if (!compilationUnits.isEmpty()) {
final File targetJar = new File(ProjectUtil.getBonitaStudioWorkFolder(), exportedJarName);
final CreateJarOperation createJarOperation = new CreateJarOperation(targetJar,
toArray(compilationUnits, ICompilationUnit.class));
createJarOperation.run(Repository.NULL_PROGRESS_MONITOR);
final IStatus status = createJarOperation.getStatus();
if (status.getSeverity() == IStatus.ERROR || status.getSeverity() == IStatus.CANCEL) {
targetJar.delete();
throw new JarExportFailedException(
Messages.errorBuildingJarForGroovyScriptsFor6xApplication + " ",
status);
}
builder.addExternalResource(
new BarResource(EXTERNAL_LIB_BAR_LOCATION + targetJar.getName(), toByteArray(targetJar)));
targetJar.delete();
}
}
private Set<ICompilationUnit> collectCompilationUnits(final Configuration configuration,
final List<FragmentContainer> containers) {
final Set<ICompilationUnit> result = new HashSet<>();
......@@ -194,9 +161,10 @@ public class GroovyScriptBarResourceProvider implements BARResourcesProvider {
for (final EObject fragment : ModelHelper.getAllItemsOfType(fc, ConfigurationPackage.Literals.FRAGMENT)) {
if (((Fragment) fragment).getType().equals(FragmentTypes.GROOVY_SCRIPT)) {
if (((Fragment) fragment).isExported()) {
final GroovyFileStore file = store.getChild(((Fragment) fragment).getValue());
if (file != null) {
result.add(file.getCompilationUnit());
final IResource file = store.getResource()
.findMember(Path.fromOSString(((Fragment) fragment).getValue()));
if (file instanceof IFile && file.exists()) {
result.add(JavaCore.createCompilationUnitFrom((IFile) file));
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment