This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.provisioning.model-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-provisioning-model.git
commit 4b98c32d19fc98161211fa6c411d12ee929c9acb Author: Carsten Ziegeler <cziege...@apache.org> AuthorDate: Wed Oct 1 16:03:47 2014 +0000 Refactor model and add basic read/write test git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/tooling/support/slingstart-model@1628749 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 4 + .../apache/sling/provisioning/model/Artifact.java | 2 +- .../sling/provisioning/model/ArtifactGroup.java | 17 +-- .../model/{Traceable.java => Commentable.java} | 26 +--- .../sling/provisioning/model/Configuration.java | 2 +- .../apache/sling/provisioning/model/Feature.java | 16 +- .../apache/sling/provisioning/model/ItemList.java | 50 +++++++ .../sling/provisioning/model/KeyValueMap.java | 55 +++++++ .../org/apache/sling/provisioning/model/Model.java | 4 +- .../sling/provisioning/model/ModelUtility.java | 20 +-- .../apache/sling/provisioning/model/RunMode.java | 18 ++- .../apache/sling/provisioning/model/Traceable.java | 25 +--- .../sling/provisioning/model/io/ModelReader.java | 166 +++++++++------------ .../sling/provisioning/model/io/ModelWriter.java | 86 +++++------ .../apache/sling/provisioning/model/io/IOTest.java | 75 ++++++++++ src/test/resources/boot.txt | 40 +++++ src/test/resources/example.txt | 64 ++++++++ src/test/resources/main.txt | 104 +++++++++++++ src/test/resources/oak.txt | 19 +++ 19 files changed, 560 insertions(+), 233 deletions(-) diff --git a/pom.xml b/pom.xml index 46f9477..8d212a2 100644 --- a/pom.xml +++ b/pom.xml @@ -64,5 +64,9 @@ <version>1.2.8</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> </dependencies> </project> diff --git a/src/main/java/org/apache/sling/provisioning/model/Artifact.java b/src/main/java/org/apache/sling/provisioning/model/Artifact.java index bb5d844..432c4bf 100644 --- a/src/main/java/org/apache/sling/provisioning/model/Artifact.java +++ b/src/main/java/org/apache/sling/provisioning/model/Artifact.java @@ -25,7 +25,7 @@ import java.util.Map; * In addition, the classifier and type can be specified as well. * An artifact can have any metadata. */ -public class Artifact extends Traceable { +public class Artifact extends Commentable { private final String groupId; private final String artifactId; diff --git a/src/main/java/org/apache/sling/provisioning/model/ArtifactGroup.java b/src/main/java/org/apache/sling/provisioning/model/ArtifactGroup.java index 0d0ccf9..8cb3550 100644 --- a/src/main/java/org/apache/sling/provisioning/model/ArtifactGroup.java +++ b/src/main/java/org/apache/sling/provisioning/model/ArtifactGroup.java @@ -16,20 +16,16 @@ */ package org.apache.sling.provisioning.model; -import java.util.ArrayList; -import java.util.List; /** * A artifact group holds a set of artifacts. * A valid start level is positive, start level 0 means the default OSGi start level. */ -public class ArtifactGroup extends Traceable +public class ArtifactGroup extends ItemList<Artifact> implements Comparable<ArtifactGroup> { private final int level; - private final List<Artifact> artifacts = new ArrayList<Artifact>(); - public ArtifactGroup(final int level) { this.level = level; } @@ -38,20 +34,17 @@ public class ArtifactGroup extends Traceable return this.level; } - public List<Artifact> getArtifacts() { - return this.artifacts; - } - /** * Search an artifact with the same groupId, artifactId, version, type and classifier. * Version is not considered. */ public Artifact search(final Artifact template) { Artifact found = null; - for(final Artifact current : this.artifacts) { + for(final Artifact current : this) { if ( current.getGroupId().equals(template.getGroupId()) && current.getArtifactId().equals(template.getArtifactId()) - && current.getClassifier().equals(template.getClassifier()) + && ((current.getClassifier() == null && template.getClassifier() == null) + || (current.getClassifier().equals(template.getClassifier()) )) && current.getType().equals(template.getType()) ) { found = current; break; @@ -73,7 +66,7 @@ public class ArtifactGroup extends Traceable @Override public String toString() { return "ArtifactGroup [level=" + level - + ", artifacts=" + artifacts + + ", artifacts=" + this.items + ( this.getLocation() != null ? ", location=" + this.getLocation() : "") + "]"; } diff --git a/src/main/java/org/apache/sling/provisioning/model/Traceable.java b/src/main/java/org/apache/sling/provisioning/model/Commentable.java similarity index 67% copy from src/main/java/org/apache/sling/provisioning/model/Traceable.java copy to src/main/java/org/apache/sling/provisioning/model/Commentable.java index 4345ab5..b966a91 100644 --- a/src/main/java/org/apache/sling/provisioning/model/Traceable.java +++ b/src/main/java/org/apache/sling/provisioning/model/Commentable.java @@ -20,33 +20,12 @@ package org.apache.sling.provisioning.model; * A traceable has a comment and a location. * Both are optional. */ -public abstract class Traceable { - - /** The location. */ - private String location; +public abstract class Commentable extends Traceable { /** The comment. */ private String comment; /** - * Get the location. - * The location might be the location of the model file or any other - * means identifying where the object is defined. - * @return The location or {@code null}. - */ - public String getLocation() { - return this.location; - } - - /** - * Set the location. - * @param value The new location. - */ - public void setLocation(final String value) { - this.location = value; - } - - /** * Get the comment. * @return The comment or {@code null}. */ @@ -64,8 +43,7 @@ public abstract class Traceable { @Override public String toString() { - return "SSMTraceable [location=" + location + ", comment=" + comment - + "]"; + return "Commentable [location=" + this.getLocation() + ", comment=" + comment + "]"; } } diff --git a/src/main/java/org/apache/sling/provisioning/model/Configuration.java b/src/main/java/org/apache/sling/provisioning/model/Configuration.java index 67535ce..b317a14 100644 --- a/src/main/java/org/apache/sling/provisioning/model/Configuration.java +++ b/src/main/java/org/apache/sling/provisioning/model/Configuration.java @@ -23,7 +23,7 @@ import java.util.Hashtable; /** * Configuration */ -public class Configuration extends Traceable { +public class Configuration extends Commentable { private final String pid; diff --git a/src/main/java/org/apache/sling/provisioning/model/Feature.java b/src/main/java/org/apache/sling/provisioning/model/Feature.java index 480e1b8..f333888 100644 --- a/src/main/java/org/apache/sling/provisioning/model/Feature.java +++ b/src/main/java/org/apache/sling/provisioning/model/Feature.java @@ -19,9 +19,7 @@ package org.apache.sling.provisioning.model; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** @@ -30,14 +28,14 @@ import java.util.Map; * - run modes */ public class Feature - extends Traceable + extends Commentable implements Comparable<Feature> { /** All run modes. */ private final List<RunMode> runModes = new ArrayList<RunMode>(); /** Variables. */ - private final Map<String, String> variables = new HashMap<String, String>(); + private final KeyValueMap<String> variables = new KeyValueMap<String>(); private final String name; @@ -68,7 +66,7 @@ public class Feature * Get all variables * @return The set of variables */ - public Map<String, String> getVariables() { + public KeyValueMap<String> getVariables() { return this.variables; } @@ -122,4 +120,12 @@ public class Feature return this.name.compareTo(o.name); } + @Override + public String toString() { + return "Feature [runModes=" + runModes + ", variables=" + variables + + ", name=" + name + + ( this.getLocation() != null ? ", location=" + this.getLocation() : "") + + "]"; + } + } diff --git a/src/main/java/org/apache/sling/provisioning/model/ItemList.java b/src/main/java/org/apache/sling/provisioning/model/ItemList.java new file mode 100644 index 0000000..85ea138 --- /dev/null +++ b/src/main/java/org/apache/sling/provisioning/model/ItemList.java @@ -0,0 +1,50 @@ +/* + * 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.provisioning.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ItemList<T> + extends Commentable + implements Iterable<T> { + + protected final List<T> items = new ArrayList<T>(); + + public void add(final T item) { + this.items.add(item); + } + + public void remove(final T item) { + this.items.remove(item); + } + + @Override + public Iterator<T> iterator() { + return this.items.iterator(); + } + + public boolean isEmpty() { + return this.items.isEmpty(); + } + + @Override + public String toString() { + return items.toString(); + } +} diff --git a/src/main/java/org/apache/sling/provisioning/model/KeyValueMap.java b/src/main/java/org/apache/sling/provisioning/model/KeyValueMap.java new file mode 100644 index 0000000..aa6598c --- /dev/null +++ b/src/main/java/org/apache/sling/provisioning/model/KeyValueMap.java @@ -0,0 +1,55 @@ +/* + * 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.provisioning.model; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +public class KeyValueMap<T> + extends Commentable + implements Iterable<Map.Entry<String, T>> { + + private final Map<String, T> properties = new HashMap<String, T>(); + + public T get(final String key) { + return this.properties.get(key); + } + + public void put(final String key, final T value) { + this.properties.put(key, value); + } + + public void putAll(final KeyValueMap<T> map) { + this.properties.putAll(map.properties); + } + + @Override + public Iterator<Entry<String, T>> iterator() { + return this.properties.entrySet().iterator(); + } + + public boolean isEmpty() { + return this.properties.isEmpty(); + } + + @Override + public String toString() { + return properties.toString(); + } +} diff --git a/src/main/java/org/apache/sling/provisioning/model/Model.java b/src/main/java/org/apache/sling/provisioning/model/Model.java index 5ce2a55..ee80611 100644 --- a/src/main/java/org/apache/sling/provisioning/model/Model.java +++ b/src/main/java/org/apache/sling/provisioning/model/Model.java @@ -69,8 +69,6 @@ public class Model extends Traceable { @Override public String toString() { - return "Model [features=" + features - + ( this.getLocation() != null ? ", location=" + this.getLocation() : "") - + "]"; + return "Model [features=" + features + "]"; } } diff --git a/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java b/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java index 3188d1c..d42f727 100644 --- a/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java +++ b/src/main/java/org/apache/sling/provisioning/model/ModelUtility.java @@ -55,12 +55,12 @@ public abstract class ModelUtility { for(final ArtifactGroup group : runMode.getArtifactGroups()) { final ArtifactGroup baseGroup = baseRunMode.getOrCreateArtifactGroup(group.getLevel()); - for(final Artifact artifact : group.getArtifacts()) { + for(final Artifact artifact : group) { final Artifact found = baseGroup.search(artifact); if ( found != null ) { - baseGroup.getArtifacts().remove(found); + baseGroup.remove(found); } - baseGroup.getArtifacts().add(artifact); + baseGroup.add(artifact); } } @@ -75,7 +75,7 @@ public abstract class ModelUtility { } // settings - for(final Map.Entry<String, String> entry : runMode.getSettings().entrySet() ) { + for(final Map.Entry<String, String> entry : runMode.getSettings() ) { baseRunMode.getSettings().put(entry.getKey(), entry.getValue()); } } @@ -109,8 +109,6 @@ public abstract class ModelUtility { */ public static Model getEffectiveModel(final Model model, final VariableResolver resolver) { final Model result = new Model(); - result.setComment(model.getComment()); - result.setLocation(model.getLocation()); for(final Feature feature : model.getFeatures()) { final Feature newFeature = result.getOrCreateFeature(feature.getName()); @@ -121,15 +119,13 @@ public abstract class ModelUtility { for(final RunMode runMode : feature.getRunModes()) { final RunMode newRunMode = newFeature.getOrCreateRunMode(runMode.getRunModes()); - newRunMode.setComment(runMode.getComment()); - newRunMode.setLocation(runMode.getLocation()); for(final ArtifactGroup group : runMode.getArtifactGroups()) { final ArtifactGroup newGroup = newRunMode.getOrCreateArtifactGroup(group.getLevel()); newGroup.setComment(group.getComment()); newGroup.setLocation(group.getLocation()); - for(final Artifact artifact : group.getArtifacts()) { + for(final Artifact artifact : group) { final Artifact newArtifact = new Artifact(replace(feature, artifact.getGroupId(), resolver), replace(feature, artifact.getArtifactId(), resolver), replace(feature, artifact.getVersion(), resolver), @@ -138,7 +134,7 @@ public abstract class ModelUtility { newArtifact.setComment(artifact.getComment()); newArtifact.setLocation(artifact.getLocation()); - newGroup.getArtifacts().add(newArtifact); + newGroup.add(newArtifact); } } @@ -201,7 +197,7 @@ public abstract class ModelUtility { newRunMode.getConfigurations().add(newConfig); } - for(final Map.Entry<String, String> entry : runMode.getSettings().entrySet() ) { + for(final Map.Entry<String, String> entry : runMode.getSettings() ) { newRunMode.getSettings().put(entry.getKey(), replace(feature, entry.getValue(), resolver)); } } @@ -284,7 +280,7 @@ public abstract class ModelUtility { if ( sl.getLevel() < 0 ) { errors.put(sl, "Invalid start level " + sl.getLevel()); } - for(final Artifact a : sl.getArtifacts()) { + for(final Artifact a : sl) { String error = null; if ( a.getGroupId() == null || a.getGroupId().isEmpty() ) { error = "groupId missing"; diff --git a/src/main/java/org/apache/sling/provisioning/model/RunMode.java b/src/main/java/org/apache/sling/provisioning/model/RunMode.java index 677abaf..72a8b23 100644 --- a/src/main/java/org/apache/sling/provisioning/model/RunMode.java +++ b/src/main/java/org/apache/sling/provisioning/model/RunMode.java @@ -19,9 +19,7 @@ package org.apache.sling.provisioning.model; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; /** @@ -43,9 +41,9 @@ public class RunMode private final List<ArtifactGroup> groups = new ArrayList<ArtifactGroup>(); - private final List<Configuration> configurations = new ArrayList<Configuration>(); + private final ItemList<Configuration> configurations = new ItemList<Configuration>(); - private final Map<String, String> settings = new HashMap<String, String>(); + private final KeyValueMap<String> settings = new KeyValueMap<String>(); public RunMode(final String[] runModes) { this.runModes = getSortedRunModesArray(runModes); @@ -153,7 +151,7 @@ public class RunMode return null; } - public Configuration getOrCreateConfiguration(final String pid, final String factoryPid) { + public Configuration getConfiguration(final String pid, final String factoryPid) { Configuration found = null; for(final Configuration current : this.configurations) { if ( factoryPid == null ) { @@ -168,6 +166,11 @@ public class RunMode } } } + return found; + } + + public Configuration getOrCreateConfiguration(final String pid, final String factoryPid) { + Configuration found = getConfiguration(pid, factoryPid); if ( found == null ) { found = new Configuration(pid, factoryPid); this.configurations.add(found); @@ -179,11 +182,11 @@ public class RunMode return this.groups; } - public List<Configuration> getConfigurations() { + public ItemList<Configuration> getConfigurations() { return this.configurations; } - public Map<String, String> getSettings() { + public KeyValueMap<String> getSettings() { return this.settings; } @@ -209,7 +212,6 @@ public class RunMode return "RunMode [runModes=" + Arrays.toString(runModes) + ", groups=" + groups + ", configurations=" + configurations + ", settings=" + settings - + ( this.getLocation() != null ? ", location=" + this.getLocation() : "") + "]"; } diff --git a/src/main/java/org/apache/sling/provisioning/model/Traceable.java b/src/main/java/org/apache/sling/provisioning/model/Traceable.java index 4345ab5..d4ced41 100644 --- a/src/main/java/org/apache/sling/provisioning/model/Traceable.java +++ b/src/main/java/org/apache/sling/provisioning/model/Traceable.java @@ -17,17 +17,13 @@ package org.apache.sling.provisioning.model; /** - * A traceable has a comment and a location. - * Both are optional. + * A traceable has an optional location. */ public abstract class Traceable { /** The location. */ private String location; - /** The comment. */ - private String comment; - /** * Get the location. * The location might be the location of the model file or any other @@ -46,26 +42,9 @@ public abstract class Traceable { this.location = value; } - /** - * Get the comment. - * @return The comment or {@code null}. - */ - public String getComment() { - return this.comment; - } - - /** - * Set the comment. - * @param value The new comment. - */ - public void setComment(final String value) { - this.comment = value; - } - @Override public String toString() { - return "SSMTraceable [location=" + location + ", comment=" + comment - + "]"; + return "Traceable [location=" + location + "]"; } } diff --git a/src/main/java/org/apache/sling/provisioning/model/io/ModelReader.java b/src/main/java/org/apache/sling/provisioning/model/io/ModelReader.java index c3833df..948f3e6 100644 --- a/src/main/java/org/apache/sling/provisioning/model/io/ModelReader.java +++ b/src/main/java/org/apache/sling/provisioning/model/io/ModelReader.java @@ -25,31 +25,32 @@ import java.util.Map; import org.apache.sling.provisioning.model.Artifact; import org.apache.sling.provisioning.model.ArtifactGroup; +import org.apache.sling.provisioning.model.Commentable; import org.apache.sling.provisioning.model.Configuration; import org.apache.sling.provisioning.model.Feature; import org.apache.sling.provisioning.model.Model; import org.apache.sling.provisioning.model.ModelConstants; import org.apache.sling.provisioning.model.RunMode; -import org.apache.sling.provisioning.model.Traceable; public class ModelReader { private enum CATEGORY { - NONE(null), - FEATURE("feature"), - VARIABLES("variables"), - GLOBAL("global"), - RUN_MODE("runMode"), - ARTIFACTS("artifacts"), - SETTINGS("settings"), - CONFIGURATIONS("configurations"), - CONFIG(null); + NONE(null, null), + FEATURE("feature", new String[] {"name"}), + VARIABLES("variables", null), + ARTIFACTS("artifacts", new String[] {"runModes", "startLevel"}), + SETTINGS("settings", new String[] {"runModes"}), + CONFIGURATIONS("configurations", new String[] {"runModes"}), + CONFIG(null, null); public final String name; - private CATEGORY(final String n) { + public final String[] parameters; + + private CATEGORY(final String n, final String[] p) { this.name = n; + this.parameters = p; } } @@ -64,9 +65,6 @@ public class ModelReader { return mr.readModel(reader); } - /** Is this a single feature model? */ - private boolean isSingleFeature = false; - private CATEGORY mode = CATEGORY.NONE; private final Model model = new Model(); @@ -101,16 +99,18 @@ public class ModelReader { lineNumberReader = new LineNumberReader(reader); String line; while ( (line = lineNumberReader.readLine()) != null ) { + // trim the line line = line.trim(); + // ignore empty line if ( line.isEmpty() ) { checkConfig(); continue; } + // comment? if ( line.startsWith("#") ) { checkConfig(); - mode = CATEGORY.NONE; final String c = line.substring(1).trim(); if ( comment == null ) { comment = c; @@ -122,8 +122,9 @@ public class ModelReader { if ( global ) { global = false; - model.setComment(comment); - comment = null; + if ( !line.startsWith("[feature ") ) { + throw new IOException(exceptionPrefix + " Model file must start with a feature category."); + } } if ( line.startsWith("[") ) { @@ -149,22 +150,16 @@ public class ModelReader { Map<String, String> parameters = Collections.emptyMap(); if (line.charAt(pos) != ']') { final String parameterLine = line.substring(pos + 1, line.length() - 1).trim(); - parameters = parseParameters(parameterLine); + parameters = parseParameters(parameterLine, this.mode.parameters); } switch ( this.mode ) { case NONE : break; // this can never happen case CONFIG : break; // this can never happen - case FEATURE : if ( this.isSingleFeature ) { - throw new IOException(exceptionPrefix + "Single feature model allows only one feature."); - } - final String name = parameters.get("name"); + case FEATURE : final String name = parameters.get("name"); if ( name == null ) { throw new IOException(exceptionPrefix + "Feature name missing in line " + this.lineNumberReader.getLineNumber() + ": " + line); } - if ( parameters.size() > 1 ) { - throw new IOException(exceptionPrefix + "Unknown feature parameters in line " + this.lineNumberReader.getLineNumber() + ": " + line); - } if ( model.findFeature(name) != null ) { throw new IOException(exceptionPrefix + "Duplicate feature in line " + this.lineNumberReader.getLineNumber() + ": " + line); } @@ -174,45 +169,16 @@ public class ModelReader { this.artifactGroup = null; break; case VARIABLES : checkFeature(); + this.init(this.feature.getVariables()); break; - case RUN_MODE : checkFeature(); - final String names = parameters.get("names"); - if ( names == null ) { - throw new IOException(exceptionPrefix + "Run mode names missing in line " + this.lineNumberReader.getLineNumber() + ": " + line); - } - if ( parameters.size() > 1 ) { - throw new IOException(exceptionPrefix + "Unknown run mode parameters in line " + this.lineNumberReader.getLineNumber() + ": " + line); - } - final String[] rm = names.split(","); - if ( this.feature.getRunMode(rm) != null ) { - throw new IOException(exceptionPrefix + "Duplicate run mode in line " + this.lineNumberReader.getLineNumber() + ": " + line); - } - this.runMode = this.feature.getOrCreateRunMode(rm); - this.init(this.runMode); - this.artifactGroup = null; - break; - case GLOBAL : checkFeature(); - if ( !parameters.isEmpty() ) { - throw new IOException(exceptionPrefix + "Unknown global parameters in line " + this.lineNumberReader.getLineNumber() + ": " + line); - } - if ( this.feature.getRunMode(null) != null ) { - throw new IOException(exceptionPrefix + "Duplicate global run mode in line " + this.lineNumberReader.getLineNumber() + ": " + line); - } - this.runMode = this.feature.getOrCreateRunMode(null); - this.init(this.runMode); - this.artifactGroup = null; - break; case SETTINGS: checkFeature(); - checkRunMode(); + checkRunMode(parameters); + this.init(this.runMode.getSettings()); break; case ARTIFACTS: checkFeature(); - checkRunMode(); - String level = parameters.get("startLevel"); - if ( (level == null && !parameters.isEmpty()) - || (level != null && parameters.size() > 1 ) ) { - throw new IOException(exceptionPrefix + "Unknown artifacts parameters in line " + this.lineNumberReader.getLineNumber() + ": " + line); - } + checkRunMode(parameters); int startLevel = 0; + String level = parameters.get("startLevel"); if ( level != null ) { try { startLevel = Integer.valueOf(level); @@ -227,7 +193,8 @@ public class ModelReader { this.init(this.artifactGroup); break; case CONFIGURATIONS: checkFeature(); - checkRunMode(); + checkRunMode(parameters); + this.init(this.runMode.getConfigurations()); break; } } else { @@ -239,27 +206,22 @@ public class ModelReader { case SETTINGS : final String[] settings = parseProperty(line); runMode.getSettings().put(settings[0], settings[1]); break; - case FEATURE: - case RUN_MODE: - case GLOBAL: - case ARTIFACTS : this.checkFeature(); - this.checkRunMode(); - if ( this.artifactGroup == null ) { - this.artifactGroup = this.runMode.getOrCreateArtifactGroup(0); - } - String artifactUrl = line; + case FEATURE: this.runMode = this.feature.getOrCreateRunMode(null); + this.artifactGroup = this.runMode.getOrCreateArtifactGroup(0); + // no break, we continue with ARTIFACT + case ARTIFACTS : String artifactUrl = line; Map<String, String> parameters = Collections.emptyMap(); if ( line.endsWith("]") ) { final int startPos = line.indexOf("["); if ( startPos != -1 ) { artifactUrl = line.substring(0, startPos).trim(); - parameters = parseParameters(line.substring(startPos + 1, line.length() - 1).trim()); + parameters = parseParameters(line.substring(startPos + 1, line.length() - 1).trim(), null); } } try { final Artifact artifact = Artifact.fromMvnUrl("mvn:" + artifactUrl); this.init(artifact); - this.artifactGroup.getArtifacts().add(artifact); + this.artifactGroup.add(artifact); artifact.getMetadata().putAll(parameters); } catch ( final IllegalArgumentException iae) { throw new IOException(exceptionPrefix + iae.getMessage() + " in line " + this.lineNumberReader.getLineNumber(), iae); @@ -271,14 +233,10 @@ public class ModelReader { final int startPos = line.indexOf("["); if ( startPos != -1 ) { configId = line.substring(0, startPos).trim(); - cfgPars = parseParameters(line.substring(startPos + 1, line.length() - 1).trim()); + cfgPars = parseParameters(line.substring(startPos + 1, line.length() - 1).trim(), new String[] {"format"}); } } String format = cfgPars.get("format"); - if ( (format == null && !cfgPars.isEmpty()) - || (format != null && cfgPars.size() > 1 ) ) { - throw new IOException(exceptionPrefix + "Unknown configuration parameters in line " + this.lineNumberReader.getLineNumber() + ": " + line); - } if ( format != null ) { if ( !ModelConstants.CFG_FORMAT_FELIX_CA.equals(format) && !ModelConstants.CFG_FORMAT_PROPERTIES.equals(format) ) { @@ -287,15 +245,23 @@ public class ModelReader { } else { format = ModelConstants.CFG_FORMAT_FELIX_CA; } + final String pid; + final String factoryPid; final int factoryPos = configId.indexOf('-'); if ( factoryPos == -1 ) { + pid = configId; + factoryPid = null; config = new Configuration(configId, null); } else { - config = new Configuration(configId.substring(factoryPos + 1), configId.substring(0, factoryPos)); + pid = configId.substring(factoryPos + 1); + factoryPid = configId.substring(0, factoryPos); + } + if ( runMode.getConfiguration(pid, factoryPid) != null ) { + throw new IOException(exceptionPrefix + "Duplicate configuration in line " + this.lineNumberReader.getLineNumber()); } + config = runMode.getOrCreateConfiguration(pid, factoryPid); this.init(config); config.getProperties().put(ModelConstants.CFG_UNPROCESSED_FORMAT, format); - runMode.getConfigurations().add(config); configBuilder = new StringBuilder(); mode = CATEGORY.CONFIG; break; @@ -318,30 +284,26 @@ public class ModelReader { */ private void checkFeature() throws IOException { if ( feature == null ) { - if ( model.getLocation() == null ) { - throw new IOException(exceptionPrefix + "No preceding feature definition in line " + this.lineNumberReader.getLineNumber()); - } - final int beginPos = model.getLocation().replace('\\', '/').lastIndexOf("/"); - String newName = model.getLocation().substring(beginPos + 1); - final int endPos = newName.lastIndexOf('.'); - if ( endPos != -1 ) { - newName = newName.substring(0, endPos); - } - this.isSingleFeature = true; - feature = model.getOrCreateFeature(newName); + throw new IOException(exceptionPrefix + "No preceding feature definition in line " + this.lineNumberReader.getLineNumber()); } } /** * Check for a run mode object */ - private void checkRunMode() throws IOException { - if ( runMode == null ) { - runMode = this.feature.getOrCreateRunMode(null); + private void checkRunMode(final Map<String, String> parameters) throws IOException { + String[] runModes = null; + final String rmDef = parameters.get("runModes"); + if ( rmDef != null ) { + runModes = rmDef.split(","); + for(int i=0; i<runModes.length; i++) { + runModes[i] = runModes[i].trim(); + } } + runMode = this.feature.getOrCreateRunMode(runModes); } - private void init(final Traceable traceable) { + private void init(final Commentable traceable) { traceable.setComment(this.comment); this.comment = null; final String number = String.valueOf(this.lineNumberReader.getLineNumber()); @@ -377,7 +339,7 @@ public class ModelReader { return new String[] {key, value}; } - private Map<String, String> parseParameters(final String line) throws IOException { + private Map<String, String> parseParameters(final String line, final String[] allowedParameters) throws IOException { final Map<String, String>parameters = new HashMap<String, String>(); final String[] keyValuePairs = line.split(" "); for(String kv : keyValuePairs) { @@ -387,7 +349,21 @@ public class ModelReader { if ( sep == -1 ) { throw new IOException(exceptionPrefix + "Invalid parameter definition in line " + this.lineNumberReader.getLineNumber() + ": " + line); } - parameters.put(kv.substring(0, sep).trim(), kv.substring(sep + 1).trim()); + final String key = kv.substring(0, sep).trim(); + parameters.put(key, kv.substring(sep + 1).trim()); + + if ( allowedParameters != null ) { + boolean found = false; + for(final String allowed : allowedParameters) { + if ( key.equals(allowed) ) { + found = true; + break; + } + } + if ( !found ) { + throw new IOException(exceptionPrefix + "Invalid parameter " + key + " in line " + this.lineNumberReader.getLineNumber()); + } + } } } return parameters; diff --git a/src/main/java/org/apache/sling/provisioning/model/io/ModelWriter.java b/src/main/java/org/apache/sling/provisioning/model/io/ModelWriter.java index 4b023f0..09c8423 100644 --- a/src/main/java/org/apache/sling/provisioning/model/io/ModelWriter.java +++ b/src/main/java/org/apache/sling/provisioning/model/io/ModelWriter.java @@ -27,22 +27,22 @@ import java.util.Map; import org.apache.felix.cm.file.ConfigurationHandler; import org.apache.sling.provisioning.model.Artifact; import org.apache.sling.provisioning.model.ArtifactGroup; +import org.apache.sling.provisioning.model.Commentable; import org.apache.sling.provisioning.model.Configuration; import org.apache.sling.provisioning.model.Feature; import org.apache.sling.provisioning.model.Model; import org.apache.sling.provisioning.model.ModelConstants; import org.apache.sling.provisioning.model.RunMode; -import org.apache.sling.provisioning.model.Traceable; /** * Simple writer for the a model */ public class ModelWriter { - private static void writeComment(final PrintWriter pw, final Traceable traceable) + private static void writeComment(final PrintWriter pw, final Commentable commentable) throws IOException { - if ( traceable.getComment() != null ) { - final LineNumberReader lnr = new LineNumberReader(new StringReader(traceable.getComment())); + if ( commentable.getComment() != null ) { + final LineNumberReader lnr = new LineNumberReader(new StringReader(commentable.getComment())); try { String line = null; while ( (line = lnr.readLine()) != null ) { @@ -55,6 +55,22 @@ public class ModelWriter { } } + private static void writeRunMode(final PrintWriter pw, final RunMode runMode) { + final String[] rm = runMode.getRunModes(); + if ( rm != null && rm.length > 0 ) { + pw.print(" runModes="); + boolean first = true; + for(final String mode : rm) { + if ( first ) { + first = false; + } else { + pw.print(","); + } + pw.print(mode); + } + } + } + /** * Writes the model to the writer. * The writer is not closed. @@ -66,8 +82,6 @@ public class ModelWriter { throws IOException { final PrintWriter pw = new PrintWriter(writer); - writeComment(pw, model); - // features for(final Feature feature : model.getFeatures()) { writeComment(pw, feature); @@ -78,8 +92,9 @@ public class ModelWriter { // variables if ( !feature.getVariables().isEmpty() ) { + writeComment(pw, feature.getVariables()); pw.println("[variables]"); - for(final Map.Entry<String, String> entry : feature.getVariables().entrySet()) { + for(final Map.Entry<String, String> entry : feature.getVariables()) { pw.print(" "); pw.print(entry.getKey()); pw.print("="); @@ -90,43 +105,14 @@ public class ModelWriter { // run modes for(final RunMode runMode : feature.getRunModes()) { - // skip empty run mode - if ( runMode.getConfigurations().isEmpty() && runMode.getSettings().isEmpty() ) { - boolean hasArtifacts = false; - for(final ArtifactGroup sl : runMode.getArtifactGroups()) { - if ( !sl.getArtifacts().isEmpty() ) { - hasArtifacts = true; - break; - } - } - if ( !hasArtifacts ) { - continue; - } - } - writeComment(pw, runMode); - final String[] runModes = runMode.getRunModes(); - if ( runModes == null || runModes.length == 0 ) { - pw.println("[global]"); - } else { - pw.print("[runMode names="); - boolean first = true; - for(final String mode : runModes) { - if ( first ) { - first = false; - } else { - pw.print(","); - } - pw.print(mode); - } - pw.println("]"); - } - pw.println(); - // settings if ( !runMode.getSettings().isEmpty() ) { - pw.println("[settings]"); + writeComment(pw, runMode.getSettings()); + pw.print("[settings"); + writeRunMode(pw, runMode); + pw.println("]"); - for(final Map.Entry<String, String> entry : runMode.getSettings().entrySet()) { + for(final Map.Entry<String, String> entry : runMode.getSettings()) { pw.print(" "); pw.print(entry.getKey()); pw.print("="); @@ -138,7 +124,7 @@ public class ModelWriter { // artifact groups for(final ArtifactGroup group : runMode.getArtifactGroups()) { // skip empty groups - if ( group.getArtifacts().isEmpty() ) { + if ( group.isEmpty() ) { continue; } writeComment(pw, group); @@ -147,11 +133,12 @@ public class ModelWriter { pw.print(" startLevel="); pw.print(String.valueOf(group.getLevel())); } + writeRunMode(pw, runMode); pw.println("]"); pw.println(); // artifacts - for(final Artifact ad : group.getArtifacts()) { + for(final Artifact ad : group) { writeComment(pw, ad); pw.print(" "); pw.print(ad.toMvnUrl().substring(4)); @@ -160,26 +147,27 @@ public class ModelWriter { for(final Map.Entry<String, String> entry : ad.getMetadata().entrySet()) { if ( first ) { first = false; - pw.print("{ "); + pw.print(" { "); } else { pw.print(", "); } pw.print(entry.getKey()); pw.print("="); - pw.println(entry.getValue()); + pw.print(entry.getValue()); } pw.print("}"); } pw.println(); } - if ( !group.getArtifacts().isEmpty() ) { - pw.println(); - } + pw.println(); } // configurations if ( !runMode.getConfigurations().isEmpty() ) { - pw.println("[configurations]"); + writeComment(pw, runMode.getConfigurations()); + pw.print("[configurations"); + writeRunMode(pw, runMode); + pw.println("]"); for(final Configuration config : runMode.getConfigurations()) { writeComment(pw, config); final String raw = (String)config.getProperties().get(ModelConstants.CFG_UNPROCESSED); diff --git a/src/test/java/org/apache/sling/provisioning/model/io/IOTest.java b/src/test/java/org/apache/sling/provisioning/model/io/IOTest.java new file mode 100644 index 0000000..313f9d4 --- /dev/null +++ b/src/test/java/org/apache/sling/provisioning/model/io/IOTest.java @@ -0,0 +1,75 @@ +/* + * 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.provisioning.model.io; + +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Map; + +import org.apache.sling.provisioning.model.Model; +import org.apache.sling.provisioning.model.ModelUtility; +import org.apache.sling.provisioning.model.Traceable; +import org.junit.Test; + +public class IOTest { + + /** + * Not really a unit test...but better than nothing + */ + @Test public void testReadWrite() throws Exception { + final Model result = new Model(); + final String[] candidates = new String[] {"boot.txt", "example.txt", "main.txt", "oak.txt"}; + + for(final String name : candidates) { + final Reader reader = new InputStreamReader(this.getClass().getResourceAsStream("/" + name), "UTF-8"); + try { + final Model current = ModelReader.read(reader, name); + final Map<Traceable, String> errors = ModelUtility.validate(current); + if (errors != null ) { + throw new Exception("Invalid model at " + name + " : " + errors); + } + ModelUtility.merge(result, current); + } finally { + reader.close(); + } + } + + final Map<Traceable, String> errors = ModelUtility.validate(result); + if (errors != null ) { + throw new Exception("Invalid assembled model : " + errors); + } + + // write the complete model + StringWriter writer = new StringWriter(); + try { + ModelWriter.write(writer, result); + } finally { + writer.close(); + } + + // and read it again + StringReader reader = new StringReader(writer.toString()); + final Model readModel = ModelReader.read(reader, "memory"); + reader.close(); + final Map<Traceable, String> readErrors = ModelUtility.validate(readModel); + if (readErrors != null ) { + throw new Exception("Invalid read model : " + readErrors); + } + } +} diff --git a/src/test/resources/boot.txt b/src/test/resources/boot.txt new file mode 100644 index 0000000..7f08d39 --- /dev/null +++ b/src/test/resources/boot.txt @@ -0,0 +1,40 @@ +# The :launchpad feature defines Sling's launchpad version +# Only a single artifact is allowed within this feature. +# +[feature name=:launchpad] + org.apache.sling/org.apache.sling.launchpad.base/4.4.1-2.5.2/jar + + +# The :boot feature contains all things to bootstrap the installation. +# +[feature name=:boot] + +# additional entries for sling.properties +# --------------------------------------- +# jackrabbit and oak run modes are mutually exclusive, +# and cannot be changed after the first startup +[settings] + sling.run.mode.install.options=jackrabbit,oak + +[artifacts] + org.slf4j/slf4j-api/1.7.6/jar + org.apache.sling/org.apache.sling.commons.log/4.0.0/jar + org.apache.sling/org.apache.sling.commons.logservice/1.0.2/jar + org.slf4j/jcl-over-slf4j/1.7.6/jar + org.slf4j/log4j-over-slf4j/1.7.6/jar + org.apache.sling/org.apache.sling.settings/1.3.2/jar + org.apache.sling/org.apache.sling.fragment.xml/1.0.2/jar + org.apache.sling/org.apache.sling.fragment.transaction/1.0.0/jar + org.apache.sling/org.apache.sling.javax.activation/0.1.0/jar + org.apache.sling/org.apache.sling.fragment.ws/${ws.version}/jar + org.apache.sling/org.apache.sling.launchpad.installer/1.2.0/jar + org.apache.sling/org.apache.sling.installer.core/3.5.4/jar + org.apache.sling/org.apache.sling.installer.provider.file/1.0.4/jar + org.apache.felix/org.apache.felix.configadmin/1.6.0/jar + org.apache.felix/org.apache.felix.eventadmin/1.4.2/jar + +# Add an a servlet implementation for the standalone case +[artifacts startLevel=5 runModes=:standalone] + org.apache.felix/org.apache.felix.http.api/2.3.0/jar + org.apache.felix/org.apache.felix.http.servlet-api/1.0.0/jar + org.apache.felix/org.apache.felix.http.jetty/2.3.0/jar diff --git a/src/test/resources/example.txt b/src/test/resources/example.txt new file mode 100644 index 0000000..0153cd3 --- /dev/null +++ b/src/test/resources/example.txt @@ -0,0 +1,64 @@ +# This is a feature description +# +# A feature consists of variables and run mode dependent artifacts. +# +[feature name=example] +# The variables are global and can be used within artifact definitions, configurations, +# and settings. +# +# Variables +[variables] + ws.version=1.0.2 + +# Settings, artifacts and configurations belong to a run mode. If none is specified +# the default run mode is used. The same goes with the start level for artifacts +# Framework properties +[settings] + sling.options=jackrabbit,oak + +[artifacts] + commons-io/commons-io/1.4/jar + commons-fileupload/commons-fileupload/1.3.1/jar + commons-collections/commons-collections/3.2.1/jar + commons-codec/commons-codec/1.9/jar + commons-lang/commons-lang/2.6/jar + org.apache.commons/commons-math/2.2/jar +# Artifacts can have additional information like a SHA1 etc. +# + org.apache.commons/commons-math/2.2/jar [sha1=2353750701ABE] + +# A start level can be specified +[artifacts startLevel=5] + org.apache.sling/org.apache.sling.extensions.webconsolebranding/1.0.0/jar + org.apache.sling/org.apache.sling.extensions.webconsolesecurityprovider/1.0.0/jar + +# And now the configurations section +# A configuration ends with an empty line and all configurations use the Apache Felix +# ConfigAdmin format. +# +[configurations] +# A plain configuration +org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStoreService + name="Default\ NodeStore" + repository.home="sling/oak/repository" + +# A factory configuration with the alias error +org.apache.sling.log.LoggerFactory-error + name="Test" + value="Hallo" + +# A configuration using properties format: +org.apache.sling.another.config [format=properties] + test=A + value=5 + + + +# Now artifacts, configurations and settings can be specified. All of them belong to +# the previous runMode definition +# +[artifacts startLevel=15 runModes=jackrabbit] + org.apache.derby/derby/10.5.3.0_1/jar + org.apache.sling/org.apache.sling.jcr.jackrabbit.server/2.1.3-SNAPSHOT/jar + + diff --git a/src/test/resources/main.txt b/src/test/resources/main.txt new file mode 100644 index 0000000..1afbc3f --- /dev/null +++ b/src/test/resources/main.txt @@ -0,0 +1,104 @@ +[feature name=main] + +[variables] + ws.version=1.0.2 + +[artifacts] + commons-io/commons-io/1.4/jar + commons-fileupload/commons-fileupload/1.3.1/jar + commons-collections/commons-collections/3.2.1/jar + commons-codec/commons-codec/1.9/jar + commons-lang/commons-lang/2.6/jar + org.apache.commons/commons-math/2.2/jar + commons-pool/commons-pool/1.6/jar + org.apache.servicemix.bundles/org.apache.servicemix.bundles.concurrent/1.3.4_1/jar + org.apache.geronimo.bundles/commons-httpclient/3.1_1/jar + org.apache.sling/org.apache.sling.commons.osgi/2.2.2/jar + org.apache.sling/org.apache.sling.commons.mime/2.1.8/jar + org.apache.sling/org.apache.sling.commons.classloader/1.3.2/jar + org.apache.sling/org.apache.sling.commons.compiler/2.2.0/jar + org.apache.sling/org.apache.sling.commons.scheduler/2.4.4/jar + org.apache.sling/org.apache.sling.commons.threads/3.2.0/jar + org.apache.sling/org.apache.sling.discovery.api/1.0.0/jar + org.apache.sling/org.apache.sling.discovery.support/1.0.0/jar + org.apache.sling/org.apache.sling.discovery.impl/1.0.10/jar + org.apache.sling/org.apache.sling.event/3.3.14/jar + org.apache.sling/org.apache.sling.api/2.8.0/jar + org.apache.sling/org.apache.sling.serviceusermapper/1.0.2/jar + org.apache.sling/org.apache.sling.resourceresolver/1.1.3-SNAPSHOT/jar + org.apache.sling/org.apache.sling.auth.core/1.2.0/jar + org.apache.sling/org.apache.sling.engine/2.3.5-SNAPSHOT/jar + org.apache.sling/org.apache.sling.auth.openid/1.0.4/jar + org.apache.sling/org.apache.sling.auth.form/1.0.6/jar + org.apache.sling/org.apache.sling.auth.selector/1.0.6/jar + org.apache.sling/org.apache.sling.adapter/2.1.1-SNAPSHOT/jar + org.apache.sling/org.apache.sling.servlets.resolver/2.3.2/jar + org.apache.sling/org.apache.sling.servlets.get/2.1.10/jar + org.apache.sling/org.apache.sling.servlets.post/2.3.6/jar + org.apache.sling/org.apache.sling.jcr.contentloader/2.1.8/jar + org.apache.sling/org.apache.sling.jcr.resource/2.3.8/jar + org.apache.sling/org.apache.sling.jcr.classloader/3.2.1-SNAPSHOT/jar + org.apache.sling/org.apache.sling.bundleresource.impl/2.2.0/jar + org.apache.sling/org.apache.sling.fsresource/1.1.4/jar + org.apache.sling/org.apache.sling.launchpad.content/2.0.8/jar + org.apache.sling/org.apache.sling.scripting.api/2.1.6/jar + org.apache.sling/org.apache.sling.scripting.core/2.0.27-SNAPSHOT/jar + org.apache.sling/org.apache.sling.scripting.javascript/2.0.12/jar + org.apache.sling/org.apache.sling.scripting.jsp/2.1.4/jar + org.apache.sling/org.apache.sling.scripting.jsp.taglib/2.2.2/jar + org.apache.geronimo.bundles/jstl/1.2_1/jar + org.apache.sling/org.apache.sling.models.api/1.1.0/jar + org.apache.sling/org.apache.sling.models.impl/1.1.0/jar + org.apache.felix/org.apache.felix.http.whiteboard/2.2.0/jar + org.apache.sling/org.apache.sling.installer.console/1.0.0/jar + org.apache.sling/org.apache.sling.installer.factory.configuration/1.0.14/jar + org.apache.sling/org.apache.sling.installer.provider.jcr/3.1.8/jar + +[artifacts startLevel=5] + org.apache.sling/org.apache.sling.extensions.webconsolebranding/1.0.0/jar + org.apache.sling/org.apache.sling.extensions.webconsolesecurityprovider/1.0.0/jar + org.apache.felix/org.apache.felix.inventory/1.0.4/jar + org.apache.felix/org.apache.felix.prefs/1.0.6/jar + org.apache.felix/org.apache.felix.webconsole/4.2.2/jar + org.apache.geronimo.bundles/json/20090211_1/jar + org.apache.felix/org.apache.felix.webconsole.plugins.ds/1.0.0/jar + org.apache.felix/org.apache.felix.webconsole.plugins.packageadmin/1.0.0/jar + org.apache.felix/org.apache.felix.webconsole.plugins.event/1.0.2/jar + org.apache.felix/org.apache.felix.webconsole.plugins.memoryusage/1.0.4/jar + org.apache.sling/org.apache.sling.commons.json/2.0.8/jar + org.apache.felix/org.apache.felix.bundlerepository/1.6.4/jar + org.apache.sling/org.apache.sling.extensions.threaddump/0.2.2/jar + org.apache.sling/org.apache.sling.jcr.webconsole/1.0.1-SNAPSHOT/jar + org.apache.sling/org.apache.sling.extensions.explorer/1.0.4/jar + org.apache.aries.jmx/org.apache.aries.jmx.api/1.1.0/jar + org.apache.aries/org.apache.aries.util/1.1.0/jar + org.apache.aries.jmx/org.apache.aries.jmx.core/1.1.1/jar + org.apache.aries.jmx/org.apache.aries.jmx.whiteboard/1.0.0/jar + +[artifacts startLevel=10] + org.apache.felix/org.apache.felix.scr/1.8.2/jar + org.apache.felix/org.apache.felix.metatype/1.0.10/jar + org.apache.tika/tika-core/1.2/jar + org.apache.tika/tika-bundle/1.2/jar + +[artifacts startLevel=15] + org.apache.sling/org.apache.sling.jcr.jcr-wrapper/2.0.0/jar + org.apache.sling/org.apache.sling.jcr.api/2.2.0/jar + org.apache.sling/org.apache.sling.jcr.base/2.2.2/jar + org.apache.sling/org.apache.sling.jcr.registration/1.0.1-SNAPSHOT/jar + org.apache.jackrabbit/jackrabbit-api/2.7.5/jar + org.apache.jackrabbit/jackrabbit-jcr-commons/2.7.5/jar + org.apache.jackrabbit/jackrabbit-spi/2.7.1/jar + org.apache.jackrabbit/jackrabbit-spi-commons/2.7.1/jar + org.apache.jackrabbit/jackrabbit-webdav/2.7.1/jar + org.apache.jackrabbit/jackrabbit-jcr-rmi/2.7.1/jar + org.apache.sling/org.apache.sling.jcr.webdav/2.2.2/jar + org.apache.sling/org.apache.sling.jcr.davex/1.2.1-SNAPSHOT/jar + org.apache.sling/org.apache.sling.jcr.jackrabbit.usermanager/2.2.1-SNAPSHOT/jar + org.apache.sling/org.apache.sling.jcr.jackrabbit.accessmanager/2.1.1-SNAPSHOT/jar + +[artifacts startLevel=15 runModes=jackrabbit] + org.apache.derby/derby/10.5.3.0_1/jar + org.apache.sling/org.apache.sling.jcr.jackrabbit.server/2.1.3-SNAPSHOT/jar + + diff --git a/src/test/resources/oak.txt b/src/test/resources/oak.txt new file mode 100644 index 0000000..936c2ac --- /dev/null +++ b/src/test/resources/oak.txt @@ -0,0 +1,19 @@ +# This is the OAK feature. +[feature name=oak] +# All bundles are defined to be started at start level 15 +# The segment node store is used via a configuration +[artifacts startLevel=15 runModes=oak] + org.apache.sling/org.apache.sling.jcr.oak.server/0.0.2-SNAPSHOT/jar + com.google.guava/guava/15.0/jar + org.apache.jackrabbit/oak-core/1.0.0/jar + org.apache.jackrabbit/oak-commons/1.0.0/jar + org.apache.jackrabbit/oak-mk/1.0.0/jar + org.apache.jackrabbit/oak-mk-api/1.0.0/jar + org.apache.jackrabbit/oak-mk-remote/1.0.0/jar + org.apache.jackrabbit/oak-lucene/1.0.0/jar + org.apache.jackrabbit/oak-blob/1.0.0/jar + +[configurations runModes=oak] + org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStoreService + name="Default\ NodeStore" + repository.home="sling/oak/repository" -- To stop receiving notification emails like this one, please contact "commits@sling.apache.org" <commits@sling.apache.org>.