mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-23 16:05:09 +00:00
Compare commits
No commits in common. "a2840982e53f8c2fae897dc02250e8f806b103af" and "6dd17a5561e115d8e2be377e4daeb876f3424667" have entirely different histories.
a2840982e5
...
6dd17a5561
52
.github/workflows/build.yml
vendored
52
.github/workflows/build.yml
vendored
@ -47,56 +47,18 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DISABLE_ADDITIONAL_FEATURES: false
|
DISABLE_ADDITIONAL_FEATURES: false
|
||||||
|
|
||||||
- name: Check Test Reports Exist
|
|
||||||
id: check-reports
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
missing_reports=()
|
|
||||||
|
|
||||||
# Check for required test report directories
|
|
||||||
if [ ! -d "stirling-pdf/build/reports/tests/" ]; then
|
|
||||||
missing_reports+=("stirling-pdf/build/reports/tests/")
|
|
||||||
fi
|
|
||||||
if [ ! -d "stirling-pdf/build/test-results/" ]; then
|
|
||||||
missing_reports+=("stirling-pdf/build/test-results/")
|
|
||||||
fi
|
|
||||||
if [ ! -d "common/build/reports/tests/" ]; then
|
|
||||||
missing_reports+=("common/build/reports/tests/")
|
|
||||||
fi
|
|
||||||
if [ ! -d "common/build/test-results/" ]; then
|
|
||||||
missing_reports+=("common/build/test-results/")
|
|
||||||
fi
|
|
||||||
if [ ! -d "proprietary/build/reports/tests/" ]; then
|
|
||||||
missing_reports+=("proprietary/build/reports/tests/")
|
|
||||||
fi
|
|
||||||
if [ ! -d "proprietary/build/test-results/" ]; then
|
|
||||||
missing_reports+=("proprietary/build/test-results/")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Fail if any required reports are missing
|
|
||||||
if [ ${#missing_reports[@]} -gt 0 ]; then
|
|
||||||
echo "ERROR: The following required test report directories are missing:"
|
|
||||||
printf '%s\n' "${missing_reports[@]}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "All required test report directories are present"
|
|
||||||
|
|
||||||
- name: Upload Test Reports
|
- name: Upload Test Reports
|
||||||
if: steps.check-reports.outcome == 'success'
|
if: always()
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: test-reports-jdk-${{ matrix.jdk-version }}
|
name: test-reports-jdk-${{ matrix.jdk-version }}
|
||||||
path: |
|
path: |
|
||||||
stirling-pdf/build/reports/tests/
|
build/reports/tests/
|
||||||
stirling-pdf/build/test-results/
|
build/test-results/
|
||||||
stirling-pdf/build/reports/problems/
|
build/reports/problems/
|
||||||
common/build/reports/tests/
|
/common/build/reports/tests/
|
||||||
common/build/test-results/
|
/common/build/test-results/
|
||||||
common/build/reports/problems/
|
/common/build/reports/problems/
|
||||||
proprietary/build/reports/tests/
|
|
||||||
proprietary/build/test-results/
|
|
||||||
proprietary/build/reports/problems/
|
|
||||||
retention-days: 3
|
retention-days: 3
|
||||||
|
|
||||||
check-licence:
|
check-licence:
|
||||||
|
@ -473,7 +473,6 @@ spotless {
|
|||||||
target sourceSets.main.allJava
|
target sourceSets.main.allJava
|
||||||
target project(':common').sourceSets.main.allJava
|
target project(':common').sourceSets.main.allJava
|
||||||
target project(':proprietary').sourceSets.main.allJava
|
target project(':proprietary').sourceSets.main.allJava
|
||||||
target project(':stirling-pdf').sourceSets.main.allJava
|
|
||||||
|
|
||||||
googleJavaFormat("1.27.0").aosp().reorderImports(false)
|
googleJavaFormat("1.27.0").aosp().reorderImports(false)
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package stirling.software.common.configuration;
|
package stirling.software.common.configuration;
|
||||||
|
|
||||||
|
import io.github.pixee.security.SystemCommand;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@ -8,22 +10,29 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.context.annotation.Profile;
|
import org.springframework.context.annotation.Profile;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.thymeleaf.spring6.SpringTemplateEngine;
|
import org.thymeleaf.spring6.SpringTemplateEngine;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
@ -25,7 +25,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -257,7 +256,7 @@ public class UserController {
|
|||||||
} else {
|
} else {
|
||||||
// Check if the selected team is Internal - prevent assigning to it
|
// Check if the selected team is Internal - prevent assigning to it
|
||||||
Team selectedTeam = teamRepository.findById(effectiveTeamId).orElse(null);
|
Team selectedTeam = teamRepository.findById(effectiveTeamId).orElse(null);
|
||||||
if (selectedTeam != null && TeamService.INTERNAL_TEAM_NAME.equals(selectedTeam.getName())) {
|
if (selectedTeam != null && selectedTeam.getName().equals(TeamService.INTERNAL_TEAM_NAME)) {
|
||||||
return new RedirectView("/adminSettings?messageType=internalTeamNotAccessible", true);
|
return new RedirectView("/adminSettings?messageType=internalTeamNotAccessible", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,7 +276,6 @@ public class UserController {
|
|||||||
|
|
||||||
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
@PostMapping("/admin/changeRole")
|
@PostMapping("/admin/changeRole")
|
||||||
@Transactional
|
|
||||||
public RedirectView changeRole(
|
public RedirectView changeRole(
|
||||||
@RequestParam(name = "username") String username,
|
@RequestParam(name = "username") String username,
|
||||||
@RequestParam(name = "role") String role,
|
@RequestParam(name = "role") String role,
|
||||||
@ -315,12 +313,12 @@ public class UserController {
|
|||||||
Team team = teamRepository.findById(teamId).orElse(null);
|
Team team = teamRepository.findById(teamId).orElse(null);
|
||||||
if (team != null) {
|
if (team != null) {
|
||||||
// Prevent assigning to Internal team
|
// Prevent assigning to Internal team
|
||||||
if (TeamService.INTERNAL_TEAM_NAME.equals(team.getName())) {
|
if (team.getName().equals(TeamService.INTERNAL_TEAM_NAME)) {
|
||||||
return new RedirectView("/adminSettings?messageType=internalTeamNotAccessible", true);
|
return new RedirectView("/adminSettings?messageType=internalTeamNotAccessible", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent moving users from Internal team
|
// Prevent moving users from Internal team
|
||||||
if (user.getTeam() != null && TeamService.INTERNAL_TEAM_NAME.equals(user.getTeam().getName())) {
|
if (user.getTeam() != null && user.getTeam().getName().equals(TeamService.INTERNAL_TEAM_NAME)) {
|
||||||
return new RedirectView("/adminSettings?messageType=cannotMoveInternalUsers", true);
|
return new RedirectView("/adminSettings?messageType=cannotMoveInternalUsers", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
package stirling.software.proprietary.security.service;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.mockito.InjectMocks;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
|
||||||
import stirling.software.proprietary.model.Team;
|
|
||||||
import stirling.software.proprietary.security.repository.TeamRepository;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
|
||||||
class TeamServiceTest {
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private TeamRepository teamRepository;
|
|
||||||
|
|
||||||
@InjectMocks
|
|
||||||
private TeamService teamService;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getDefaultTeam() {
|
|
||||||
var team = new Team();
|
|
||||||
team.setName("Marleyans");
|
|
||||||
|
|
||||||
when(teamRepository.findByName(TeamService.DEFAULT_TEAM_NAME))
|
|
||||||
.thenReturn(Optional.of(team));
|
|
||||||
|
|
||||||
Team result = teamService.getOrCreateDefaultTeam();
|
|
||||||
|
|
||||||
assertEquals(team, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void createDefaultTeam_whenRepositoryIsEmpty() {
|
|
||||||
String teamName = "Default";
|
|
||||||
var defaultTeam = new Team();
|
|
||||||
defaultTeam.setId(1L);
|
|
||||||
defaultTeam.setName(teamName);
|
|
||||||
|
|
||||||
when(teamRepository.findByName(teamName))
|
|
||||||
.thenReturn(Optional.empty());
|
|
||||||
when(teamRepository.save(any(Team.class))).thenReturn(defaultTeam);
|
|
||||||
|
|
||||||
Team result = teamService.getOrCreateDefaultTeam();
|
|
||||||
|
|
||||||
assertEquals(TeamService.DEFAULT_TEAM_NAME, result.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void getInternalTeam() {
|
|
||||||
var team = new Team();
|
|
||||||
team.setName("Eldians");
|
|
||||||
|
|
||||||
when(teamRepository.findByName(TeamService.INTERNAL_TEAM_NAME))
|
|
||||||
.thenReturn(Optional.of(team));
|
|
||||||
|
|
||||||
Team result = teamService.getOrCreateInternalTeam();
|
|
||||||
|
|
||||||
assertEquals(team, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void createInternalTeam_whenRepositoryIsEmpty() {
|
|
||||||
String teamName = "Internal";
|
|
||||||
Team internalTeam = new Team();
|
|
||||||
internalTeam.setId(2L);
|
|
||||||
internalTeam.setName(teamName);
|
|
||||||
|
|
||||||
when(teamRepository.findByName(teamName))
|
|
||||||
.thenReturn(Optional.empty());
|
|
||||||
when(teamRepository.save(any(Team.class))).thenReturn(internalTeam);
|
|
||||||
when(teamRepository.findByName(TeamService.INTERNAL_TEAM_NAME))
|
|
||||||
.thenReturn(Optional.empty());
|
|
||||||
|
|
||||||
Team result = teamService.getOrCreateInternalTeam();
|
|
||||||
|
|
||||||
assertEquals(internalTeam, result);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,317 +0,0 @@
|
|||||||
package stirling.software.proprietary.security.service;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Optional;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.mockito.InjectMocks;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
|
||||||
import org.springframework.context.MessageSource;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
||||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
|
||||||
import stirling.software.common.model.enumeration.Role;
|
|
||||||
import stirling.software.common.model.exception.UnsupportedProviderException;
|
|
||||||
import stirling.software.proprietary.model.Team;
|
|
||||||
import stirling.software.proprietary.security.database.repository.AuthorityRepository;
|
|
||||||
import stirling.software.proprietary.security.database.repository.UserRepository;
|
|
||||||
import stirling.software.proprietary.security.model.AuthenticationType;
|
|
||||||
import stirling.software.proprietary.security.model.User;
|
|
||||||
import stirling.software.proprietary.security.repository.TeamRepository;
|
|
||||||
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
|
||||||
class UserServiceTest {
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private UserRepository userRepository;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private TeamRepository teamRepository;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private AuthorityRepository authorityRepository;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private PasswordEncoder passwordEncoder;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private MessageSource messageSource;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private SessionPersistentRegistry sessionPersistentRegistry;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private DatabaseServiceInterface databaseService;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private ApplicationProperties.Security.OAUTH2 oauth2Properties;
|
|
||||||
|
|
||||||
@InjectMocks
|
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
private Team mockTeam;
|
|
||||||
private User mockUser;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
mockTeam = new Team();
|
|
||||||
mockTeam.setId(1L);
|
|
||||||
mockTeam.setName("Test Team");
|
|
||||||
|
|
||||||
mockUser = new User();
|
|
||||||
mockUser.setId(1L);
|
|
||||||
mockUser.setUsername("testuser");
|
|
||||||
mockUser.setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithUsernameAndAuthenticationType_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
String username = "testuser";
|
|
||||||
AuthenticationType authType = AuthenticationType.WEB;
|
|
||||||
|
|
||||||
when(teamRepository.findByName("Default")).thenReturn(Optional.of(mockTeam));
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doNothing().when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When
|
|
||||||
userService.saveUser(username, authType);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithUsernamePasswordAndTeamId_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
String username = "testuser";
|
|
||||||
String password = "password123";
|
|
||||||
Long teamId = 1L;
|
|
||||||
String encodedPassword = "encodedPassword123";
|
|
||||||
|
|
||||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
|
||||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doNothing().when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When
|
|
||||||
User result = userService.saveUser(username, password, teamId);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
verify(passwordEncoder).encode(password);
|
|
||||||
verify(teamRepository).findById(teamId);
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithTeamAndRole_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
String username = "testuser";
|
|
||||||
String password = "password123";
|
|
||||||
String role = Role.ADMIN.getRoleId();
|
|
||||||
boolean firstLogin = true;
|
|
||||||
String encodedPassword = "encodedPassword123";
|
|
||||||
|
|
||||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doNothing().when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When
|
|
||||||
User result = userService.saveUser(username, password, mockTeam, role, firstLogin);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
verify(passwordEncoder).encode(password);
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithInvalidUsername_ThrowsException() throws Exception {
|
|
||||||
// Given
|
|
||||||
String invalidUsername = "ab"; // Too short (less than 3 characters)
|
|
||||||
AuthenticationType authType = AuthenticationType.WEB;
|
|
||||||
|
|
||||||
// When & Then
|
|
||||||
IllegalArgumentException exception = assertThrows(
|
|
||||||
IllegalArgumentException.class,
|
|
||||||
() -> userService.saveUser(invalidUsername, authType)
|
|
||||||
);
|
|
||||||
|
|
||||||
verify(userRepository, never()).save(any(User.class));
|
|
||||||
verify(databaseService, never()).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithNullPassword_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
String username = "testuser";
|
|
||||||
Long teamId = 1L;
|
|
||||||
|
|
||||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doNothing().when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When
|
|
||||||
User result = userService.saveUser(username, null, teamId);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
verify(passwordEncoder, never()).encode(anyString());
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithEmptyPassword_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
String username = "testuser";
|
|
||||||
String emptyPassword = "";
|
|
||||||
Long teamId = 1L;
|
|
||||||
|
|
||||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doNothing().when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When
|
|
||||||
User result = userService.saveUser(username, emptyPassword, teamId);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
verify(passwordEncoder, never()).encode(anyString());
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithValidEmail_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
String emailUsername = "test@example.com";
|
|
||||||
AuthenticationType authType = AuthenticationType.SSO;
|
|
||||||
|
|
||||||
when(teamRepository.findByName("Default")).thenReturn(Optional.of(mockTeam));
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doNothing().when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When
|
|
||||||
userService.saveUser(emailUsername, authType);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithReservedUsername_ThrowsException() throws Exception {
|
|
||||||
// Given
|
|
||||||
String reservedUsername = "all_users";
|
|
||||||
AuthenticationType authType = AuthenticationType.WEB;
|
|
||||||
|
|
||||||
// When & Then
|
|
||||||
IllegalArgumentException exception = assertThrows(
|
|
||||||
IllegalArgumentException.class,
|
|
||||||
() -> userService.saveUser(reservedUsername, authType)
|
|
||||||
);
|
|
||||||
|
|
||||||
verify(userRepository, never()).save(any(User.class));
|
|
||||||
verify(databaseService, never()).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithAnonymousUser_ThrowsException() throws Exception {
|
|
||||||
// Given
|
|
||||||
String anonymousUsername = "anonymoususer";
|
|
||||||
AuthenticationType authType = AuthenticationType.WEB;
|
|
||||||
|
|
||||||
// When & Then
|
|
||||||
IllegalArgumentException exception = assertThrows(
|
|
||||||
IllegalArgumentException.class,
|
|
||||||
() -> userService.saveUser(anonymousUsername, authType)
|
|
||||||
);
|
|
||||||
|
|
||||||
verify(userRepository, never()).save(any(User.class));
|
|
||||||
verify(databaseService, never()).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_DatabaseExportThrowsException_StillSavesUser() throws Exception {
|
|
||||||
// Given
|
|
||||||
String username = "testuser";
|
|
||||||
String password = "password123";
|
|
||||||
Long teamId = 1L;
|
|
||||||
String encodedPassword = "encodedPassword123";
|
|
||||||
|
|
||||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
|
||||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doThrow(new SQLException("Database export failed")).when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When & Then
|
|
||||||
assertThrows(SQLException.class, () -> userService.saveUser(username, password, teamId));
|
|
||||||
|
|
||||||
// Verify user was still saved before the exception
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithFirstLoginFlag_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
String username = "testuser";
|
|
||||||
String password = "password123";
|
|
||||||
Long teamId = 1L;
|
|
||||||
boolean firstLogin = true;
|
|
||||||
boolean enabled = false;
|
|
||||||
String encodedPassword = "encodedPassword123";
|
|
||||||
|
|
||||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
|
||||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doNothing().when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When
|
|
||||||
userService.saveUser(username, password, teamId, firstLogin, enabled);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(passwordEncoder).encode(password);
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testSaveUser_WithCustomRole_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
String username = "testuser";
|
|
||||||
String password = "password123";
|
|
||||||
Long teamId = 1L;
|
|
||||||
String customRole = Role.LIMITED_API_USER.getRoleId();
|
|
||||||
String encodedPassword = "encodedPassword123";
|
|
||||||
|
|
||||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
|
||||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
|
||||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
|
||||||
doNothing().when(databaseService).exportDatabase();
|
|
||||||
|
|
||||||
// When
|
|
||||||
userService.saveUser(username, password, teamId, customRole);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(passwordEncoder).encode(password);
|
|
||||||
verify(userRepository).save(any(User.class));
|
|
||||||
verify(databaseService).exportDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -13,6 +13,8 @@ import java.util.Properties;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
@ -216,16 +218,14 @@ public class SPDFApplication {
|
|||||||
}
|
}
|
||||||
log.info("######################################");
|
log.info("######################################");
|
||||||
// 2. Detect if SecurityConfiguration is present on classpath
|
// 2. Detect if SecurityConfiguration is present on classpath
|
||||||
if (isClassPresent(
|
if (isClassPresent("stirling.software.proprietary.security.configuration.SecurityConfiguration")) {
|
||||||
"stirling.software.proprietary.security.configuration.SecurityConfiguration")) {
|
|
||||||
log.info("security");
|
log.info("security");
|
||||||
return new String[] {"security"};
|
return new String[] { "security" };
|
||||||
} else {
|
} else {
|
||||||
log.info("default");
|
log.info("default");
|
||||||
return new String[] {"default"};
|
return new String[] { "default" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isClassPresent(String className) {
|
private static boolean isClassPresent(String className) {
|
||||||
try {
|
try {
|
||||||
Class.forName(className, false, SPDFApplication.class.getClassLoader());
|
Class.forName(className, false, SPDFApplication.class.getClassLoader());
|
||||||
|
@ -25,7 +25,9 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
// Handler for external static resources
|
// Handler for external static resources
|
||||||
registry.addResourceHandler("/**")
|
registry.addResourceHandler("/**")
|
||||||
.addResourceLocations(
|
.addResourceLocations(
|
||||||
"file:" + InstallationPathConfig.getStaticPath(), "classpath:/static/");
|
"file:" + InstallationPathConfig.getStaticPath(),
|
||||||
|
"classpath:/static/"
|
||||||
|
);
|
||||||
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
|
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
|
||||||
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
|
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
|
||||||
// .setCachePeriod(0); // Optional: disable caching
|
// .setCachePeriod(0); // Optional: disable caching
|
||||||
|
@ -69,8 +69,7 @@ public class EditTableOfContentsController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Map<String, Object>> extractBookmarkItems(
|
private List<Map<String, Object>> extractBookmarkItems(PDDocument document, PDDocumentOutline outline) throws Exception {
|
||||||
PDDocument document, PDDocumentOutline outline) throws Exception {
|
|
||||||
List<Map<String, Object>> bookmarks = new ArrayList<>();
|
List<Map<String, Object>> bookmarks = new ArrayList<>();
|
||||||
PDOutlineItem current = outline.getFirstChild();
|
PDOutlineItem current = outline.getFirstChild();
|
||||||
|
|
||||||
@ -115,8 +114,7 @@ public class EditTableOfContentsController {
|
|||||||
return bookmarks;
|
return bookmarks;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> processChild(PDDocument document, PDOutlineItem item)
|
private Map<String, Object> processChild(PDDocument document, PDOutlineItem item) throws Exception {
|
||||||
throws Exception {
|
|
||||||
Map<String, Object> bookmark = new HashMap<>();
|
Map<String, Object> bookmark = new HashMap<>();
|
||||||
|
|
||||||
// Get bookmark title
|
// Get bookmark title
|
||||||
@ -156,8 +154,8 @@ public class EditTableOfContentsController {
|
|||||||
@Operation(
|
@Operation(
|
||||||
summary = "Edit Table of Contents",
|
summary = "Edit Table of Contents",
|
||||||
description = "Add or edit bookmarks/table of contents in a PDF document.")
|
description = "Add or edit bookmarks/table of contents in a PDF document.")
|
||||||
public ResponseEntity<byte[]> editTableOfContents(
|
public ResponseEntity<byte[]> editTableOfContents(@ModelAttribute EditTableOfContentsRequest request)
|
||||||
@ModelAttribute EditTableOfContentsRequest request) throws Exception {
|
throws Exception {
|
||||||
MultipartFile file = request.getFileInput();
|
MultipartFile file = request.getFileInput();
|
||||||
PDDocument document = null;
|
PDDocument document = null;
|
||||||
|
|
||||||
@ -165,9 +163,9 @@ public class EditTableOfContentsController {
|
|||||||
document = pdfDocumentFactory.load(file);
|
document = pdfDocumentFactory.load(file);
|
||||||
|
|
||||||
// Parse the bookmark data from JSON
|
// Parse the bookmark data from JSON
|
||||||
List<BookmarkItem> bookmarks =
|
List<BookmarkItem> bookmarks = objectMapper.readValue(
|
||||||
objectMapper.readValue(
|
request.getBookmarkData(),
|
||||||
request.getBookmarkData(), new TypeReference<List<BookmarkItem>>() {});
|
new TypeReference<List<BookmarkItem>>() {});
|
||||||
|
|
||||||
// Create a new document outline
|
// Create a new document outline
|
||||||
PDDocumentOutline outline = new PDDocumentOutline();
|
PDDocumentOutline outline = new PDDocumentOutline();
|
||||||
@ -191,8 +189,7 @@ public class EditTableOfContentsController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addBookmarksToOutline(
|
private void addBookmarksToOutline(PDDocument document, PDDocumentOutline outline, List<BookmarkItem> bookmarks) {
|
||||||
PDDocument document, PDDocumentOutline outline, List<BookmarkItem> bookmarks) {
|
|
||||||
for (BookmarkItem bookmark : bookmarks) {
|
for (BookmarkItem bookmark : bookmarks) {
|
||||||
PDOutlineItem item = createOutlineItem(document, bookmark);
|
PDOutlineItem item = createOutlineItem(document, bookmark);
|
||||||
outline.addLast(item);
|
outline.addLast(item);
|
||||||
@ -203,8 +200,7 @@ public class EditTableOfContentsController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addChildBookmarks(
|
private void addChildBookmarks(PDDocument document, PDOutlineItem parent, List<BookmarkItem> children) {
|
||||||
PDDocument document, PDOutlineItem parent, List<BookmarkItem> children) {
|
|
||||||
for (BookmarkItem child : children) {
|
for (BookmarkItem child : children) {
|
||||||
PDOutlineItem item = createOutlineItem(document, child);
|
PDOutlineItem item = createOutlineItem(document, child);
|
||||||
parent.addLast(item);
|
parent.addLast(item);
|
||||||
|
@ -27,9 +27,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
|
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/general")
|
@RequestMapping("/api/v1/general")
|
||||||
|
@ -31,11 +31,11 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
|
|
||||||
import stirling.software.common.model.PdfMetadata;
|
import stirling.software.common.model.PdfMetadata;
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
import stirling.software.common.service.PdfMetadataService;
|
import stirling.software.common.service.PdfMetadataService;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
|
import stirling.software.SPDF.model.api.SplitPdfByChaptersRequest;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/general")
|
@RequestMapping("/api/v1/general")
|
||||||
|
@ -31,9 +31,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
|
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
|
import stirling.software.SPDF.model.api.SplitPdfBySectionsRequest;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/general")
|
@RequestMapping("/api/v1/general")
|
||||||
|
@ -16,10 +16,8 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
import io.github.pixee.security.Filenames;
|
import io.github.pixee.security.Filenames;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.configuration.RuntimePathConfig;
|
import stirling.software.common.configuration.RuntimePathConfig;
|
||||||
import stirling.software.common.model.api.converters.EmlToPdfRequest;
|
import stirling.software.common.model.api.converters.EmlToPdfRequest;
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
@ -96,8 +94,7 @@ public class ConvertEmlToPDF {
|
|||||||
try {
|
try {
|
||||||
byte[] pdfBytes =
|
byte[] pdfBytes =
|
||||||
EmlToPdf.convertEmlToPdf(
|
EmlToPdf.convertEmlToPdf(
|
||||||
runtimePathConfig
|
runtimePathConfig.getWeasyPrintPath(), // Use configured WeasyPrint path
|
||||||
.getWeasyPrintPath(), // Use configured WeasyPrint path
|
|
||||||
request,
|
request,
|
||||||
fileBytes,
|
fileBytes,
|
||||||
originalFilename,
|
originalFilename,
|
||||||
@ -122,20 +119,12 @@ public class ConvertEmlToPDF {
|
|||||||
.body("Conversion was interrupted".getBytes(StandardCharsets.UTF_8));
|
.body("Conversion was interrupted".getBytes(StandardCharsets.UTF_8));
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
String errorMessage = buildErrorMessage(e, originalFilename);
|
String errorMessage = buildErrorMessage(e, originalFilename);
|
||||||
log.error(
|
log.error("EML to PDF conversion failed for {}: {}", originalFilename, errorMessage, e);
|
||||||
"EML to PDF conversion failed for {}: {}",
|
|
||||||
originalFilename,
|
|
||||||
errorMessage,
|
|
||||||
e);
|
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
.body(errorMessage.getBytes(StandardCharsets.UTF_8));
|
.body(errorMessage.getBytes(StandardCharsets.UTF_8));
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
String errorMessage = buildErrorMessage(e, originalFilename);
|
String errorMessage = buildErrorMessage(e, originalFilename);
|
||||||
log.error(
|
log.error("EML to PDF conversion failed for {}: {}", originalFilename, errorMessage, e);
|
||||||
"EML to PDF conversion failed for {}: {}",
|
|
||||||
originalFilename,
|
|
||||||
errorMessage,
|
|
||||||
e);
|
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
.body(errorMessage.getBytes(StandardCharsets.UTF_8));
|
.body(errorMessage.getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import stirling.software.common.model.api.GeneralFile;
|
||||||
import stirling.software.common.configuration.RuntimePathConfig;
|
import stirling.software.common.configuration.RuntimePathConfig;
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
import stirling.software.common.model.api.GeneralFile;
|
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||||
import stirling.software.common.util.FileToPdf;
|
import stirling.software.common.util.FileToPdf;
|
||||||
import stirling.software.common.util.WebResponseUtils;
|
import stirling.software.common.util.WebResponseUtils;
|
||||||
|
@ -36,8 +36,8 @@ import stirling.software.SPDF.model.PipelineConfig;
|
|||||||
import stirling.software.SPDF.model.PipelineOperation;
|
import stirling.software.SPDF.model.PipelineOperation;
|
||||||
import stirling.software.SPDF.model.PipelineResult;
|
import stirling.software.SPDF.model.PipelineResult;
|
||||||
import stirling.software.SPDF.service.ApiDocService;
|
import stirling.software.SPDF.service.ApiDocService;
|
||||||
import stirling.software.common.configuration.RuntimePathConfig;
|
|
||||||
import stirling.software.common.service.PostHogService;
|
import stirling.software.common.service.PostHogService;
|
||||||
|
import stirling.software.common.configuration.RuntimePathConfig;
|
||||||
import stirling.software.common.util.FileMonitor;
|
import stirling.software.common.util.FileMonitor;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -184,8 +184,7 @@ public class RedactController {
|
|||||||
String pageNumbersInput = request.getPageNumbers();
|
String pageNumbersInput = request.getPageNumbers();
|
||||||
String[] parsedPageNumbers =
|
String[] parsedPageNumbers =
|
||||||
pageNumbersInput != null ? pageNumbersInput.split(",") : new String[0];
|
pageNumbersInput != null ? pageNumbersInput.split(",") : new String[0];
|
||||||
List<Integer> pageNumbers =
|
List<Integer> pageNumbers = GeneralUtils.parsePageList(parsedPageNumbers, pagesCount, false);
|
||||||
GeneralUtils.parsePageList(parsedPageNumbers, pagesCount, false);
|
|
||||||
Collections.sort(pageNumbers);
|
Collections.sort(pageNumbers);
|
||||||
return pageNumbers;
|
return pageNumbers;
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ import io.swagger.v3.oas.annotations.Hidden;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.Dependency;
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.model.Dependency;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Controller
|
@Controller
|
||||||
@ -48,7 +48,9 @@ public class HomeWebController {
|
|||||||
InputStream is = resource.getInputStream();
|
InputStream is = resource.getInputStream();
|
||||||
String json = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
String json = new String(is.readAllBytes(), StandardCharsets.UTF_8);
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
Map<String, List<Dependency>> data = mapper.readValue(json, new TypeReference<>() {});
|
Map<String, List<Dependency>> data =
|
||||||
|
mapper.readValue(json, new TypeReference<>() {
|
||||||
|
});
|
||||||
model.addAttribute("dependencies", data.get("dependencies"));
|
model.addAttribute("dependencies", data.get("dependencies"));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("exception", e);
|
log.error("exception", e);
|
||||||
|
@ -4,21 +4,15 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
import stirling.software.common.model.api.PDFFile;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
public class EditTableOfContentsRequest extends PDFFile {
|
public class EditTableOfContentsRequest extends PDFFile {
|
||||||
|
|
||||||
@Schema(
|
@Schema(description = "Bookmark structure in JSON format", example = "[{\"title\":\"Chapter 1\",\"pageNumber\":1,\"children\":[{\"title\":\"Section 1.1\",\"pageNumber\":2}]}]")
|
||||||
description = "Bookmark structure in JSON format",
|
|
||||||
example =
|
|
||||||
"[{\"title\":\"Chapter 1\",\"pageNumber\":1,\"children\":[{\"title\":\"Section 1.1\",\"pageNumber\":2}]}]")
|
|
||||||
private String bookmarkData;
|
private String bookmarkData;
|
||||||
|
|
||||||
@Schema(
|
@Schema(description = "Whether to replace existing bookmarks or append to them", example = "true")
|
||||||
description = "Whether to replace existing bookmarks or append to them",
|
|
||||||
example = "true")
|
|
||||||
private Boolean replaceExisting;
|
private Boolean replaceExisting;
|
||||||
}
|
}
|
@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
import stirling.software.common.model.api.PDFFile;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
import stirling.software.common.model.api.PDFFile;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
import stirling.software.SPDF.model.api.PDFWithPageNums;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
import stirling.software.common.model.api.PDFFile;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import stirling.software.common.model.api.PDFFile;
|
import stirling.software.common.model.api.PDFFile;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -14,8 +14,8 @@ import io.micrometer.core.instrument.search.Search;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import stirling.software.SPDF.config.EndpointInspector;
|
|
||||||
import stirling.software.common.service.PostHogService;
|
import stirling.software.common.service.PostHogService;
|
||||||
|
import stirling.software.SPDF.config.EndpointInspector;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@ -45,77 +45,77 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.core:jackson-annotations",
|
"moduleName": "com.fasterxml.jackson.core:jackson-annotations",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson",
|
"moduleUrl": "https://github.com/FasterXML/jackson",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.core:jackson-core",
|
"moduleName": "com.fasterxml.jackson.core:jackson-core",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-core",
|
"moduleUrl": "https://github.com/FasterXML/jackson-core",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.core:jackson-databind",
|
"moduleName": "com.fasterxml.jackson.core:jackson-databind",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson",
|
"moduleUrl": "https://github.com/FasterXML/jackson",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml",
|
"moduleName": "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-dataformats-text",
|
"moduleUrl": "https://github.com/FasterXML/jackson-dataformats-text",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8",
|
"moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jdk8",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8",
|
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jdk8",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310",
|
"moduleName": "com.fasterxml.jackson.datatype:jackson-datatype-jsr310",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310",
|
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.jaxrs:jackson-jaxrs-base",
|
"moduleName": "com.fasterxml.jackson.jaxrs:jackson-jaxrs-base",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-jaxrs-providers/jackson-jaxrs-base",
|
"moduleUrl": "https://github.com/FasterXML/jackson-jaxrs-providers/jackson-jaxrs-base",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider",
|
"moduleName": "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-jaxrs-providers/jackson-jaxrs-json-provider",
|
"moduleUrl": "https://github.com/FasterXML/jackson-jaxrs-providers/jackson-jaxrs-json-provider",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.module:jackson-module-jaxb-annotations",
|
"moduleName": "com.fasterxml.jackson.module:jackson-module-jaxb-annotations",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-base",
|
"moduleUrl": "https://github.com/FasterXML/jackson-modules-base",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson.module:jackson-module-parameter-names",
|
"moduleName": "com.fasterxml.jackson.module:jackson-module-parameter-names",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names",
|
"moduleUrl": "https://github.com/FasterXML/jackson-modules-java8/jackson-module-parameter-names",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.fasterxml.jackson:jackson-bom",
|
"moduleName": "com.fasterxml.jackson:jackson-bom",
|
||||||
"moduleUrl": "https://github.com/FasterXML/jackson-bom",
|
"moduleUrl": "https://github.com/FasterXML/jackson-bom",
|
||||||
"moduleVersion": "2.19.0",
|
"moduleVersion": "2.18.3",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -161,20 +161,14 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "com.google.code.gson:gson",
|
"moduleName": "com.google.code.gson:gson",
|
||||||
"moduleUrl": "https://github.com/google/gson",
|
"moduleUrl": "https://github.com/google/gson",
|
||||||
"moduleVersion": "2.13.1",
|
"moduleVersion": "2.11.0",
|
||||||
"moduleLicense": "Apache-2.0",
|
"moduleLicense": "Apache-2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "com.google.errorprone:error_prone_annotations",
|
|
||||||
"moduleVersion": "2.11.0",
|
|
||||||
"moduleLicense": "Apache 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "com.google.errorprone:error_prone_annotations",
|
"moduleName": "com.google.errorprone:error_prone_annotations",
|
||||||
"moduleUrl": "https://errorprone.info/error_prone_annotations",
|
"moduleUrl": "https://errorprone.info/error_prone_annotations",
|
||||||
"moduleVersion": "2.38.0",
|
"moduleVersion": "2.27.0",
|
||||||
"moduleLicense": "Apache 2.0",
|
"moduleLicense": "Apache 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -497,7 +491,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "com.zaxxer:HikariCP",
|
"moduleName": "com.zaxxer:HikariCP",
|
||||||
"moduleUrl": "https://github.com/brettwooldridge/HikariCP",
|
"moduleUrl": "https://github.com/brettwooldridge/HikariCP",
|
||||||
"moduleVersion": "6.3.0",
|
"moduleVersion": "5.1.0",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -518,7 +512,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "commons-codec:commons-codec",
|
"moduleName": "commons-codec:commons-codec",
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-codec/",
|
"moduleUrl": "https://commons.apache.org/proper/commons-codec/",
|
||||||
"moduleVersion": "1.18.0",
|
"moduleVersion": "1.17.2",
|
||||||
"moduleLicense": "Apache-2.0",
|
"moduleLicense": "Apache-2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -529,20 +523,6 @@
|
|||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "commons-io:commons-io",
|
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-io/",
|
|
||||||
"moduleVersion": "2.11.0",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"moduleName": "commons-io:commons-io",
|
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-io/",
|
|
||||||
"moduleVersion": "2.13.0",
|
|
||||||
"moduleLicense": "Apache-2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "commons-io:commons-io",
|
"moduleName": "commons-io:commons-io",
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-io/",
|
"moduleUrl": "https://commons.apache.org/proper/commons-io/",
|
||||||
@ -566,7 +546,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "io.micrometer:micrometer-commons",
|
"moduleName": "io.micrometer:micrometer-commons",
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||||
"moduleVersion": "1.15.0",
|
"moduleVersion": "1.14.6",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -577,31 +557,24 @@
|
|||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "io.micrometer:micrometer-core",
|
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
|
||||||
"moduleVersion": "1.15.0",
|
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "io.micrometer:micrometer-jakarta9",
|
"moduleName": "io.micrometer:micrometer-jakarta9",
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||||
"moduleVersion": "1.15.0",
|
"moduleVersion": "1.14.6",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "io.micrometer:micrometer-observation",
|
"moduleName": "io.micrometer:micrometer-observation",
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||||
"moduleVersion": "1.15.0",
|
"moduleVersion": "1.14.6",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "io.micrometer:micrometer-registry-prometheus",
|
"moduleName": "io.micrometer:micrometer-registry-prometheus",
|
||||||
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
"moduleUrl": "https://github.com/micrometer-metrics/micrometer",
|
||||||
"moduleVersion": "1.15.0",
|
"moduleVersion": "1.14.6",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -710,13 +683,6 @@
|
|||||||
"moduleLicense": "GPL2 w/ CPE",
|
"moduleLicense": "GPL2 w/ CPE",
|
||||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "jakarta.mail:jakarta.mail-api",
|
|
||||||
"moduleUrl": "https://www.eclipse.org",
|
|
||||||
"moduleVersion": "2.1.3",
|
|
||||||
"moduleLicense": "GPL2 w/ CPE",
|
|
||||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "jakarta.persistence:jakarta.persistence-api",
|
"moduleName": "jakarta.persistence:jakarta.persistence-api",
|
||||||
"moduleUrl": "https://www.eclipse.org",
|
"moduleUrl": "https://www.eclipse.org",
|
||||||
@ -731,13 +697,6 @@
|
|||||||
"moduleLicense": "GPL2 w/ CPE",
|
"moduleLicense": "GPL2 w/ CPE",
|
||||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "jakarta.servlet:jakarta.servlet-api",
|
|
||||||
"moduleUrl": "https://www.eclipse.org",
|
|
||||||
"moduleVersion": "6.1.0",
|
|
||||||
"moduleLicense": "GPL2 w/ CPE",
|
|
||||||
"moduleLicenseUrl": "https://www.gnu.org/software/classpath/license.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "jakarta.transaction:jakarta.transaction-api",
|
"moduleName": "jakarta.transaction:jakarta.transaction-api",
|
||||||
"moduleUrl": "https://projects.eclipse.org/projects/ee4j.jta",
|
"moduleUrl": "https://projects.eclipse.org/projects/ee4j.jta",
|
||||||
@ -817,7 +776,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "net.bytebuddy:byte-buddy",
|
"moduleName": "net.bytebuddy:byte-buddy",
|
||||||
"moduleVersion": "1.17.5",
|
"moduleVersion": "1.15.11",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -876,13 +835,6 @@
|
|||||||
"moduleLicense": "Apache-2.0",
|
"moduleLicense": "Apache-2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.apache.commons:commons-text",
|
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-text",
|
|
||||||
"moduleVersion": "1.10.0",
|
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.apache.commons:commons-text",
|
"moduleName": "org.apache.commons:commons-text",
|
||||||
"moduleUrl": "https://commons.apache.org/proper/commons-text",
|
"moduleUrl": "https://commons.apache.org/proper/commons-text",
|
||||||
@ -967,7 +919,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.apache.tomcat.embed:tomcat-embed-el",
|
"moduleName": "org.apache.tomcat.embed:tomcat-embed-el",
|
||||||
"moduleUrl": "https://tomcat.apache.org/",
|
"moduleUrl": "https://tomcat.apache.org/",
|
||||||
"moduleVersion": "10.1.41",
|
"moduleVersion": "10.1.40",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -1005,13 +957,6 @@
|
|||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.bouncycastle:bcpkix-jdk18on",
|
|
||||||
"moduleUrl": "https://www.bouncycastle.org/java.html",
|
|
||||||
"moduleVersion": "1.72",
|
|
||||||
"moduleLicense": "Bouncy Castle Licence",
|
|
||||||
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.bouncycastle:bcpkix-jdk18on",
|
"moduleName": "org.bouncycastle:bcpkix-jdk18on",
|
||||||
"moduleUrl": "https://www.bouncycastle.org/download/bouncy-castle-java/",
|
"moduleUrl": "https://www.bouncycastle.org/download/bouncy-castle-java/",
|
||||||
@ -1026,13 +971,6 @@
|
|||||||
"moduleLicense": "Bouncy Castle Licence",
|
"moduleLicense": "Bouncy Castle Licence",
|
||||||
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"moduleName": "org.bouncycastle:bcutil-jdk18on",
|
|
||||||
"moduleUrl": "https://www.bouncycastle.org/java.html",
|
|
||||||
"moduleVersion": "1.72",
|
|
||||||
"moduleLicense": "Bouncy Castle Licence",
|
|
||||||
"moduleLicenseUrl": "https://www.bouncycastle.org/licence.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"moduleName": "org.bouncycastle:bcutil-jdk18on",
|
"moduleName": "org.bouncycastle:bcutil-jdk18on",
|
||||||
"moduleUrl": "https://www.bouncycastle.org/download/bouncy-castle-java/",
|
"moduleUrl": "https://www.bouncycastle.org/download/bouncy-castle-java/",
|
||||||
@ -1083,182 +1021,182 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-client",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-client",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-common",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-common",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jetty-server",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jetty-server",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-servlet",
|
"moduleName": "org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-servlet",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-annotations",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-annotations",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-plus",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-plus",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlet",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlet",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlets",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-servlets",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-webapp",
|
"moduleName": "org.eclipse.jetty.ee10:jetty-ee10-webapp",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-client",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-client",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-common",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-common",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-server",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-core-server",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-api",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-api",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-common",
|
"moduleName": "org.eclipse.jetty.websocket:jetty-websocket-jetty-common",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-alpn-client",
|
"moduleName": "org.eclipse.jetty:jetty-alpn-client",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-client",
|
"moduleName": "org.eclipse.jetty:jetty-client",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-ee",
|
"moduleName": "org.eclipse.jetty:jetty-ee",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-http",
|
"moduleName": "org.eclipse.jetty:jetty-http",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-io",
|
"moduleName": "org.eclipse.jetty:jetty-io",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-plus",
|
"moduleName": "org.eclipse.jetty:jetty-plus",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-security",
|
"moduleName": "org.eclipse.jetty:jetty-security",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-server",
|
"moduleName": "org.eclipse.jetty:jetty-server",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-session",
|
"moduleName": "org.eclipse.jetty:jetty-session",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-util",
|
"moduleName": "org.eclipse.jetty:jetty-util",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.eclipse.jetty:jetty-xml",
|
"moduleName": "org.eclipse.jetty:jetty-xml",
|
||||||
"moduleUrl": "https://jetty.org/",
|
"moduleUrl": "https://jetty.org/",
|
||||||
"moduleVersion": "12.0.21",
|
"moduleVersion": "12.0.19",
|
||||||
"moduleLicense": "Eclipse Public License - Version 2.0",
|
"moduleLicense": "Eclipse Public License - Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-2.0/"
|
||||||
},
|
},
|
||||||
@ -1300,7 +1238,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.hibernate.orm:hibernate-core",
|
"moduleName": "org.hibernate.orm:hibernate-core",
|
||||||
"moduleUrl": "https://www.hibernate.org/orm/6.6",
|
"moduleUrl": "https://www.hibernate.org/orm/6.6",
|
||||||
"moduleVersion": "6.6.15.Final",
|
"moduleVersion": "6.6.13.Final",
|
||||||
"moduleLicense": "GNU Library General Public License v2.1 or later",
|
"moduleLicense": "GNU Library General Public License v2.1 or later",
|
||||||
"moduleLicenseUrl": "https://www.opensource.org/licenses/LGPL-2.1"
|
"moduleLicenseUrl": "https://www.opensource.org/licenses/LGPL-2.1"
|
||||||
},
|
},
|
||||||
@ -1517,294 +1455,294 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot",
|
"moduleName": "org.springframework.boot:spring-boot",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-actuator",
|
"moduleName": "org.springframework.boot:spring-boot-actuator",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-actuator-autoconfigure",
|
"moduleName": "org.springframework.boot:spring-boot-actuator-autoconfigure",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-autoconfigure",
|
"moduleName": "org.springframework.boot:spring-boot-autoconfigure",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-devtools",
|
"moduleName": "org.springframework.boot:spring-boot-devtools",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter",
|
"moduleName": "org.springframework.boot:spring-boot-starter",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-actuator",
|
"moduleName": "org.springframework.boot:spring-boot-starter-actuator",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-data-jpa",
|
"moduleName": "org.springframework.boot:spring-boot-starter-data-jpa",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-jdbc",
|
"moduleName": "org.springframework.boot:spring-boot-starter-jdbc",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-jetty",
|
"moduleName": "org.springframework.boot:spring-boot-starter-jetty",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-json",
|
"moduleName": "org.springframework.boot:spring-boot-starter-json",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-logging",
|
"moduleName": "org.springframework.boot:spring-boot-starter-logging",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-mail",
|
"moduleName": "org.springframework.boot:spring-boot-starter-mail",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-oauth2-client",
|
"moduleName": "org.springframework.boot:spring-boot-starter-oauth2-client",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-security",
|
"moduleName": "org.springframework.boot:spring-boot-starter-security",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-thymeleaf",
|
"moduleName": "org.springframework.boot:spring-boot-starter-thymeleaf",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-validation",
|
"moduleName": "org.springframework.boot:spring-boot-starter-validation",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.boot:spring-boot-starter-web",
|
"moduleName": "org.springframework.boot:spring-boot-starter-web",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-boot",
|
"moduleUrl": "https://spring.io/projects/spring-boot",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.data:spring-data-commons",
|
"moduleName": "org.springframework.data:spring-data-commons",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-data",
|
"moduleUrl": "https://spring.io/projects/spring-data",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.data:spring-data-jpa",
|
"moduleName": "org.springframework.data:spring-data-jpa",
|
||||||
"moduleUrl": "https://projects.spring.io/spring-data-jpa",
|
"moduleUrl": "https://projects.spring.io/spring-data-jpa",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-config",
|
"moduleName": "org.springframework.security:spring-security-config",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.5.0",
|
"moduleVersion": "6.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-core",
|
"moduleName": "org.springframework.security:spring-security-core",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.5.0",
|
"moduleVersion": "6.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-crypto",
|
"moduleName": "org.springframework.security:spring-security-crypto",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.5.0",
|
"moduleVersion": "6.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-oauth2-client",
|
"moduleName": "org.springframework.security:spring-security-oauth2-client",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.5.0",
|
"moduleVersion": "6.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-oauth2-core",
|
"moduleName": "org.springframework.security:spring-security-oauth2-core",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.5.0",
|
"moduleVersion": "6.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-oauth2-jose",
|
"moduleName": "org.springframework.security:spring-security-oauth2-jose",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.5.0",
|
"moduleVersion": "6.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-saml2-service-provider",
|
"moduleName": "org.springframework.security:spring-security-saml2-service-provider",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.5.0",
|
"moduleVersion": "6.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.security:spring-security-web",
|
"moduleName": "org.springframework.security:spring-security-web",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-security",
|
"moduleUrl": "https://spring.io/projects/spring-security",
|
||||||
"moduleVersion": "6.5.0",
|
"moduleVersion": "6.4.5",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework.session:spring-session-core",
|
"moduleName": "org.springframework.session:spring-session-core",
|
||||||
"moduleUrl": "https://spring.io/projects/spring-session",
|
"moduleUrl": "https://spring.io/projects/spring-session",
|
||||||
"moduleVersion": "3.5.0",
|
"moduleVersion": "3.4.3",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-aop",
|
"moduleName": "org.springframework:spring-aop",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-aspects",
|
"moduleName": "org.springframework:spring-aspects",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-beans",
|
"moduleName": "org.springframework:spring-beans",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-context",
|
"moduleName": "org.springframework:spring-context",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-context-support",
|
"moduleName": "org.springframework:spring-context-support",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-core",
|
"moduleName": "org.springframework:spring-core",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-expression",
|
"moduleName": "org.springframework:spring-expression",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-jcl",
|
"moduleName": "org.springframework:spring-jcl",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-jdbc",
|
"moduleName": "org.springframework:spring-jdbc",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-orm",
|
"moduleName": "org.springframework:spring-orm",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-tx",
|
"moduleName": "org.springframework:spring-tx",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-web",
|
"moduleName": "org.springframework:spring-web",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-webmvc",
|
"moduleName": "org.springframework:spring-webmvc",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.2.7",
|
"moduleVersion": "6.2.6",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
@ -1848,14 +1786,14 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.webjars:webjars-locator-lite",
|
"moduleName": "org.webjars:webjars-locator-lite",
|
||||||
"moduleUrl": "https://webjars.org",
|
"moduleUrl": "https://webjars.org",
|
||||||
"moduleVersion": "1.1.0",
|
"moduleVersion": "1.0.1",
|
||||||
"moduleLicense": "MIT",
|
"moduleLicense": "MIT",
|
||||||
"moduleLicenseUrl": "https://github.com/webjars/webjars-locator-lite/blob/main/LICENSE.md"
|
"moduleLicenseUrl": "https://github.com/webjars/webjars-locator-lite/blob/main/LICENSE.md"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.yaml:snakeyaml",
|
"moduleName": "org.yaml:snakeyaml",
|
||||||
"moduleUrl": "https://bitbucket.org/snakeyaml/snakeyaml",
|
"moduleUrl": "https://bitbucket.org/snakeyaml/snakeyaml",
|
||||||
"moduleVersion": "2.4",
|
"moduleVersion": "2.3",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
|
@ -77,15 +77,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Alert Messages -->
|
<!-- Alert Messages -->
|
||||||
<div th:if="${addMessage}" th:class="${#strings.contains(addMessage, 'Successfully') or #strings.contains(addMessage, 'Created') ? 'alert alert-success data-mb-3' : 'alert alert-danger data-mb-3'}">
|
<div th:if="${addMessage}" class="alert alert-danger data-mb-3">
|
||||||
<span th:text="#{${addMessage}}">Default message if not found</span>
|
<span th:text="#{${addMessage}}">Default message if not found</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div th:if="${changeMessage}" th:class="${#strings.contains(changeMessage, 'Successfully') or #strings.contains(changeMessage, 'Created') ? 'alert alert-success data-mb-3' : 'alert alert-danger data-mb-3'}">
|
<div th:if="${changeMessage}" class="alert alert-danger data-mb-3">
|
||||||
<span th:text="#{${changeMessage}}">Default message if not found</span>
|
<span th:text="#{${changeMessage}}">Default message if not found</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div th:if="${deleteMessage}" th:class="${#strings.contains(deleteMessage, 'Successfully') or #strings.contains(deleteMessage, 'Created') ? 'alert alert-success data-mb-3' : 'alert alert-danger data-mb-3'}">
|
<div th:if="${deleteMessage}" class="alert alert-danger data-mb-3">
|
||||||
<span th:text="#{${deleteMessage}}">Default message if not found</span>
|
<span th:text="#{${deleteMessage}}">Default message if not found</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -28,6 +28,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToText.submit}"></button>
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToText.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
|
<p th:if="${@endpointConfiguration.isEndpointEnabled('pdf-to-rtf')}" class="mt-3" th:text="#{PDFToText.credit}"></p>
|
||||||
|
<option th:if="${@endpointConfiguration.isEndpointEnabled('pdf-to-rtf')}" value="rtf">RTF</option>
|
||||||
|
<option value="txt">TXT</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToText.submit}"></button>
|
||||||
|
</form>
|
||||||
<p th:if="${@endpointConfiguration.isEndpointEnabled('pdf-to-rtf')}" class="mt-3" th:text="#{PDFToText.credit}"></p>
|
<p th:if="${@endpointConfiguration.isEndpointEnabled('pdf-to-rtf')}" class="mt-3" th:text="#{PDFToText.credit}"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -277,9 +277,6 @@
|
|||||||
<div
|
<div
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry('split-pdf-by-sections', 'grid_on', 'home.split-by-sections.title', 'home.split-by-sections.desc', 'split-by-sections.tags', 'advance')}">
|
th:replace="~{fragments/navbarEntry :: navbarEntry('split-pdf-by-sections', 'grid_on', 'home.split-by-sections.title', 'home.split-by-sections.desc', 'split-by-sections.tags', 'advance')}">
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
th:replace="~{fragments/navbarEntry :: navbarEntry('edit-table-of-contents', 'bookmark_add', 'home.editTableOfContents.title', 'home.editTableOfContents.desc', 'editTableOfContents.tags', 'advance')}">
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('split-pdf-by-chapters', '/images/split-chapters.svg#icon-split-chapters', 'home.splitPdfByChapters.title', 'home.splitPdfByChapters.desc', 'splitPdfByChapters.tags', 'advance')}">
|
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('split-pdf-by-chapters', '/images/split-chapters.svg#icon-split-chapters', 'home.splitPdfByChapters.title', 'home.splitPdfByChapters.desc', 'splitPdfByChapters.tags', 'advance')}">
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,9 +45,6 @@
|
|||||||
<div class="newfeature"
|
<div class="newfeature"
|
||||||
th:insert="~{fragments/navbarEntry :: navbarEntry('compress-pdf', 'zoom_in_map', 'home.compressPdfs.title', 'home.compressPdfs.desc', 'compressPDFs.tags', 'advance')}">
|
th:insert="~{fragments/navbarEntry :: navbarEntry('compress-pdf', 'zoom_in_map', 'home.compressPdfs.title', 'home.compressPdfs.desc', 'compressPDFs.tags', 'advance')}">
|
||||||
</div>
|
</div>
|
||||||
<div class="newfeature"
|
|
||||||
th:insert="~{fragments/navbarEntry :: navbarEntry('edit-table-of-contents', 'bookmark_add', 'home.editTableOfContents.title', 'home.editTableOfContents.desc', 'editTableOfContents.tags', 'advance')}">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,382 +0,0 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import static org.mockito.ArgumentMatchers.*;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDPage;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDPageTree;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.InjectMocks;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.mock.web.MockMultipartFile;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
import stirling.software.SPDF.controller.api.EditTableOfContentsController.BookmarkItem;
|
|
||||||
import stirling.software.SPDF.model.api.EditTableOfContentsRequest;
|
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
|
||||||
class EditTableOfContentsControllerTest {
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private CustomPDFDocumentFactory pdfDocumentFactory;
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private ObjectMapper objectMapper;
|
|
||||||
|
|
||||||
@InjectMocks
|
|
||||||
private EditTableOfContentsController editTableOfContentsController;
|
|
||||||
|
|
||||||
private MockMultipartFile mockFile;
|
|
||||||
private PDDocument mockDocument;
|
|
||||||
private PDDocumentCatalog mockCatalog;
|
|
||||||
private PDPageTree mockPages;
|
|
||||||
private PDPage mockPage1;
|
|
||||||
private PDPage mockPage2;
|
|
||||||
private PDDocumentOutline mockOutline;
|
|
||||||
private PDOutlineItem mockOutlineItem;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
mockFile = new MockMultipartFile("file", "test.pdf", "application/pdf", "PDF content".getBytes());
|
|
||||||
mockDocument = mock(PDDocument.class);
|
|
||||||
mockCatalog = mock(PDDocumentCatalog.class);
|
|
||||||
mockPages = mock(PDPageTree.class);
|
|
||||||
mockPage1 = mock(PDPage.class);
|
|
||||||
mockPage2 = mock(PDPage.class);
|
|
||||||
mockOutline = mock(PDDocumentOutline.class);
|
|
||||||
mockOutlineItem = mock(PDOutlineItem.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testExtractBookmarks_WithExistingBookmarks_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDocument);
|
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockCatalog.getDocumentOutline()).thenReturn(mockOutline);
|
|
||||||
when(mockOutline.getFirstChild()).thenReturn(mockOutlineItem);
|
|
||||||
|
|
||||||
when(mockOutlineItem.getTitle()).thenReturn("Chapter 1");
|
|
||||||
when(mockOutlineItem.findDestinationPage(mockDocument)).thenReturn(mockPage1);
|
|
||||||
when(mockDocument.getPages()).thenReturn(mockPages);
|
|
||||||
when(mockPages.indexOf(mockPage1)).thenReturn(0);
|
|
||||||
when(mockOutlineItem.getFirstChild()).thenReturn(null);
|
|
||||||
when(mockOutlineItem.getNextSibling()).thenReturn(null);
|
|
||||||
|
|
||||||
// When
|
|
||||||
List<Map<String, Object>> result = editTableOfContentsController.extractBookmarks(mockFile);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
assertEquals(1, result.size());
|
|
||||||
|
|
||||||
Map<String, Object> bookmark = result.get(0);
|
|
||||||
assertEquals("Chapter 1", bookmark.get("title"));
|
|
||||||
assertEquals(1, bookmark.get("pageNumber")); // 1-based
|
|
||||||
assertInstanceOf(List.class, bookmark.get("children"));
|
|
||||||
|
|
||||||
verify(mockDocument).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testExtractBookmarks_NoOutline_ReturnsEmptyList() throws Exception {
|
|
||||||
// Given
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDocument);
|
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockCatalog.getDocumentOutline()).thenReturn(null);
|
|
||||||
|
|
||||||
// When
|
|
||||||
List<Map<String, Object>> result = editTableOfContentsController.extractBookmarks(mockFile);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
assertTrue(result.isEmpty());
|
|
||||||
verify(mockDocument).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testExtractBookmarks_WithNestedBookmarks_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
PDOutlineItem childItem = mock(PDOutlineItem.class);
|
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDocument);
|
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockCatalog.getDocumentOutline()).thenReturn(mockOutline);
|
|
||||||
when(mockOutline.getFirstChild()).thenReturn(mockOutlineItem);
|
|
||||||
|
|
||||||
// Parent bookmark
|
|
||||||
when(mockOutlineItem.getTitle()).thenReturn("Chapter 1");
|
|
||||||
when(mockOutlineItem.findDestinationPage(mockDocument)).thenReturn(mockPage1);
|
|
||||||
when(mockDocument.getPages()).thenReturn(mockPages);
|
|
||||||
when(mockPages.indexOf(mockPage1)).thenReturn(0);
|
|
||||||
when(mockOutlineItem.getFirstChild()).thenReturn(childItem);
|
|
||||||
when(mockOutlineItem.getNextSibling()).thenReturn(null);
|
|
||||||
|
|
||||||
// Child bookmark
|
|
||||||
when(childItem.getTitle()).thenReturn("Section 1.1");
|
|
||||||
when(childItem.findDestinationPage(mockDocument)).thenReturn(mockPage2);
|
|
||||||
when(mockPages.indexOf(mockPage2)).thenReturn(1);
|
|
||||||
when(childItem.getFirstChild()).thenReturn(null);
|
|
||||||
when(childItem.getNextSibling()).thenReturn(null);
|
|
||||||
|
|
||||||
// When
|
|
||||||
List<Map<String, Object>> result = editTableOfContentsController.extractBookmarks(mockFile);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
assertEquals(1, result.size());
|
|
||||||
|
|
||||||
Map<String, Object> parentBookmark = result.get(0);
|
|
||||||
assertEquals("Chapter 1", parentBookmark.get("title"));
|
|
||||||
assertEquals(1, parentBookmark.get("pageNumber"));
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<Map<String, Object>> children = (List<Map<String, Object>>) parentBookmark.get("children");
|
|
||||||
assertEquals(1, children.size());
|
|
||||||
|
|
||||||
Map<String, Object> childBookmark = children.get(0);
|
|
||||||
assertEquals("Section 1.1", childBookmark.get("title"));
|
|
||||||
assertEquals(2, childBookmark.get("pageNumber"));
|
|
||||||
|
|
||||||
verify(mockDocument).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testExtractBookmarks_PageNotFound_UsesPageOne() throws Exception {
|
|
||||||
// Given
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDocument);
|
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockCatalog.getDocumentOutline()).thenReturn(mockOutline);
|
|
||||||
when(mockOutline.getFirstChild()).thenReturn(mockOutlineItem);
|
|
||||||
|
|
||||||
when(mockOutlineItem.getTitle()).thenReturn("Chapter 1");
|
|
||||||
when(mockOutlineItem.findDestinationPage(mockDocument)).thenReturn(null); // Page not found
|
|
||||||
when(mockOutlineItem.getFirstChild()).thenReturn(null);
|
|
||||||
when(mockOutlineItem.getNextSibling()).thenReturn(null);
|
|
||||||
|
|
||||||
// When
|
|
||||||
List<Map<String, Object>> result = editTableOfContentsController.extractBookmarks(mockFile);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
assertEquals(1, result.size());
|
|
||||||
|
|
||||||
Map<String, Object> bookmark = result.get(0);
|
|
||||||
assertEquals("Chapter 1", bookmark.get("title"));
|
|
||||||
assertEquals(1, bookmark.get("pageNumber")); // Default to page 1
|
|
||||||
|
|
||||||
verify(mockDocument).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testEditTableOfContents_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
EditTableOfContentsRequest request = new EditTableOfContentsRequest();
|
|
||||||
request.setFileInput(mockFile);
|
|
||||||
request.setBookmarkData("[{\"title\":\"Chapter 1\",\"pageNumber\":1,\"children\":[]}]");
|
|
||||||
request.setReplaceExisting(true);
|
|
||||||
|
|
||||||
List<BookmarkItem> bookmarks = new ArrayList<>();
|
|
||||||
BookmarkItem bookmark = new BookmarkItem();
|
|
||||||
bookmark.setTitle("Chapter 1");
|
|
||||||
bookmark.setPageNumber(1);
|
|
||||||
bookmark.setChildren(new ArrayList<>());
|
|
||||||
bookmarks.add(bookmark);
|
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDocument);
|
|
||||||
when(objectMapper.readValue(eq(request.getBookmarkData()), any(TypeReference.class))).thenReturn(bookmarks);
|
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockDocument.getNumberOfPages()).thenReturn(5);
|
|
||||||
when(mockDocument.getPage(0)).thenReturn(mockPage1);
|
|
||||||
|
|
||||||
// Mock saving behavior
|
|
||||||
doAnswer(invocation -> {
|
|
||||||
ByteArrayOutputStream baos = invocation.getArgument(0);
|
|
||||||
baos.write("mocked pdf content".getBytes());
|
|
||||||
return null;
|
|
||||||
}).when(mockDocument).save(any(ByteArrayOutputStream.class));
|
|
||||||
|
|
||||||
// When
|
|
||||||
ResponseEntity<byte[]> result = editTableOfContentsController.editTableOfContents(request);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
assertNotNull(result.getBody());
|
|
||||||
|
|
||||||
ArgumentCaptor<PDDocumentOutline> outlineCaptor = ArgumentCaptor.forClass(PDDocumentOutline.class);
|
|
||||||
verify(mockCatalog).setDocumentOutline(outlineCaptor.capture());
|
|
||||||
|
|
||||||
PDDocumentOutline capturedOutline = outlineCaptor.getValue();
|
|
||||||
assertNotNull(capturedOutline);
|
|
||||||
|
|
||||||
verify(mockDocument).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testEditTableOfContents_WithNestedBookmarks_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
EditTableOfContentsRequest request = new EditTableOfContentsRequest();
|
|
||||||
request.setFileInput(mockFile);
|
|
||||||
|
|
||||||
String bookmarkJson = "[{\"title\":\"Chapter 1\",\"pageNumber\":1,\"children\":[{\"title\":\"Section 1.1\",\"pageNumber\":2,\"children\":[]}]}]";
|
|
||||||
request.setBookmarkData(bookmarkJson);
|
|
||||||
|
|
||||||
List<BookmarkItem> bookmarks = new ArrayList<>();
|
|
||||||
BookmarkItem parentBookmark = new BookmarkItem();
|
|
||||||
parentBookmark.setTitle("Chapter 1");
|
|
||||||
parentBookmark.setPageNumber(1);
|
|
||||||
|
|
||||||
BookmarkItem childBookmark = new BookmarkItem();
|
|
||||||
childBookmark.setTitle("Section 1.1");
|
|
||||||
childBookmark.setPageNumber(2);
|
|
||||||
childBookmark.setChildren(new ArrayList<>());
|
|
||||||
|
|
||||||
List<BookmarkItem> children = new ArrayList<>();
|
|
||||||
children.add(childBookmark);
|
|
||||||
parentBookmark.setChildren(children);
|
|
||||||
bookmarks.add(parentBookmark);
|
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDocument);
|
|
||||||
when(objectMapper.readValue(eq(bookmarkJson), any(TypeReference.class))).thenReturn(bookmarks);
|
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockDocument.getNumberOfPages()).thenReturn(5);
|
|
||||||
when(mockDocument.getPage(0)).thenReturn(mockPage1);
|
|
||||||
when(mockDocument.getPage(1)).thenReturn(mockPage2);
|
|
||||||
|
|
||||||
doAnswer(invocation -> {
|
|
||||||
ByteArrayOutputStream baos = invocation.getArgument(0);
|
|
||||||
baos.write("mocked pdf content".getBytes());
|
|
||||||
return null;
|
|
||||||
}).when(mockDocument).save(any(ByteArrayOutputStream.class));
|
|
||||||
|
|
||||||
// When
|
|
||||||
ResponseEntity<byte[]> result = editTableOfContentsController.editTableOfContents(request);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
verify(mockCatalog).setDocumentOutline(any(PDDocumentOutline.class));
|
|
||||||
verify(mockDocument).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testEditTableOfContents_PageNumberBounds_ClampsValues() throws Exception {
|
|
||||||
// Given
|
|
||||||
EditTableOfContentsRequest request = new EditTableOfContentsRequest();
|
|
||||||
request.setFileInput(mockFile);
|
|
||||||
request.setBookmarkData("[{\"title\":\"Chapter 1\",\"pageNumber\":-5,\"children\":[]},{\"title\":\"Chapter 2\",\"pageNumber\":100,\"children\":[]}]");
|
|
||||||
|
|
||||||
List<BookmarkItem> bookmarks = new ArrayList<>();
|
|
||||||
|
|
||||||
BookmarkItem bookmark1 = new BookmarkItem();
|
|
||||||
bookmark1.setTitle("Chapter 1");
|
|
||||||
bookmark1.setPageNumber(-5); // Negative page number
|
|
||||||
bookmark1.setChildren(new ArrayList<>());
|
|
||||||
|
|
||||||
BookmarkItem bookmark2 = new BookmarkItem();
|
|
||||||
bookmark2.setTitle("Chapter 2");
|
|
||||||
bookmark2.setPageNumber(100); // Page number exceeds document pages
|
|
||||||
bookmark2.setChildren(new ArrayList<>());
|
|
||||||
|
|
||||||
bookmarks.add(bookmark1);
|
|
||||||
bookmarks.add(bookmark2);
|
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenReturn(mockDocument);
|
|
||||||
when(objectMapper.readValue(eq(request.getBookmarkData()), any(TypeReference.class))).thenReturn(bookmarks);
|
|
||||||
when(mockDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockDocument.getNumberOfPages()).thenReturn(5);
|
|
||||||
when(mockDocument.getPage(0)).thenReturn(mockPage1); // For negative page number
|
|
||||||
when(mockDocument.getPage(4)).thenReturn(mockPage2); // For page number exceeding bounds
|
|
||||||
|
|
||||||
doAnswer(invocation -> {
|
|
||||||
ByteArrayOutputStream baos = invocation.getArgument(0);
|
|
||||||
baos.write("mocked pdf content".getBytes());
|
|
||||||
return null;
|
|
||||||
}).when(mockDocument).save(any(ByteArrayOutputStream.class));
|
|
||||||
|
|
||||||
// When
|
|
||||||
ResponseEntity<byte[]> result = editTableOfContentsController.editTableOfContents(request);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
verify(mockDocument).getPage(0); // Clamped to first page
|
|
||||||
verify(mockDocument).getPage(4); // Clamped to last page
|
|
||||||
verify(mockDocument).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testCreateOutlineItem_ValidPageNumber_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
BookmarkItem bookmark = new BookmarkItem();
|
|
||||||
bookmark.setTitle("Test Chapter");
|
|
||||||
bookmark.setPageNumber(3);
|
|
||||||
|
|
||||||
when(mockDocument.getNumberOfPages()).thenReturn(5);
|
|
||||||
when(mockDocument.getPage(2)).thenReturn(mockPage1); // 0-indexed
|
|
||||||
|
|
||||||
// When
|
|
||||||
Method createOutlineItemMethod = EditTableOfContentsController.class.getDeclaredMethod("createOutlineItem", PDDocument.class, BookmarkItem.class);
|
|
||||||
createOutlineItemMethod.setAccessible(true);
|
|
||||||
PDOutlineItem result = (PDOutlineItem) createOutlineItemMethod.invoke(editTableOfContentsController, mockDocument, bookmark);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
verify(mockDocument).getPage(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testBookmarkItem_GettersAndSetters() {
|
|
||||||
// Given
|
|
||||||
BookmarkItem bookmark = new BookmarkItem();
|
|
||||||
List<BookmarkItem> children = new ArrayList<>();
|
|
||||||
|
|
||||||
// When
|
|
||||||
bookmark.setTitle("Test Title");
|
|
||||||
bookmark.setPageNumber(5);
|
|
||||||
bookmark.setChildren(children);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertEquals("Test Title", bookmark.getTitle());
|
|
||||||
assertEquals(5, bookmark.getPageNumber());
|
|
||||||
assertEquals(children, bookmark.getChildren());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testEditTableOfContents_IOExceptionDuringLoad_ThrowsException() throws Exception {
|
|
||||||
// Given
|
|
||||||
EditTableOfContentsRequest request = new EditTableOfContentsRequest();
|
|
||||||
request.setFileInput(mockFile);
|
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenThrow(new RuntimeException("Failed to load PDF"));
|
|
||||||
|
|
||||||
// When & Then
|
|
||||||
assertThrows(RuntimeException.class, () -> editTableOfContentsController.editTableOfContents(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testExtractBookmarks_IOExceptionDuringLoad_ThrowsException() throws Exception {
|
|
||||||
// Given
|
|
||||||
when(pdfDocumentFactory.load(mockFile)).thenThrow(new RuntimeException("Failed to load PDF"));
|
|
||||||
|
|
||||||
// When & Then
|
|
||||||
assertThrows(RuntimeException.class, () -> editTableOfContentsController.extractBookmarks(mockFile));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,279 +0,0 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import static org.mockito.ArgumentMatchers.*;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDPage;
|
|
||||||
import org.apache.pdfbox.pdmodel.PDPageTree;
|
|
||||||
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.InjectMocks;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
|
||||||
import org.springframework.mock.web.MockMultipartFile;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
|
||||||
class MergeControllerTest {
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private CustomPDFDocumentFactory pdfDocumentFactory;
|
|
||||||
|
|
||||||
@InjectMocks
|
|
||||||
private MergeController mergeController;
|
|
||||||
|
|
||||||
private MockMultipartFile mockFile1;
|
|
||||||
private MockMultipartFile mockFile2;
|
|
||||||
private MockMultipartFile mockFile3;
|
|
||||||
private PDDocument mockDocument;
|
|
||||||
private PDDocument mockMergedDocument;
|
|
||||||
private PDDocumentCatalog mockCatalog;
|
|
||||||
private PDPageTree mockPages;
|
|
||||||
private PDPage mockPage1;
|
|
||||||
private PDPage mockPage2;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
mockFile1 = new MockMultipartFile("file1", "document1.pdf", "application/pdf", "PDF content 1".getBytes());
|
|
||||||
mockFile2 = new MockMultipartFile("file2", "document2.pdf", "application/pdf", "PDF content 2".getBytes());
|
|
||||||
mockFile3 = new MockMultipartFile("file3", "chapter3.pdf", "application/pdf", "PDF content 3".getBytes());
|
|
||||||
|
|
||||||
mockDocument = mock(PDDocument.class);
|
|
||||||
mockMergedDocument = mock(PDDocument.class);
|
|
||||||
mockCatalog = mock(PDDocumentCatalog.class);
|
|
||||||
mockPages = mock(PDPageTree.class);
|
|
||||||
mockPage1 = mock(PDPage.class);
|
|
||||||
mockPage2 = mock(PDPage.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testAddTableOfContents_WithMultipleFiles_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
MultipartFile[] files = {mockFile1, mockFile2, mockFile3};
|
|
||||||
|
|
||||||
// Mock the merged document setup
|
|
||||||
when(mockMergedDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockMergedDocument.getNumberOfPages()).thenReturn(6);
|
|
||||||
when(mockMergedDocument.getPage(0)).thenReturn(mockPage1);
|
|
||||||
when(mockMergedDocument.getPage(2)).thenReturn(mockPage2);
|
|
||||||
when(mockMergedDocument.getPage(4)).thenReturn(mockPage1);
|
|
||||||
|
|
||||||
// Mock individual document loading for page count
|
|
||||||
PDDocument doc1 = mock(PDDocument.class);
|
|
||||||
PDDocument doc2 = mock(PDDocument.class);
|
|
||||||
PDDocument doc3 = mock(PDDocument.class);
|
|
||||||
|
|
||||||
when(pdfDocumentFactory.load(mockFile1)).thenReturn(doc1);
|
|
||||||
when(pdfDocumentFactory.load(mockFile2)).thenReturn(doc2);
|
|
||||||
when(pdfDocumentFactory.load(mockFile3)).thenReturn(doc3);
|
|
||||||
|
|
||||||
when(doc1.getNumberOfPages()).thenReturn(2);
|
|
||||||
when(doc2.getNumberOfPages()).thenReturn(2);
|
|
||||||
when(doc3.getNumberOfPages()).thenReturn(2);
|
|
||||||
|
|
||||||
// When
|
|
||||||
Method addTableOfContentsMethod = MergeController.class.getDeclaredMethod("addTableOfContents", PDDocument.class, MultipartFile[].class);
|
|
||||||
addTableOfContentsMethod.setAccessible(true);
|
|
||||||
addTableOfContentsMethod.invoke(mergeController, mockMergedDocument, files);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
ArgumentCaptor<PDDocumentOutline> outlineCaptor = ArgumentCaptor.forClass(PDDocumentOutline.class);
|
|
||||||
verify(mockCatalog).setDocumentOutline(outlineCaptor.capture());
|
|
||||||
|
|
||||||
PDDocumentOutline capturedOutline = outlineCaptor.getValue();
|
|
||||||
assertNotNull(capturedOutline);
|
|
||||||
|
|
||||||
// Verify that documents were loaded for page count
|
|
||||||
verify(pdfDocumentFactory).load(mockFile1);
|
|
||||||
verify(pdfDocumentFactory).load(mockFile2);
|
|
||||||
verify(pdfDocumentFactory).load(mockFile3);
|
|
||||||
|
|
||||||
// Verify document closing
|
|
||||||
verify(doc1).close();
|
|
||||||
verify(doc2).close();
|
|
||||||
verify(doc3).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testAddTableOfContents_WithSingleFile_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
MultipartFile[] files = {mockFile1};
|
|
||||||
|
|
||||||
when(mockMergedDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockMergedDocument.getNumberOfPages()).thenReturn(3);
|
|
||||||
when(mockMergedDocument.getPage(0)).thenReturn(mockPage1);
|
|
||||||
|
|
||||||
PDDocument doc1 = mock(PDDocument.class);
|
|
||||||
when(pdfDocumentFactory.load(mockFile1)).thenReturn(doc1);
|
|
||||||
when(doc1.getNumberOfPages()).thenReturn(3);
|
|
||||||
|
|
||||||
// When
|
|
||||||
Method addTableOfContentsMethod = MergeController.class.getDeclaredMethod("addTableOfContents", PDDocument.class, MultipartFile[].class);
|
|
||||||
addTableOfContentsMethod.setAccessible(true);
|
|
||||||
addTableOfContentsMethod.invoke(mergeController, mockMergedDocument, files);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(mockCatalog).setDocumentOutline(any(PDDocumentOutline.class));
|
|
||||||
verify(pdfDocumentFactory).load(mockFile1);
|
|
||||||
verify(doc1).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testAddTableOfContents_WithEmptyArray_Success() throws Exception {
|
|
||||||
// Given
|
|
||||||
MultipartFile[] files = {};
|
|
||||||
when(mockMergedDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
|
|
||||||
// When
|
|
||||||
Method addTableOfContentsMethod = MergeController.class.getDeclaredMethod("addTableOfContents", PDDocument.class, MultipartFile[].class);
|
|
||||||
addTableOfContentsMethod.setAccessible(true);
|
|
||||||
addTableOfContentsMethod.invoke(mergeController, mockMergedDocument, files);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(mockMergedDocument).getDocumentCatalog();
|
|
||||||
verify(mockCatalog).setDocumentOutline(any(PDDocumentOutline.class));
|
|
||||||
verifyNoInteractions(pdfDocumentFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testAddTableOfContents_WithIOException_HandlesGracefully() throws Exception {
|
|
||||||
// Given
|
|
||||||
MultipartFile[] files = {mockFile1, mockFile2};
|
|
||||||
|
|
||||||
when(mockMergedDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockMergedDocument.getNumberOfPages()).thenReturn(4);
|
|
||||||
when(mockMergedDocument.getPage(anyInt())).thenReturn(mockPage1); // Use anyInt() to avoid stubbing conflicts
|
|
||||||
|
|
||||||
// First document loads successfully
|
|
||||||
PDDocument doc1 = mock(PDDocument.class);
|
|
||||||
when(pdfDocumentFactory.load(mockFile1)).thenReturn(doc1);
|
|
||||||
when(doc1.getNumberOfPages()).thenReturn(2);
|
|
||||||
|
|
||||||
// Second document throws IOException
|
|
||||||
when(pdfDocumentFactory.load(mockFile2)).thenThrow(new IOException("Failed to load document"));
|
|
||||||
|
|
||||||
// When
|
|
||||||
Method addTableOfContentsMethod = MergeController.class.getDeclaredMethod("addTableOfContents", PDDocument.class, MultipartFile[].class);
|
|
||||||
addTableOfContentsMethod.setAccessible(true);
|
|
||||||
|
|
||||||
// Should not throw exception
|
|
||||||
assertDoesNotThrow(() ->
|
|
||||||
addTableOfContentsMethod.invoke(mergeController, mockMergedDocument, files)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(mockCatalog).setDocumentOutline(any(PDDocumentOutline.class));
|
|
||||||
verify(pdfDocumentFactory).load(mockFile1);
|
|
||||||
verify(pdfDocumentFactory).load(mockFile2);
|
|
||||||
verify(doc1).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testAddTableOfContents_FilenameWithoutExtension_UsesFullName() throws Exception {
|
|
||||||
// Given
|
|
||||||
MockMultipartFile fileWithoutExtension = new MockMultipartFile("file", "document_no_ext", "application/pdf", "PDF content".getBytes());
|
|
||||||
MultipartFile[] files = {fileWithoutExtension};
|
|
||||||
|
|
||||||
when(mockMergedDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockMergedDocument.getNumberOfPages()).thenReturn(1);
|
|
||||||
when(mockMergedDocument.getPage(0)).thenReturn(mockPage1);
|
|
||||||
|
|
||||||
PDDocument doc = mock(PDDocument.class);
|
|
||||||
when(pdfDocumentFactory.load(fileWithoutExtension)).thenReturn(doc);
|
|
||||||
when(doc.getNumberOfPages()).thenReturn(1);
|
|
||||||
|
|
||||||
// When
|
|
||||||
Method addTableOfContentsMethod = MergeController.class.getDeclaredMethod("addTableOfContents", PDDocument.class, MultipartFile[].class);
|
|
||||||
addTableOfContentsMethod.setAccessible(true);
|
|
||||||
addTableOfContentsMethod.invoke(mergeController, mockMergedDocument, files);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(mockCatalog).setDocumentOutline(any(PDDocumentOutline.class));
|
|
||||||
verify(doc).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testAddTableOfContents_PageIndexExceedsDocumentPages_HandlesGracefully() throws Exception {
|
|
||||||
// Given
|
|
||||||
MultipartFile[] files = {mockFile1};
|
|
||||||
|
|
||||||
when(mockMergedDocument.getDocumentCatalog()).thenReturn(mockCatalog);
|
|
||||||
when(mockMergedDocument.getNumberOfPages()).thenReturn(0); // No pages in merged document
|
|
||||||
|
|
||||||
PDDocument doc1 = mock(PDDocument.class);
|
|
||||||
when(pdfDocumentFactory.load(mockFile1)).thenReturn(doc1);
|
|
||||||
when(doc1.getNumberOfPages()).thenReturn(3);
|
|
||||||
|
|
||||||
// When
|
|
||||||
Method addTableOfContentsMethod = MergeController.class.getDeclaredMethod("addTableOfContents", PDDocument.class, MultipartFile[].class);
|
|
||||||
addTableOfContentsMethod.setAccessible(true);
|
|
||||||
|
|
||||||
// Should not throw exception
|
|
||||||
assertDoesNotThrow(() ->
|
|
||||||
addTableOfContentsMethod.invoke(mergeController, mockMergedDocument, files)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
verify(mockCatalog).setDocumentOutline(any(PDDocumentOutline.class));
|
|
||||||
verify(mockMergedDocument, never()).getPage(anyInt());
|
|
||||||
verify(doc1).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testMergeDocuments_Success() throws IOException {
|
|
||||||
// Given
|
|
||||||
PDDocument doc1 = mock(PDDocument.class);
|
|
||||||
PDDocument doc2 = mock(PDDocument.class);
|
|
||||||
List<PDDocument> documents = Arrays.asList(doc1, doc2);
|
|
||||||
|
|
||||||
PDPageTree pages1 = mock(PDPageTree.class);
|
|
||||||
PDPageTree pages2 = mock(PDPageTree.class);
|
|
||||||
PDPage page1 = mock(PDPage.class);
|
|
||||||
PDPage page2 = mock(PDPage.class);
|
|
||||||
|
|
||||||
when(pdfDocumentFactory.createNewDocument()).thenReturn(mockMergedDocument);
|
|
||||||
when(doc1.getPages()).thenReturn(pages1);
|
|
||||||
when(doc2.getPages()).thenReturn(pages2);
|
|
||||||
when(pages1.iterator()).thenReturn(Arrays.asList(page1).iterator());
|
|
||||||
when(pages2.iterator()).thenReturn(Arrays.asList(page2).iterator());
|
|
||||||
|
|
||||||
// When
|
|
||||||
PDDocument result = mergeController.mergeDocuments(documents);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
assertEquals(mockMergedDocument, result);
|
|
||||||
verify(mockMergedDocument).addPage(page1);
|
|
||||||
verify(mockMergedDocument).addPage(page2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testMergeDocuments_EmptyList_ReturnsEmptyDocument() throws IOException {
|
|
||||||
// Given
|
|
||||||
List<PDDocument> documents = Arrays.asList();
|
|
||||||
|
|
||||||
when(pdfDocumentFactory.createNewDocument()).thenReturn(mockMergedDocument);
|
|
||||||
|
|
||||||
// When
|
|
||||||
PDDocument result = mergeController.mergeDocuments(documents);
|
|
||||||
|
|
||||||
// Then
|
|
||||||
assertNotNull(result);
|
|
||||||
assertEquals(mockMergedDocument, result);
|
|
||||||
verify(mockMergedDocument, never()).addPage(any(PDPage.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user