Commit 6945837c authored by Romain Bioteau's avatar Romain Bioteau
Browse files

Merge pull request #251 from bonitasoft/fix/BS-14159-betterHandlingOfInvalidValidator

BS-14159: warn user when a validator is invalid instead of having a NPE
parents ed463774 be8ab618
...@@ -35,7 +35,8 @@ Require-Bundle: org.eclipse.ui, ...@@ -35,7 +35,8 @@ Require-Bundle: org.eclipse.ui,
org.junit;bundle-version="4.11.0";resolution:=optional, org.junit;bundle-version="4.11.0";resolution:=optional,
assertj-core;bundle-version="1.5.0";resolution:=optional, assertj-core;bundle-version="1.5.0";resolution:=optional,
org.mockito;bundle-version="1.10.19";resolution:=optional, org.mockito;bundle-version="1.10.19";resolution:=optional,
org.bonitasoft.studio.tests-utils;bundle-version="7.0.2";resolution:=optional org.bonitasoft.studio.tests-utils;bundle-version="7.0.2";resolution:=optional,
org.eclipse.emf.ecore
Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Export-Package: org.bonitasoft.studio.validators.descriptor.validator, Export-Package: org.bonitasoft.studio.validators.descriptor.validator,
......
/**
* Copyright (C) 2015 Bonitasoft S.A.
* Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This program is free software: you can redistribute it and/or modify
* 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
* 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/>.
*/
package org.bonitasoft.studio.validators.provider;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import org.assertj.core.api.Assertions;
import org.bonitasoft.engine.bpm.bar.BarResource;
import org.bonitasoft.engine.bpm.bar.BusinessArchiveBuilder;
import org.bonitasoft.studio.common.FragmentTypes;
import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.common.repository.filestore.PackageFileStore;
import org.bonitasoft.studio.common.repository.filestore.SourceFileStore;
import org.bonitasoft.studio.model.configuration.Configuration;
import org.bonitasoft.studio.model.configuration.builders.ConfigurationBuilder;
import org.bonitasoft.studio.model.configuration.builders.FragmentContainerBuilder;
import org.bonitasoft.studio.model.process.AbstractProcess;
import org.bonitasoft.studio.validators.descriptor.validator.ValidatorDescriptor;
import org.bonitasoft.studio.validators.repository.ValidatorDescriptorFileStore;
import org.bonitasoft.studio.validators.repository.ValidatorDescriptorRepositoryStore;
import org.bonitasoft.studio.validators.repository.ValidatorSourceRepositorySotre;
import org.eclipse.emf.ecore.EObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ValidatorBarResourceProviderTest {
private ValidatorBarResourceProvider provider;
@Mock
private ValidatorDescriptorRepositoryStore validatorDescStore;
@Mock
private ValidatorSourceRepositorySotre validatorSourceStore;
@Mock
private RepositoryAccessor repoAccessor;
@Mock
private BusinessArchiveBuilder builder;
@Mock
private ValidatorDescriptorFileStore defFile;
@Mock
private ValidatorDescriptor descriptor;
@Mock
private PackageFileStore packageFileStore;
@Mock
private SourceFileStore sourceFileStore;
@Before
public void setUp() throws Exception {
provider = spy(new ValidatorBarResourceProvider());
doReturn(repoAccessor).when(provider).getRepositoryAccessor();
doReturn(validatorDescStore).when(repoAccessor).getRepositoryStore(ValidatorDescriptorRepositoryStore.class);
doReturn(validatorSourceStore).when(repoAccessor).getRepositoryStore(ValidatorSourceRepositorySotre.class);
}
@Test
public void testInvalidValidatorDefinitionThrowExplicitException() {
final String validatorId = "org.bonitasoft.invalid.";
final String className = "org.bonitasoft.invalid.";
doReturn(defFile).when(validatorDescStore).getChild(validatorId + "." + ValidatorDescriptorRepositoryStore.VALIDATOR_EXT);
doReturn(true).when(defFile).canBeShared();
doReturn(descriptor).when(defFile).getContent();
doReturn(className).when(descriptor).getClassName();
doReturn(packageFileStore).when(validatorSourceStore).getChild(className);
final FragmentContainerBuilder dependencies = FragmentContainerBuilder.aFragmentContainer(FragmentTypes.VALIDATOR).
havingChildren(FragmentContainerBuilder.aFragmentContainer(validatorId));
final Configuration configuration = ConfigurationBuilder.aConfiguration().havingApplicationDependencies(dependencies).build();
try {
provider.addResourcesForConfiguration(builder, (AbstractProcess) null, configuration, Collections.<EObject> emptySet());
} catch (final RuntimeException e) {
Assertions.assertThat(e.getMessage()).isEqualTo("Invalid validator definition " + validatorId + "!");
return;
} catch (final FileNotFoundException e) {
e.printStackTrace();
}
fail("A clean RuntimeException should have been thrown.");
}
@Test
public void testNotExistingValidatorDefinitionThrowExplicitException() {
final String validatorId = "org.bonitasoft.invalid.";
final String className = "org.bonitasoft.invalid.";
doReturn(defFile).when(validatorDescStore).getChild(validatorId + "." + ValidatorDescriptorRepositoryStore.VALIDATOR_EXT);
doReturn(true).when(defFile).canBeShared();
doReturn(descriptor).when(defFile).getContent();
doReturn(className).when(descriptor).getClassName();
doReturn(null).when(validatorSourceStore).getChild(className);
final FragmentContainerBuilder dependencies = FragmentContainerBuilder.aFragmentContainer(FragmentTypes.VALIDATOR).
havingChildren(FragmentContainerBuilder.aFragmentContainer(validatorId));
final Configuration configuration = ConfigurationBuilder.aConfiguration().havingApplicationDependencies(dependencies).build();
try {
provider.addResourcesForConfiguration(builder, (AbstractProcess) null, configuration, Collections.<EObject> emptySet());
} catch (final RuntimeException e) {
e.printStackTrace();
} catch (final FileNotFoundException e) {
Assertions.assertThat(e.getMessage()).isEqualTo(
"Validator class " + className + " not found for validator definition " + validatorId + "!");
return;
}
fail("A clean RuntimeException should have been thrown.");
}
@Test
public void testValidatorDefinitionAdded() throws InvocationTargetException, FileNotFoundException, IOException, InterruptedException {
final String validatorId = "org.bonitasoft.valid.Test";
final String className = "org.bonitasoft.valid.Test";
doReturn(defFile).when(validatorDescStore).getChild(validatorId + "." + ValidatorDescriptorRepositoryStore.VALIDATOR_EXT);
doReturn(true).when(defFile).canBeShared();
doReturn(descriptor).when(defFile).getContent();
doReturn(className).when(descriptor).getClassName();
doReturn(sourceFileStore).when(validatorSourceStore).getChild(className);
doReturn("test".getBytes()).when(provider).createJarContentAsByteArray(sourceFileStore);
final FragmentContainerBuilder dependencies = FragmentContainerBuilder.aFragmentContainer(FragmentTypes.VALIDATOR).
havingChildren(FragmentContainerBuilder.aFragmentContainer(validatorId));
final Configuration configuration = ConfigurationBuilder.aConfiguration().havingApplicationDependencies(dependencies).build();
provider.addResourcesForConfiguration(builder, (AbstractProcess) null, configuration, Collections.<EObject> emptySet());
verify(builder).addExternalResource(any(BarResource.class));
}
}
/** /**
* Copyright (C) 2012-2014 Bonitasoft S.A. * Copyright (C) 2012-2015 Bonitasoft S.A.
* Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -29,7 +29,8 @@ import org.bonitasoft.studio.common.FragmentTypes; ...@@ -29,7 +29,8 @@ import org.bonitasoft.studio.common.FragmentTypes;
import org.bonitasoft.studio.common.ProjectUtil; import org.bonitasoft.studio.common.ProjectUtil;
import org.bonitasoft.studio.common.extension.BARResourcesProvider; import org.bonitasoft.studio.common.extension.BARResourcesProvider;
import org.bonitasoft.studio.common.log.BonitaStudioLog; import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.common.repository.RepositoryManager; import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.common.repository.filestore.AbstractFileStore;
import org.bonitasoft.studio.common.repository.filestore.SourceFileStore; import org.bonitasoft.studio.common.repository.filestore.SourceFileStore;
import org.bonitasoft.studio.model.configuration.Configuration; import org.bonitasoft.studio.model.configuration.Configuration;
import org.bonitasoft.studio.model.configuration.FragmentContainer; import org.bonitasoft.studio.model.configuration.FragmentContainer;
...@@ -47,31 +48,32 @@ public class ValidatorBarResourceProvider implements BARResourcesProvider { ...@@ -47,31 +48,32 @@ public class ValidatorBarResourceProvider implements BARResourcesProvider {
@Override @Override
public void addResourcesForConfiguration(final BusinessArchiveBuilder builder, final AbstractProcess process, final Configuration configuration, public void addResourcesForConfiguration(final BusinessArchiveBuilder builder, final AbstractProcess process, final Configuration configuration,
final Set<EObject> exludedObject) { final Set<EObject> exludedObject) throws FileNotFoundException {
if (configuration == null) { if (configuration == null) {
return; return;
} }
final List<BarResource> resources = findAndCreateBarResourceForValidator(configuration);
for (final BarResource barResource : resources) {
builder.addExternalResource(barResource);
}
}
protected List<BarResource> findAndCreateBarResourceForValidator(final Configuration configuration) throws FileNotFoundException {
final List<BarResource> resources = new ArrayList<BarResource>(); final List<BarResource> resources = new ArrayList<BarResource>();
final ValidatorDescriptorRepositoryStore validatorDescStore = RepositoryManager.getInstance().getRepositoryStore( final ValidatorDescriptorRepositoryStore validatorDescStore = getRepositoryAccessor().getRepositoryStore(ValidatorDescriptorRepositoryStore.class);
ValidatorDescriptorRepositoryStore.class); final ValidatorSourceRepositorySotre validatorSourceStore = getRepositoryAccessor().getRepositoryStore(ValidatorSourceRepositorySotre.class);
final ValidatorSourceRepositorySotre validatorSourceStore = RepositoryManager.getInstance().getRepositoryStore(ValidatorSourceRepositorySotre.class);
final FragmentContainer validatorContainer = getContainer(configuration); final FragmentContainer validatorContainer = getContainer(configuration);
if (validatorContainer != null) { if (validatorContainer != null) {
for (final FragmentContainer validator : validatorContainer.getChildren()) { for (final FragmentContainer validator : validatorContainer.getChildren()) {
final String validatorId = validator.getId(); final String validatorId = validator.getId();
final ValidatorDescriptorFileStore defFile = validatorDescStore.getChild(validatorId + "." final ValidatorDescriptorFileStore defFile = validatorDescStore.getChild(validatorId + "."
+ ValidatorDescriptorRepositoryStore.VALIDATOR_EXT); + ValidatorDescriptorRepositoryStore.VALIDATOR_EXT);
if (defFile == null) { if (defFile == null) {
throw new RuntimeException("Validator descriptor not found for id " + validatorId + "!"); throw new RuntimeException("Validator descriptor not found for id " + validatorId + "!");
} } else if (defFile.canBeShared()) {
if (defFile != null && defFile.canBeShared()) {
final ValidatorDescriptor descriptor = defFile.getContent(); final ValidatorDescriptor descriptor = defFile.getContent();
final SourceFileStore file = (SourceFileStore) validatorSourceStore.getChild(descriptor.getClassName()); final SourceFileStore file = findSourceFileStoreForValidator(validatorSourceStore, validatorId, descriptor);
if (file == null) {
throw new RuntimeException("Validator class " + descriptor.getClassName() + " not found for validator definition " + validatorId + "!");
}
try { try {
final byte[] content = createJarContentAsByteArray(file); final byte[] content = createJarContentAsByteArray(file);
resources.add(new BarResource(ValidatorSourceRepositorySotre.VALIDATOR_PATH_IN_BAR + descriptor.getClassName() + ".jar", content)); resources.add(new BarResource(ValidatorSourceRepositorySotre.VALIDATOR_PATH_IN_BAR + descriptor.getClassName() + ".jar", content));
...@@ -81,13 +83,22 @@ public class ValidatorBarResourceProvider implements BARResourcesProvider { ...@@ -81,13 +83,22 @@ public class ValidatorBarResourceProvider implements BARResourcesProvider {
} }
} }
} }
return resources;
}
for (final BarResource barResource : resources) { protected SourceFileStore findSourceFileStoreForValidator(final ValidatorSourceRepositorySotre validatorSourceStore, final String validatorId,
builder.addExternalResource(barResource); final ValidatorDescriptor descriptor) throws FileNotFoundException {
final AbstractFileStore child = validatorSourceStore.getChild(descriptor.getClassName());
if (child == null) {
throw new FileNotFoundException("Validator class " + descriptor.getClassName() + " not found for validator definition " + validatorId + "!");
}
if (!(child instanceof SourceFileStore)) {
throw new RuntimeException("Invalid validator definition " + validatorId + "!");
} }
return (SourceFileStore) child;
} }
private byte[] createJarContentAsByteArray(final SourceFileStore file) throws IOException, InvocationTargetException, InterruptedException, protected byte[] createJarContentAsByteArray(final SourceFileStore file) throws IOException, InvocationTargetException, InterruptedException,
FileNotFoundException { FileNotFoundException {
final File tmpFile = File.createTempFile(file.getName(), ".jar", ProjectUtil.getBonitaStudioWorkFolder()); final File tmpFile = File.createTempFile(file.getName(), ".jar", ProjectUtil.getBonitaStudioWorkFolder());
tmpFile.deleteOnExit(); tmpFile.deleteOnExit();
...@@ -102,11 +113,17 @@ public class ValidatorBarResourceProvider implements BARResourcesProvider { ...@@ -102,11 +113,17 @@ public class ValidatorBarResourceProvider implements BARResourcesProvider {
private FragmentContainer getContainer(final Configuration configuration) { private FragmentContainer getContainer(final Configuration configuration) {
for (final FragmentContainer container : configuration.getApplicationDependencies()) { for (final FragmentContainer container : configuration.getApplicationDependencies()) {
if (container.getId().equals(FragmentTypes.VALIDATOR)) { if (FragmentTypes.VALIDATOR.equals(container.getId())) {
return container; return container;
} }
} }
return null; return null;
} }
protected RepositoryAccessor getRepositoryAccessor() {
final RepositoryAccessor repositoryAccessor = new RepositoryAccessor();
repositoryAccessor.init();
return repositoryAccessor;
}
} }
Supports Markdown
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