private void deleteConnectorInstancesIfNecessary(
     final SProcessInstance processInstance, final SProcessDefinition processDefinition)
     throws SConnectorInstanceReadException, SConnectorInstanceDeletionException {
   if (processDefinition != null && processDefinition.hasConnectors()) {
     connectorInstanceService.deleteConnectors(
         processInstance.getId(), SConnectorInstance.PROCESS_TYPE);
   }
 }
 private void deleteDataInstancesIfNecessary(
     final SProcessInstance processInstance, final SProcessDefinition processDefinition)
     throws SDataInstanceException {
   boolean dataPresent = true;
   if (processDefinition != null) {
     dataPresent = processDefinition.getProcessContainer().getDataDefinitions().size() > 0;
   }
   dataInstanceService.deleteLocalDataInstances(
       processInstance.getId(), DataInstanceContainer.PROCESS_INSTANCE.toString(), dataPresent);
 }
 private boolean hasConnectors(
     final SFlowNodeInstance flowNodeInstance, final SProcessDefinition processDefinition) {
   boolean hasConnectors = false;
   if (processDefinition != null) {
     final SActivityDefinition activityDefinition =
         (SActivityDefinition)
             processDefinition
                 .getProcessContainer()
                 .getFlowNode(flowNodeInstance.getFlowNodeDefinitionId());
     if (activityDefinition != null) {
       hasConnectors = activityDefinition.getConnectors().size() > 0;
     }
   }
   return hasConnectors;
 }
 private void deleteDataInstancesIfNecessary(
     final SFlowNodeInstance flowNodeInstance, final SProcessDefinition processDefinition)
     throws SDataInstanceException {
   boolean dataPresent = true;
   if (processDefinition != null) {
     final SActivityDefinition activityDefinition =
         (SActivityDefinition)
             processDefinition
                 .getProcessContainer()
                 .getFlowNode(flowNodeInstance.getFlowNodeDefinitionId());
     if (activityDefinition != null) {
       dataPresent = activityDefinition.getSDataDefinitions().size() > 0;
     }
   }
   dataInstanceService.deleteLocalDataInstances(
       flowNodeInstance.getId(), DataInstanceContainer.ACTIVITY_INSTANCE.toString(), dataPresent);
 }
  @Test
  @Cover(
      classes = {ConnectorServiceImpl.class},
      concept = Cover.BPMNConcept.CONNECTOR,
      keywords = {"connector dependencies"},
      jira = "ENGINE-1411")
  public void setConnectorImplementationDoesNotCareWhereTheJarsAre() throws Exception {
    final long tenantId = 98774L;
    final long processDefId = 17L;
    final File processDefFolder =
        new File(
            BonitaHomeServer.getInstance().getProcessesFolder(tenantId)
                + File.separator
                + processDefId);
    final File connFolder = new File(processDefFolder, "connector");
    final File classPathFolder = new File(processDefFolder, "classpath");
    connFolder.mkdirs();
    classPathFolder.mkdirs();
    try {
      final SProcessDefinition sProcessDef = mock(SProcessDefinition.class);
      when(sProcessDef.getId()).thenReturn(processDefId);
      final String connectorDefId = "org.bonitasoft.connector.BeerConnector";
      final String connectorDefVersion = "1.0.0";
      final String connectorImplId = "org.bonitasoft.connector.HoogardenConnector";
      final String connectorImplVersion = "1.0";
      final String implementationClassName =
          "org.bonitasoft.engine.connectors.HoogardenBeerConnector";
      final String dep1Jar = "some1.jar";
      final String hoogardenConnectorJar = "HoogardenConnector.jar";
      final SConnectorImplementationDescriptor ConnectorImplDescriptor =
          new SConnectorImplementationDescriptor(
              implementationClassName,
              connectorImplId,
              connectorImplVersion,
              connectorDefId,
              connectorDefVersion,
              new JarDependencies(Arrays.asList(dep1Jar, hoogardenConnectorJar)));
      when(parser.getObjectFromXML(any(InputStream.class))).thenReturn(ConnectorImplDescriptor);
      when(parser.getObjectFromXML(any(File.class))).thenReturn(ConnectorImplDescriptor);
      Map<String, byte[]> zipFileMap = new HashMap<String, byte[]>(3);
      zipFileMap.put("HoogardenBeerConnector.impl", "tototo".getBytes());
      zipFileMap.put(dep1Jar, new byte[] {12, 94, 14, 12});
      zipFileMap.put(hoogardenConnectorJar, new byte[] {12, 94, 14, 9, 54, 65, 98, 54, 21, 32, 65});
      final byte[] zip1 = IOUtil.zip(zipFileMap);
      connectorService.setConnectorImplementation(
          sProcessDef, tenantId, connectorDefId, connectorDefVersion, zip1);
      File[] jarFiles = classPathFolder.listFiles(jarFilenameFilter);

      assertEquals(2, jarFiles.length);
      final List<File> jars = Arrays.asList(jarFiles);
      assertThat(
          "Not all jar files have been found", jars, namesContain(hoogardenConnectorJar, dep1Jar));

      zipFileMap = new HashMap<String, byte[]>(1);
      zipFileMap.put("GrimbergenBeerConnector.impl", "GrimbergenBeerConnector.impl".getBytes());
      final String newJar = "GrimbergenBeerConnector.jar";
      zipFileMap.put("dummyFolder/" + newJar, new byte[] {12, 3, 14});
      final byte[] zip2 = IOUtil.zip(zipFileMap);
      connectorService.setConnectorImplementation(
          sProcessDef, tenantId, connectorDefId, connectorDefVersion, zip2);

      jarFiles = classPathFolder.listFiles(jarFilenameFilter);

      assertEquals(1, jarFiles.length);
      assertEquals(newJar, jarFiles[0].getName());
    } finally {
      final boolean folderCleaned = IOUtil.deleteDir(processDefFolder);
      if (!folderCleaned) {
        System.err.println("Folder " + processDefFolder.getName() + " could not be deleted");
      }
    }
  }
  @Test
  @Cover(
      classes = {ConnectorServiceImpl.class},
      concept = Cover.BPMNConcept.CONNECTOR,
      keywords = {"connector dependencies"},
      jira = "ENGINE-1466")
  public void setConnectorImplementationOverwritesExistingJars() throws Exception {
    final long tenantId = 98774L;
    final long processDefId = 17L;
    final File processDefFolder =
        new File(
            BonitaHomeServer.getInstance().getProcessesFolder(tenantId)
                + File.separator
                + processDefId);
    final File connFolder = new File(processDefFolder, "connector");
    final File classPathFolder = new File(processDefFolder, "classpath");
    connFolder.mkdirs();
    classPathFolder.mkdirs();
    try {
      final SProcessDefinition sProcessDef = mock(SProcessDefinition.class);
      when(sProcessDef.getId()).thenReturn(processDefId);
      final String connectorDefId = "org.bonitasoft.connector.BeerConnector";
      final String connectorDefVersion = "1.0.0";
      final String connectorImplId = "org.bonitasoft.connector.HoogardenConnector";
      final String connectorImplVersion = "1.0";
      final String implementationClassName =
          "org.bonitasoft.engine.connectors.HoogardenBeerConnector";
      final String sameConnectorJarName = "HoogardenConnector.jar";
      final SConnectorImplementationDescriptor ConnectorImplDescriptor =
          new SConnectorImplementationDescriptor(
              implementationClassName,
              connectorImplId,
              connectorImplVersion,
              connectorDefId,
              connectorDefVersion,
              new JarDependencies(Arrays.asList(sameConnectorJarName)));
      when(parser.getObjectFromXML(any(InputStream.class))).thenReturn(ConnectorImplDescriptor);
      when(parser.getObjectFromXML(any(File.class))).thenReturn(ConnectorImplDescriptor);
      Map<String, byte[]> zipFileMap = new HashMap<String, byte[]>(3);
      final byte[] originalConnectorJarContent =
          new byte[] {12, 94, 14, 9, 54, 65, 98, 54, 21, 32, 65};
      zipFileMap.put("anyName.impl", "tototo".getBytes());
      zipFileMap.put(sameConnectorJarName, originalConnectorJarContent);
      final byte[] zip1 = IOUtil.zip(zipFileMap);
      connectorService.setConnectorImplementation(
          sProcessDef, tenantId, connectorDefId, connectorDefVersion, zip1);

      File[] jarFiles = classPathFolder.listFiles(jarFilenameFilter);
      assertEquals(1, jarFiles.length);
      assertTrue(
          "Deployed connector jar is not the expected size + content",
          Arrays.equals(
              org.bonitasoft.engine.commons.io.IOUtil.getAllContentFrom(jarFiles[0]),
              originalConnectorJarContent));

      // now let's prepare the new connector implementation to replace:
      zipFileMap = new HashMap<String, byte[]>(1);
      zipFileMap.put("GrimbergenBeerConnector.impl", "GrimbergenBeerConnector.impl".getBytes());
      final byte[] newConnectorJarContent = new byte[] {12, 3, 14};
      zipFileMap.put(sameConnectorJarName, newConnectorJarContent);
      final byte[] zip2 = IOUtil.zip(zipFileMap);
      connectorService.setConnectorImplementation(
          sProcessDef, tenantId, connectorDefId, connectorDefVersion, zip2);

      jarFiles = classPathFolder.listFiles(jarFilenameFilter);
      assertEquals(1, jarFiles.length);
      assertTrue(
          "Replaced connector jar is not the expected size + content",
          Arrays.equals(
              org.bonitasoft.engine.commons.io.IOUtil.getAllContentFrom(jarFiles[0]),
              newConnectorJarContent));
    } finally {
      final boolean folderCleaned = IOUtil.deleteDir(processDefFolder);
      if (!folderCleaned) {
        System.err.println("Folder " + processDefFolder.getName() + " could not be deleted");
      }
    }
  }