Improve Type-Safe Casting with Pattern Matching (#2990)

# Description of Changes

Please provide a summary of the changes, including:

This PR refactors multiple instances of type casting throughout the
codebase by replacing them with Java's pattern matching for
`instanceof`. This approach eliminates redundant type casting, improves
code readability, and reduces the chances of `ClassCastException`. The
changes primarily affect authentication handling, PDF processing, and
certificate validation.

### Key Changes:
- Replaced traditional `instanceof` checks followed by explicit casting
with pattern matching.
- Improved readability and maintainability of type-related operations.
- Applied changes across security modules, PDF utilities, and image
processing functions.

This refactor does not introduce new functionality but enhances the
robustness and clarity of the existing code.

pending until #2818 is published

---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing)
for more details.
This commit is contained in:
Ludy
2025-02-25 21:31:50 +00:00
committed by GitHub
parent a1f7bb3e4a
commit 2ab951e080
27 changed files with 175 additions and 165 deletions
@@ -129,9 +129,9 @@ public class CertSignController {
@Operation(
summary = "Sign PDF with a Digital Certificate",
description =
"This endpoint accepts a PDF file, a digital certificate and related information to sign"
+ " the PDF. It then returns the digitally signed PDF file. Input:PDF Output:PDF"
+ " Type:SISO")
"This endpoint accepts a PDF file, a digital certificate and related"
+ " information to sign the PDF. It then returns the digitally signed PDF"
+ " file. Input:PDF Output:PDF Type:SISO")
public ResponseEntity<byte[]> signPDFWithCert(@ModelAttribute SignPDFWithCertRequest request)
throws Exception {
MultipartFile pdf = request.getFileInput();
@@ -201,17 +201,14 @@ public class CertSignController {
Object pemObject = pemParser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
PrivateKeyInfo pkInfo;
if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo pkcs8EncryptedPrivateKeyInfo) {
InputDecryptorProvider decProv =
new JceOpenSSLPKCS8DecryptorProviderBuilder().build(password.toCharArray());
pkInfo = ((PKCS8EncryptedPrivateKeyInfo) pemObject).decryptPrivateKeyInfo(decProv);
} else if (pemObject instanceof PEMEncryptedKeyPair) {
pkInfo = pkcs8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(decProv);
} else if (pemObject instanceof PEMEncryptedKeyPair pemEncryptedKeyPair) {
PEMDecryptorProvider decProv =
new JcePEMDecryptorProviderBuilder().build(password.toCharArray());
pkInfo =
((PEMEncryptedKeyPair) pemObject)
.decryptKeyPair(decProv)
.getPrivateKeyInfo();
pkInfo = pemEncryptedKeyPair.decryptKeyPair(decProv).getPrivateKeyInfo();
} else {
pkInfo = ((PEMKeyPair) pemObject).getPrivateKeyInfo();
}
@@ -214,10 +214,7 @@ public class GetInfoOnPDF {
ArrayNode attachmentsArray = objectMapper.createArrayNode();
for (PDPage page : pdfBoxDoc.getPages()) {
for (PDAnnotation annotation : page.getAnnotations()) {
if (annotation instanceof PDAnnotationFileAttachment) {
PDAnnotationFileAttachment fileAttachmentAnnotation =
(PDAnnotationFileAttachment) annotation;
if (annotation instanceof PDAnnotationFileAttachment fileAttachmentAnnotation) {
ObjectNode attachmentNode = objectMapper.createObjectNode();
attachmentNode.put("Name", fileAttachmentAnnotation.getAttachmentName());
attachmentNode.put("Description", fileAttachmentAnnotation.getContents());
@@ -437,9 +434,7 @@ public class GetInfoOnPDF {
for (COSName name : resources.getXObjectNames()) {
PDXObject xObject = resources.getXObject(name);
if (xObject instanceof PDImageXObject) {
PDImageXObject image = (PDImageXObject) xObject;
if (xObject instanceof PDImageXObject image) {
ObjectNode imageNode = objectMapper.createObjectNode();
imageNode.put("Width", image.getWidth());
imageNode.put("Height", image.getHeight());
@@ -462,10 +457,8 @@ public class GetInfoOnPDF {
Set<String> uniqueURIs = new HashSet<>(); // To store unique URIs
for (PDAnnotation annotation : annotations) {
if (annotation instanceof PDAnnotationLink) {
PDAnnotationLink linkAnnotation = (PDAnnotationLink) annotation;
if (linkAnnotation.getAction() instanceof PDActionURI) {
PDActionURI uriAction = (PDActionURI) linkAnnotation.getAction();
if (annotation instanceof PDAnnotationLink linkAnnotation) {
if (linkAnnotation.getAction() instanceof PDActionURI uriAction) {
String uri = uriAction.getURI();
uniqueURIs.add(uri); // Add to set to ensure uniqueness
}
@@ -541,8 +534,7 @@ public class GetInfoOnPDF {
Iterable<COSName> colorSpaceNames = resources.getColorSpaceNames();
for (COSName name : colorSpaceNames) {
PDColorSpace colorSpace = resources.getColorSpace(name);
if (colorSpace instanceof PDICCBased) {
PDICCBased iccBased = (PDICCBased) colorSpace;
if (colorSpace instanceof PDICCBased iccBased) {
PDStream iccData = iccBased.getPDStream();
byte[] iccBytes = iccData.toByteArray();
@@ -698,12 +690,10 @@ public class GetInfoOnPDF {
ArrayNode elementsArray = objectMapper.createArrayNode();
if (nodes != null) {
for (Object obj : nodes) {
if (obj instanceof PDStructureNode) {
PDStructureNode node = (PDStructureNode) obj;
if (obj instanceof PDStructureNode node) {
ObjectNode elementNode = objectMapper.createObjectNode();
if (node instanceof PDStructureElement) {
PDStructureElement structureElement = (PDStructureElement) node;
if (node instanceof PDStructureElement structureElement) {
elementNode.put("Type", structureElement.getStructureType());
elementNode.put("Content", getContent(structureElement));
@@ -724,8 +714,7 @@ public class GetInfoOnPDF {
StringBuilder contentBuilder = new StringBuilder();
for (Object item : structureElement.getKids()) {
if (item instanceof COSString) {
COSString cosString = (COSString) item;
if (item instanceof COSString cosString) {
contentBuilder.append(cosString.getString());
} else if (item instanceof PDStructureElement) {
// For simplicity, we're handling only COSString and PDStructureElement here
@@ -44,7 +44,8 @@ public class SanitizeController {
@Operation(
summary = "Sanitize a PDF file",
description =
"This endpoint processes a PDF file and removes specific elements based on the provided options. Input:PDF Output:PDF Type:SISO")
"This endpoint processes a PDF file and removes specific elements based on the"
+ " provided options. Input:PDF Output:PDF Type:SISO")
public ResponseEntity<byte[]> sanitizePDF(@ModelAttribute SanitizePdfRequest request)
throws IOException {
MultipartFile inputFile = request.getFileInput();
@@ -103,8 +104,7 @@ public class SanitizeController {
for (PDPage page : document.getPages()) {
for (PDAnnotation annotation : page.getAnnotations()) {
if (annotation instanceof PDAnnotationWidget) {
PDAnnotationWidget widget = (PDAnnotationWidget) annotation;
if (annotation instanceof PDAnnotationWidget widget) {
PDAction action = widget.getAction();
if (action instanceof PDActionJavaScript) {
widget.setAction(null);
@@ -157,12 +157,12 @@ public class SanitizeController {
private void sanitizeLinks(PDDocument document) throws IOException {
for (PDPage page : document.getPages()) {
for (PDAnnotation annotation : page.getAnnotations()) {
if (annotation != null && annotation instanceof PDAnnotationLink) {
PDAction action = ((PDAnnotationLink) annotation).getAction();
if (annotation != null && annotation instanceof PDAnnotationLink linkAnnotation) {
PDAction action = linkAnnotation.getAction();
if (action != null
&& (action instanceof PDActionLaunch
|| action instanceof PDActionURI)) {
((PDAnnotationLink) annotation).setAction(null);
linkAnnotation.setAction(null);
}
}
}