@SuppressWarnings("unchecked")
  @Override
  public List<Record> authorizeByConnector(
      List<Record> records,
      Collection<UserCredentials> userCredentialsList,
      ConnectorManager connectorManager) {
    List<Record> authorizedRecords = new ArrayList<Record>();

    Document document = DocumentHelper.createDocument();
    Element root = document.addElement(ServletUtil.XMLTAG_AUTHZ_QUERY);
    Element connectorQueryElement = root.addElement(ServletUtil.XMLTAG_CONNECTOR_QUERY);

    Map<ConnectorInstance, UserCredentials> credentialsMap =
        new HashMap<ConnectorInstance, UserCredentials>();
    Set<ConnectorInstance> connectorsWithoutCredentials = new HashSet<ConnectorInstance>();
    Map<String, Record> recordsByURLMap = new HashMap<String, Record>();
    boolean recordToValidate = false;
    for (Record record : records) {
      // Use to accelerate the matching between response urls and actual entities
      recordsByURLMap.put(record.getUrl(), record);
      ConnectorInstance connectorInstance = record.getConnectorInstance();
      UserCredentials connectorCredentials = credentialsMap.get(connectorInstance);
      if (connectorCredentials == null
          && !connectorsWithoutCredentials.contains(connectorInstance)) {
        RecordCollection collection = connectorInstance.getRecordCollection();
        for (CredentialGroup credentialGroup : collection.getCredentialGroups()) {
          if (credentialGroup.getConnectorInstances().contains(connectorInstance)) {
            for (UserCredentials userCredentials : userCredentialsList) {
              if (userCredentials.getCredentialGroup().equals(credentialGroup)) {
                connectorCredentials = userCredentials;
                credentialsMap.put(connectorInstance, userCredentials);
                break;
              }
            }
            break;
          }
        }
      }
      if (connectorCredentials == null) {
        connectorsWithoutCredentials.add(connectorInstance);
        LOGGER.warning("Missing credentials for connector " + connectorInstance.getName());
      } else {
        String username = connectorCredentials.getUsername();
        if (StringUtils.isNotBlank(username)) {
          String password = EncryptionUtils.decrypt(connectorCredentials.getEncryptedPassword());
          String domain = connectorCredentials.getDomain();
          Element identityElement = connectorQueryElement.addElement(ServletUtil.XMLTAG_IDENTITY);
          identityElement.setText(username);
          if (StringUtils.isNotBlank(domain)) {
            identityElement.addAttribute(ServletUtil.XMLTAG_DOMAIN_ATTRIBUTE, domain);
          }
          identityElement.addAttribute(ServletUtil.XMLTAG_PASSWORD_ATTRIBUTE, password);

          Element resourceElement = identityElement.addElement(ServletUtil.XMLTAG_RESOURCE);
          resourceElement.setText(record.getUrl());
          resourceElement.addAttribute(
              ServletUtil.XMLTAG_CONNECTOR_NAME_ATTRIBUTE, connectorInstance.getName());
          recordToValidate = true;
        }
      }
    }

    if (recordToValidate) {
      Element response =
          ConnectorManagerRequestUtils.sendPost(connectorManager, "/authorization", document);
      Element authzResponseElement = response.element(ServletUtil.XMLTAG_AUTHZ_RESPONSE);
      List<Element> answerElements = authzResponseElement.elements(ServletUtil.XMLTAG_ANSWER);
      for (Element answerElement : answerElements) {
        Element decisionElement = answerElement.element(ServletUtil.XMLTAG_DECISION);
        boolean permit = decisionElement.getTextTrim().equals("Permit");
        if (permit) {
          Element resourceElement = answerElement.element(ServletUtil.XMLTAG_RESOURCE);
          String recordUrl = resourceElement.getTextTrim();
          Record record = recordsByURLMap.get(recordUrl);
          authorizedRecords.add(record);
        }
      }
    }
    return authorizedRecords;
  }
  @Override
  public void synchronizeWithDatabase(ConnectorManager connectorManager) {
    ConnectorTypeServices connectorTypeServices = ConstellioSpringUtils.getConnectorTypeServices();

    // Add missing connector types
    List<String> connectorTypeNames = getConnectorTypes(connectorManager);
    for (String connectorTypeName : connectorTypeNames) {
      ConnectorType connectorType = connectorTypeServices.get(connectorTypeName);
      if (connectorType == null) {
        connectorType = new ConnectorType();
        connectorType.setName(connectorTypeName);

        File connectorsDir = ConstellioSpringUtils.getGoogleConnectorsDir();
        File connectorTypeDir = new File(connectorsDir, connectorType.getName());

        File iconFile = new File(connectorTypeDir, "icon.gif");
        if (iconFile.exists()) {
          try {
            byte[] iconBytes = FileUtils.readFileToByteArray(iconFile);
            connectorType.setIconFileContent(iconBytes);
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        }

        File connectorTypeMetaXmlFile = new File(connectorTypeDir, "connectorTypeMeta.xml");
        if (connectorTypeMetaXmlFile.exists()) {
          String path = connectorTypeMetaXmlFile.toURI().toString();
          BeanFactory connectorTypeMeta = new FileSystemXmlApplicationContext(path);
          if (connectorTypeMeta.containsBean("searchResultPanelClassName")) {
            String searchResultPanelClassName =
                (String) connectorTypeMeta.getBean("searchResultPanelClassName");
            connectorType.setSearchResultPanelClassName(searchResultPanelClassName);
          }
          if (connectorTypeMeta.containsBean("initInstanceHandlerClassName")) {
            String initInstancePluginClassName =
                (String) connectorTypeMeta.getBean("initInstanceHandlerClassName");
            connectorType.setInitInstanceHandlerClassName(initInstancePluginClassName);
          }
        }

        connectorType.setConnectorManager(connectorManager);
        connectorTypeServices.makePersistent(connectorType);
      }
    }

    // Remove deleted connector types
    List<ConnectorType> dbConnectorType = connectorTypeServices.list();
    for (ConnectorType connectorType : dbConnectorType) {
      if (!connectorTypeNames.contains(connectorType.getName())) {
        connectorTypeServices.makeTransient(connectorType);
      }
    }

    ConnectorInstanceServices connectorInstanceServices =
        ConstellioSpringUtils.getConnectorInstanceServices();
    BackupServices backupServices = ConstellioSpringUtils.getBackupServices();
    List<ConnectorInstance> connectorInstances = connectorInstanceServices.list();
    for (ConnectorInstance connectorInstance : connectorInstances) {
      String connectorName = connectorInstance.getName();
      String connectorTypeName = connectorInstance.getConnectorType().getName();
      boolean existingConnector = isExistingConnector(connectorManager, connectorName);
      boolean hasConfigBackup = backupServices.hasConfigBackup(connectorName, connectorTypeName);
      if (!existingConnector && hasConfigBackup) {
        backupServices.restoreConfigBackup(connectorName, connectorTypeName);
      } else if (existingConnector && !hasConfigBackup) {
        backupServices.backupConfig(connectorName, connectorTypeName);
      }
    }
  }