Skip to content

Commit 01d4b5d

Browse files
committed
XCOMMONS-2387: Exception when saving status because file path too long
1 parent bc70b68 commit 01d4b5d

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

xwiki-commons-core/xwiki-commons-job/xwiki-commons-job-default/src/main/java/org/xwiki/job/internal/DefaultJobStatusStore.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import javax.inject.Inject;
3636
import javax.inject.Singleton;
3737

38+
import org.apache.commons.codec.binary.Base64;
3839
import org.apache.commons.configuration2.PropertiesConfiguration;
3940
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
4041
import org.apache.commons.configuration2.builder.fluent.Parameters;
@@ -343,8 +344,20 @@ private File getJobFolder(List<String> id)
343344
File folder = this.configuration.getStorage();
344345

345346
if (id != null) {
346-
for (String idElement : id) {
347-
folder = new File(folder, encode(idElement));
347+
// Create a different folder for each element
348+
for (String fullIdElement : id) {
349+
// But cut each element is it's bigger than 255 bytes (and not characters) since it's a very common
350+
// limit for a single element of the path among file systems
351+
// To be sure to deal with characters not taking more than 1 byte, we start by encoding it in base 64
352+
String encodedIdElement = Base64.encodeBase64String(fullIdElement.getBytes());
353+
if (encodedIdElement.length() > 255) {
354+
do {
355+
folder = new File(folder, encode(encodedIdElement.substring(0, 255)));
356+
encodedIdElement = encodedIdElement.substring(255);
357+
} while (encodedIdElement.length() > 255);
358+
} else {
359+
folder = new File(folder, encode(encodedIdElement));
360+
}
348361
}
349362
}
350363

xwiki-commons-core/xwiki-commons-job/xwiki-commons-job-default/src/test/java/org/xwiki/job/internal/DefaultJobStatusStoreTest.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626

2727
import javax.inject.Provider;
2828

29+
import org.apache.commons.codec.binary.Base64;
2930
import org.apache.commons.io.FileUtils;
31+
import org.apache.commons.lang3.StringUtils;
3032
import org.junit.jupiter.api.Test;
3133
import org.mockito.invocation.InvocationOnMock;
3234
import org.mockito.stubbing.Answer;
@@ -396,6 +398,17 @@ void storeJobStatusWithNullId()
396398
this.store.store(jobStatus);
397399
}
398400

401+
@Test
402+
void storeJobStatusWithBigId()
403+
{
404+
DefaultRequest request = new DefaultRequest();
405+
request.setId(StringUtils.repeat('a', 768));
406+
407+
JobStatus jobStatus = new DefaultJobStatus("type", request, null, null, null);
408+
409+
this.store.store(jobStatus);
410+
}
411+
399412
@Test
400413
void storeUnserializableJobStatus()
401414
{
@@ -442,7 +455,8 @@ void storeJobStatusWhenSerializable()
442455

443456
// Verify that the status has been serialized, indirectly verifying that isSerializable() has been called and
444457
// returned true.
445-
assertTrue(new File(this.storeDirectory, "newstatus/status.xml.zip").exists());
458+
assertTrue(new File(this.storeDirectory, Base64.encodeBase64String(id.get(0).getBytes()) + "/status.xml.zip")
459+
.exists());
446460
}
447461

448462
@Test

0 commit comments

Comments
 (0)