This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.settings-1.3.2 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-settings.git
commit dac34661c10f8a01a2a0347f7dc0bdceef95752d Author: Carsten Ziegeler <[email protected]> AuthorDate: Tue Jul 8 14:28:35 2014 +0000 SLING-3737 : Instance Sling Identifier may be randomly reset on restart. Apply patch from Timothee Maret git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/settings@1608798 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 12 ++ .../settings/impl/SlingSettingsServiceImpl.java | 59 ++++---- .../impl/SlingSettingsServiceImplTest.java | 156 +++++++++++++++++++++ 3 files changed, 199 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 349146e..2a767db 100644 --- a/pom.xml +++ b/pom.xml @@ -117,5 +117,17 @@ <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.4</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.8.2</version> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java b/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java index 5fadb1e..1281495 100644 --- a/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java +++ b/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java @@ -18,6 +18,8 @@ */ package org.apache.sling.settings.impl; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -77,6 +79,9 @@ public class SlingSettingsServiceImpl /** The name of the data file holding install run mode options */ private static final String OPTIONS_FILE = "sling.options.file"; + /** The length in bytes of a sling identifier */ + private static final int SLING_ID_LENGTH = 36; + /** The properties for name, description. */ private final Map<String, String> slingProps = new HashMap<String, String>(); @@ -124,7 +129,7 @@ public class SlingSettingsServiceImpl // the osgi framework does not support storing something in the file system throw new RuntimeException("Unable to read from bundle data file."); } - this.slingId = this.readSlingId(idFile); + this.slingId = this.readSlingId(idFile, SLING_ID_LENGTH); // no sling id yet or failure to read file: create an id and store if (slingId == null) { @@ -147,7 +152,7 @@ public class SlingSettingsServiceImpl } } - private static final class Options implements Serializable { + static final class Options implements Serializable { private static final long serialVersionUID = 1L; String[] modes; String selected; @@ -263,7 +268,7 @@ public class SlingSettingsServiceImpl return optionsList; } - private void writeOptions(final BundleContext context, final List<Options> optionsList) { + void writeOptions(final BundleContext context, final List<Options> optionsList) { final File file = context.getDataFile(OPTIONS_FILE); FileOutputStream fos = null; ObjectOutputStream oos = null; @@ -286,30 +291,28 @@ public class SlingSettingsServiceImpl /** * Read the id from a file. */ - private String readSlingId(final File idFile) { - if (idFile.exists() && idFile.length() >= 36) { - FileInputStream fin = null; + String readSlingId(final File idFile, int maxLength) { + if (idFile.exists() && idFile.length() >= maxLength) { + DataInputStream dis = null; try { - fin = new FileInputStream(idFile); - final byte[] rawBytes = new byte[36]; - if (fin.read(rawBytes) == 36) { - final String rawString = new String(rawBytes, "ISO-8859-1"); + final byte[] rawBytes = new byte[maxLength]; + dis = new DataInputStream(new FileInputStream(idFile)); + dis.readFully(rawBytes); + final String rawString = new String(rawBytes, "ISO-8859-1"); - // roundtrip to ensure correct format of UUID value - final String id = UUID.fromString(rawString).toString(); - logger.debug("Got Sling ID {} from file {}", id, idFile); + // roundtrip to ensure correct format of UUID value + final String id = UUID.fromString(rawString).toString(); + logger.debug("Got Sling ID {} from file {}", id, idFile); - return id; - } + return id; } catch (final Throwable t) { logger.error("Failed reading UUID from id file " + idFile + ", creating new id", t); } finally { - if (fin != null) { + if (dis != null) { try { - fin.close(); - } catch (IOException ignore) { - } + dis.close(); + } catch (IOException ignore){} } } } @@ -319,22 +322,22 @@ public class SlingSettingsServiceImpl /** * Write the sling id file. */ - private void writeSlingId(final File idFile, final String id) { + void writeSlingId(final File idFile, final String id) { idFile.delete(); idFile.getParentFile().mkdirs(); - FileOutputStream fout = null; + DataOutputStream dos = null; try { - fout = new FileOutputStream(idFile); - fout.write(slingId.getBytes("ISO-8859-1")); - fout.flush(); + final byte[] rawBytes = id.getBytes("ISO-8859-1"); + dos = new DataOutputStream(new FileOutputStream(idFile)); + dos.write(rawBytes, 0, rawBytes.length); + dos.flush(); } catch (final Throwable t) { logger.error("Failed writing UUID to id file " + idFile, t); } finally { - if (fout != null) { + if (dos != null) { try { - fout.close(); - } catch (IOException ignore) { - } + dos.close(); + } catch (IOException ignore) {} } } } diff --git a/src/test/java/org/apache/sling/settings/impl/SlingSettingsServiceImplTest.java b/src/test/java/org/apache/sling/settings/impl/SlingSettingsServiceImplTest.java new file mode 100644 index 0000000..81e3dd1 --- /dev/null +++ b/src/test/java/org/apache/sling/settings/impl/SlingSettingsServiceImplTest.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sling.settings.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.RandomStringUtils; +import org.junit.After; +import org.junit.Assert; +import org.apache.sling.launchpad.api.StartupHandler; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.osgi.framework.BundleContext; + +public class SlingSettingsServiceImplTest { + + private static final String SLING_ID_FILE_NAME = "sling.id.file"; + + private static final String OPTIONS_FILE_NAME = "sling.options.file"; + + private static final String SLING_ID = "097bae9b-bf60-45a2-ad8c-ccdd374dd9b0"; + + private File slingIdFile = null; + + private File optionsFile = null; + + @Before + public void before() throws IOException { + slingIdFile = File.createTempFile( + SLING_ID_FILE_NAME, ""); + optionsFile = File.createTempFile( + OPTIONS_FILE_NAME, ""); + } + + @After + public void after() throws IOException { + if (slingIdFile != null ) { + slingIdFile.delete(); + slingIdFile = null; + } + if (optionsFile != null) { + optionsFile.delete(); + optionsFile = null; + } + } + + @Test + public void testGenerateSlingId() + throws IOException { + String slingId = readSlingId(slingIdFile, optionsFile, SLING_ID.length()); + Assert.assertNotNull(slingId); + } + + @Test + public void testGetSlingId() + throws IOException { + writeSlingId(slingIdFile, optionsFile, SLING_ID); + String generated = readSlingId(slingIdFile, optionsFile, SLING_ID.length()); + Assert.assertNotNull(generated); + Assert.assertEquals(SLING_ID, generated); + String slingId = readSlingId(slingIdFile, optionsFile, SLING_ID.length()); + Assert.assertNotNull(slingId); + Assert.assertEquals(generated, slingId); + } + + @Test + public void testGetLongSlingIdFromTooLargeData() + throws IOException { + String data = SLING_ID + RandomStringUtils.randomAscii(1024 * 1024); // 1MB long random String + writeSlingId(slingIdFile, optionsFile, data); + String slingId = readSlingId(slingIdFile, optionsFile, SLING_ID.length()); + Assert.assertNotNull(slingId); + Assert.assertEquals(SLING_ID, slingId); + } + + @Test + public void testGetSlingIdFromTooShortData() + throws IOException { + String data = RandomStringUtils.randomAscii(8); // 8 byte long string + writeSlingId(slingIdFile, optionsFile, data); + String slingId = readSlingId(slingIdFile, optionsFile, SLING_ID.length()); + Assert.assertNotNull(slingId); + Assert.assertNotEquals(SLING_ID, slingId); + } + + private String readSlingId(File slingIdFile, File optionsFile, int maxLength) + throws IOException { + SlingSettingsServiceImpl settings = getSlingSettings(slingIdFile, optionsFile); + return settings.readSlingId(slingIdFile, maxLength); + } + + private void writeSlingId(File slingIdFile, File optionsFile, String slingId) + throws IOException { + SlingSettingsServiceImpl settings = getSlingSettings(slingIdFile, optionsFile); + settings.writeSlingId(slingIdFile, slingId); + } + + private SlingSettingsServiceImpl getSlingSettings(File slingIdFile, File optionsFile) + throws IOException { + BundleContext context = Mockito.mock(BundleContext.class); + Mockito.when(context.getDataFile(SLING_ID_FILE_NAME)) + .thenReturn(slingIdFile); + Mockito.when(context.getDataFile(OPTIONS_FILE_NAME)) + .thenReturn(optionsFile); + StartupHandler handler = Mockito.mock(StartupHandler.class); + // write options + List<SlingSettingsServiceImpl.Options> options = new ArrayList<SlingSettingsServiceImpl.Options>(); + FileOutputStream fos = null; + ObjectOutputStream oos = null; + try { + fos = new FileOutputStream(optionsFile); + oos = new ObjectOutputStream(fos); + oos.writeObject(options); + } catch ( final IOException ioe ) { + throw new RuntimeException("Unable to write to options data file.", ioe); + } finally { + if ( oos != null ) { + try { + oos.close(); + } catch (IOException ignore) { + // ... + } + } + if ( fos != null ) { + try { + fos.close(); + } catch (IOException ignore) { + // ... + } + } + } + return new SlingSettingsServiceImpl(context, handler); + } +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
