This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.settings-1.2.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-settings.git
commit 11b3f5c00c7691c6b2c674b6e27b719518f09d5a Author: Carsten Ziegeler <[email protected]> AuthorDate: Wed Nov 14 15:56:51 2012 +0000 SLING-2662 : Enhance run mode handling git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/settings@1409238 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 2 +- .../sling/settings/SlingSettingsService.java | 16 +++ .../settings/impl/SlingSettingsServiceImpl.java | 141 ++++++++++++++++++-- .../sling/settings/impl/RunModeImplTest.java | 146 +++++++++++++++++++-- 4 files changed, 278 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index 3692eb1..ac89c2c 100644 --- a/pom.xml +++ b/pom.xml @@ -65,7 +65,7 @@ http://sling.apache.org/site/sling-settings-orgapacheslingsettings.html </Bundle-DocURL> <Export-Package> - org.apache.sling.settings;version=1.1.0 + org.apache.sling.settings;version=1.2.0 </Export-Package> <Private-Package> org.apache.sling.settings.impl diff --git a/src/main/java/org/apache/sling/settings/SlingSettingsService.java b/src/main/java/org/apache/sling/settings/SlingSettingsService.java index cd5e175..935400b 100644 --- a/src/main/java/org/apache/sling/settings/SlingSettingsService.java +++ b/src/main/java/org/apache/sling/settings/SlingSettingsService.java @@ -68,6 +68,22 @@ public interface SlingSettingsService { String RUN_MODES_PROPERTY = "sling.run.modes"; /** + * The name of the framework property defining the list + * of run mode options + * The value is a comma separated list of options where each option + * contains of a set of run modes separated by a | character. + */ + String RUN_MODE_OPTIONS = "sling.run.mode.options"; + + /** + * The name of the framework property defining the list + * of run mode options for installation time. + * The value is a comma separated list of options where each option + * contains of a set of run modes separated by a | character. + */ + String RUN_MODE_INSTALL_OPTIONS = "sling.run.mode.install.options"; + + /** * Utility method to generate an absolute path * within Sling Home. * 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 358b588..89c2588 100644 --- a/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java +++ b/src/main/java/org/apache/sling/settings/impl/SlingSettingsServiceImpl.java @@ -22,10 +22,15 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -57,6 +62,9 @@ public class SlingSettingsServiceImpl /** The name of the data file holding the sling id. */ private static final String DATA_FILE = "sling.id.file"; + /** The name of the data file holding install run mode options */ + private static final String OPTIONS_FILE = "sling.options.file"; + /** * Create the service and search the Sling home urls and * get/create a sling id. @@ -65,8 +73,8 @@ public class SlingSettingsServiceImpl */ public SlingSettingsServiceImpl(final BundleContext context) { this.setupSlingHome(context); - this.setupSlingId(context); - this.setupRunModes(context); + final boolean isInstall = this.setupSlingId(context); + this.setupRunModes(context, isInstall); } @@ -88,7 +96,7 @@ public class SlingSettingsServiceImpl /** * Get / create sling id */ - private void setupSlingId(final BundleContext context) { + private boolean setupSlingId(final BundleContext context) { // try to read the id from the id file first final File idFile = context.getDataFile(DATA_FILE); if ( idFile == null ) { @@ -101,26 +109,131 @@ public class SlingSettingsServiceImpl if (slingId == null) { slingId = UUID.randomUUID().toString(); this.writeSlingId(idFile, this.slingId); + return true; } + return false; + } + + private static final class Options implements Serializable { + private static final long serialVersionUID = 1L; + String[] modes; + String selected; + } + + private List<Options> handleOptions(final Set<String> modesSet, final String propOptions) { + if ( propOptions != null && propOptions.trim().length() > 0 ) { + final List<Options> optionsList = new ArrayList<Options>(); + + final String[] options = propOptions.trim().split("\\|"); + for(final String opt : options) { + String selected = null; + final String[] modes = opt.trim().split(","); + for(int i=0; i<modes.length; i++) { + modes[i] = modes[i].trim(); + if ( selected != null ) { + modesSet.remove(modes[i]); + } else { + if ( modesSet.contains(modes[i]) ) { + selected = modes[i]; + } + } + } + if ( selected == null ) { + selected = modes[0]; + modesSet.add(modes[0]); + } + final Options o = new Options(); + o.selected = selected; + o.modes = modes; + optionsList.add(o); + } + return optionsList; + } + return null; } /** * Set up run modes. */ - private void setupRunModes(final BundleContext context) { + @SuppressWarnings("unchecked") + private void setupRunModes(final BundleContext context, + final boolean isInstall) { + final Set<String> modesSet = new HashSet<String>(); + + // check configuration property first final String prop = context.getProperty(RUN_MODES_PROPERTY); - if (prop == null || prop.trim().length() == 0) { - this.runModes = Collections.emptySet(); - } else { - final Set<String> modesSet = new HashSet<String>(); + if (prop != null && prop.trim().length() > 0) { final String[] modes = prop.split(","); for(int i=0; i < modes.length; i++) { modesSet.add(modes[i].trim()); } - // make the set unmodifiable and synced - // we propably don't need a synced set as it is read only - this.runModes = Collections.synchronizedSet(Collections.unmodifiableSet(modesSet)); - logger.info("Active run modes {}", this.runModes); + } + + // now options + this.handleOptions(modesSet, context.getProperty(RUN_MODE_OPTIONS)); + // now install options + if ( isInstall ) { + final List<Options> optionsList = this.handleOptions(modesSet, context.getProperty(RUN_MODE_INSTALL_OPTIONS)); + if ( optionsList != null ) { + final File file = context.getDataFile(OPTIONS_FILE); + FileOutputStream fos = null; + ObjectOutputStream oos = null; + try { + fos = new FileOutputStream(file); + oos = new ObjectOutputStream(fos); + oos.writeObject(optionsList); + } catch ( final IOException ioe ) { + throw new RuntimeException("Unable to write to options data file.", ioe); + } finally { + if ( oos != null ) { + try { oos.close(); } catch ( final IOException ignore) {} + } + if ( fos != null ) { + try { fos.close(); } catch ( final IOException ignore) {} + } + } + } + } else { + final File file = context.getDataFile(OPTIONS_FILE); + if ( file.exists() ) { + List<Options> optionsList = null; + FileInputStream fis = null; + ObjectInputStream ois = null; + try { + fis = new FileInputStream(file); + ois = new ObjectInputStream(fis); + + optionsList = (List<Options>) ois.readObject(); + } catch ( final IOException ioe ) { + throw new RuntimeException("Unable to read from options data file.", ioe); + } catch (ClassNotFoundException cnfe) { + throw new RuntimeException("Unable to read from options data file.", cnfe); + } finally { + if ( ois != null ) { + try { ois.close(); } catch ( final IOException ignore) {} + } + if ( ois != null ) { + try { ois.close(); } catch ( final IOException ignore) {} + } + } + if ( optionsList != null ) { + for(final Options o : optionsList) { + for(final String m : o.modes) { + modesSet.remove(m); + } + modesSet.add(o.selected); + } + } + } + } + + // make the set unmodifiable and synced + // we probably don't need a synced set as it is read only + this.runModes = Collections.synchronizedSet(Collections.unmodifiableSet(modesSet)); + if ( this.runModes.size() > 0 ) { + logger.info("Active run modes: {}", this.runModes); + } else { + logger.info("No run modes active"); } } @@ -143,7 +256,7 @@ public class SlingSettingsServiceImpl return id; } - } catch (Throwable t) { + } catch (final Throwable t) { logger.error("Failed reading UUID from id file " + idFile + ", creating new id", t); } finally { @@ -169,7 +282,7 @@ public class SlingSettingsServiceImpl fout = new FileOutputStream(idFile); fout.write(slingId.getBytes("ISO-8859-1")); fout.flush(); - } catch (Throwable t) { + } catch (final Throwable t) { logger.error("Failed writing UUID to id file " + idFile, t); } finally { if (fout != null) { diff --git a/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java b/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java index 3235e0b..81a44ae 100644 --- a/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java +++ b/src/test/java/org/apache/sling/settings/impl/RunModeImplTest.java @@ -26,6 +26,8 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Dictionary; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import org.apache.sling.settings.SlingSettingsService; @@ -43,7 +45,7 @@ import org.osgi.framework.ServiceRegistration; public class RunModeImplTest { private void assertParse(String str, String [] expected) { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock(str)); + final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock(str, null, null)); final Set<String> modes = rm.getRunModes(); final String[] actual = modes.toArray(new String[modes.size()]); assertArrayEquals("Parsed runModes match for '" + str + "'", expected, actual); @@ -57,7 +59,7 @@ public class RunModeImplTest { } @org.junit.Test public void testMatchesNotEmpty() { - final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar")); + final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar", null, null)); assertTrue("single foo should be active", rm.getRunModes().contains("foo")); @@ -66,12 +68,121 @@ public class RunModeImplTest { assertFalse("empty should be not active", rm.getRunModes().contains("")); } + @org.junit.Test public void testOptions() { + final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar", "a,b,c|d,e,f", null)); + assertTrue("foo should be active", rm.getRunModes().contains("foo")); + assertTrue("bar should be active", rm.getRunModes().contains("bar")); + assertTrue("a should be active", rm.getRunModes().contains("a")); + assertTrue("d should be active", rm.getRunModes().contains("d")); + assertFalse("b should not be active", rm.getRunModes().contains("b")); + assertFalse("c should not be active", rm.getRunModes().contains("c")); + assertFalse("e should not be active", rm.getRunModes().contains("e")); + assertFalse("f should not be active", rm.getRunModes().contains("f")); + } + + @org.junit.Test public void testOptionsSelected() { + final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,e", "a,b,c|d,e,f", null)); + assertTrue("foo should be active", rm.getRunModes().contains("foo")); + assertTrue("bar should be active", rm.getRunModes().contains("bar")); + assertTrue("c should be active", rm.getRunModes().contains("c")); + assertTrue("e should be active", rm.getRunModes().contains("e")); + assertFalse("a should not be active", rm.getRunModes().contains("a")); + assertFalse("b should not be active", rm.getRunModes().contains("b")); + assertFalse("d should not be active", rm.getRunModes().contains("d")); + assertFalse("f should not be active", rm.getRunModes().contains("f")); + } + + @org.junit.Test public void testOptionsMultipleSelected() { + final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,e,f,a", "a,b,c|d,e,f", null)); + assertTrue("foo should be active", rm.getRunModes().contains("foo")); + assertTrue("bar should be active", rm.getRunModes().contains("bar")); + assertTrue("a should be active", rm.getRunModes().contains("a")); + assertTrue("e should be active", rm.getRunModes().contains("e")); + assertFalse("b should not be active", rm.getRunModes().contains("b")); + assertFalse("c should not be active", rm.getRunModes().contains("c")); + assertFalse("d should not be active", rm.getRunModes().contains("d")); + assertFalse("f should not be active", rm.getRunModes().contains("f")); + } + + @org.junit.Test public void testInstallOptions() { + final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar", null, "a,b,c|d,e,f")); + assertTrue("foo should be active", rm.getRunModes().contains("foo")); + assertTrue("bar should be active", rm.getRunModes().contains("bar")); + assertTrue("a should be active", rm.getRunModes().contains("a")); + assertTrue("d should be active", rm.getRunModes().contains("d")); + assertFalse("b should not be active", rm.getRunModes().contains("b")); + assertFalse("c should not be active", rm.getRunModes().contains("c")); + assertFalse("e should not be active", rm.getRunModes().contains("e")); + assertFalse("f should not be active", rm.getRunModes().contains("f")); + } + + @org.junit.Test public void testInstallOptionsSelected() { + final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,e", null , "a,b,c|d,e,f")); + assertTrue("foo should be active", rm.getRunModes().contains("foo")); + assertTrue("bar should be active", rm.getRunModes().contains("bar")); + assertTrue("c should be active", rm.getRunModes().contains("c")); + assertTrue("e should be active", rm.getRunModes().contains("e")); + assertFalse("a should not be active", rm.getRunModes().contains("a")); + assertFalse("b should not be active", rm.getRunModes().contains("b")); + assertFalse("d should not be active", rm.getRunModes().contains("d")); + assertFalse("f should not be active", rm.getRunModes().contains("f")); + } + + @org.junit.Test public void testInstallOptionsMultipleSelected() { + final SlingSettingsService rm = new SlingSettingsServiceImpl(new BundleContextMock("foo,bar,c,e,f,a", null, "a,b,c|d,e,f")); + assertTrue("foo should be active", rm.getRunModes().contains("foo")); + assertTrue("bar should be active", rm.getRunModes().contains("bar")); + assertTrue("a should be active", rm.getRunModes().contains("a")); + assertTrue("e should be active", rm.getRunModes().contains("e")); + assertFalse("b should not be active", rm.getRunModes().contains("b")); + assertFalse("c should not be active", rm.getRunModes().contains("c")); + assertFalse("d should not be active", rm.getRunModes().contains("d")); + assertFalse("f should not be active", rm.getRunModes().contains("f")); + } + + @org.junit.Test public void testInstallOptionsRestart() { + final BundleContextMock bc = new BundleContextMock("foo,bar,c,e,f,a", null, "a,b,c|d,e,f"); + new SlingSettingsServiceImpl(bc); // first context to simulate install + final SlingSettingsService rm = new SlingSettingsServiceImpl(bc); + assertTrue("foo should be active", rm.getRunModes().contains("foo")); + assertTrue("bar should be active", rm.getRunModes().contains("bar")); + assertTrue("a should be active", rm.getRunModes().contains("a")); + assertTrue("e should be active", rm.getRunModes().contains("e")); + assertFalse("b should not be active", rm.getRunModes().contains("b")); + assertFalse("c should not be active", rm.getRunModes().contains("c")); + assertFalse("d should not be active", rm.getRunModes().contains("d")); + assertFalse("f should not be active", rm.getRunModes().contains("f")); + + // and another restart with different run modes + bc.update("foo,doo,a,b,c,d,e,f"); + final SlingSettingsService rm2 = new SlingSettingsServiceImpl(bc); + assertTrue("foo should be active", rm2.getRunModes().contains("foo")); + assertTrue("doo should be active", rm2.getRunModes().contains("doo")); + assertTrue("a should be active", rm2.getRunModes().contains("a")); + assertTrue("e should be active", rm2.getRunModes().contains("e")); + assertFalse("bar should not be active", rm2.getRunModes().contains("bar")); + assertFalse("b should not be active", rm2.getRunModes().contains("b")); + assertFalse("c should not be active", rm2.getRunModes().contains("c")); + assertFalse("d should not be active", rm2.getRunModes().contains("d")); + assertFalse("f should not be active", rm2.getRunModes().contains("f")); + } + private static final class BundleContextMock implements BundleContext { - private final String str; + private String runModes; + private final String options; + private final String installOptions; + + private final Map<String, File> files = new HashMap<String, File>(); - public BundleContextMock(String str) { - this.str = str; + public BundleContextMock(String runModes, String options, String installOptions) { + this.runModes = runModes; + this.options = options; + this.installOptions = installOptions; + } + + public void update(final String rm) { + this.runModes = rm; } public void addBundleListener(BundleListener listener) { @@ -121,17 +232,28 @@ public class RunModeImplTest { } public File getDataFile(String filename) { - try { - final File f = File.createTempFile("sling", "id"); - f.deleteOnExit(); - return f; - } catch (IOException ioe) { - throw new RuntimeException(ioe); + File f = files.get(filename); + if ( f == null ) { + try { + f = File.createTempFile(filename, "id"); + f.deleteOnExit(); + files.put(filename, f); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } } + return f; } public String getProperty(String key) { - return str; + if ( key.equals(SlingSettingsService.RUN_MODES_PROPERTY) ) { + return runModes; + } else if ( key.equals(SlingSettingsService.RUN_MODE_OPTIONS) ) { + return options; + } else if ( key.equals(SlingSettingsService.RUN_MODE_INSTALL_OPTIONS) ) { + return installOptions; + } + return null; } public Object getService(ServiceReference reference) { -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
