diff --git a/cli/src/main/java/org/onosproject/cli/Comparators.java b/cli/src/main/java/org/onosproject/cli/Comparators.java index 764b227248..6efb1390d9 100644 --- a/cli/src/main/java/org/onosproject/cli/Comparators.java +++ b/cli/src/main/java/org/onosproject/cli/Comparators.java @@ -18,6 +18,7 @@ package org.onosproject.cli; import java.util.Comparator; import org.onosproject.cluster.ControllerNode; +import org.onosproject.core.Application; import org.onosproject.core.ApplicationId; import org.onosproject.net.ConnectPoint; import org.onosproject.net.Element; @@ -43,6 +44,13 @@ public final class Comparators { } }; + public static final Comparator APP_COMPARATOR = new Comparator() { + @Override + public int compare(Application app1, Application app2) { + return app1.id().id() - app2.id().id(); + } + }; + public static final Comparator ELEMENT_ID_COMPARATOR = new Comparator() { @Override public int compare(ElementId id1, ElementId id2) { diff --git a/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java b/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java index 2b90f66d5e..13d5cd8259 100644 --- a/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java +++ b/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java @@ -15,11 +15,19 @@ */ package org.onosproject.cli.app; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; import org.apache.karaf.shell.commands.Command; import org.onosproject.app.ApplicationService; import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.cli.Comparators; import org.onosproject.core.Application; +import java.util.Collections; +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; import static org.onosproject.app.ApplicationState.ACTIVE; /** @@ -36,11 +44,44 @@ public class ApplicationsListCommand extends AbstractShellCommand { @Override protected void execute() { ApplicationService service = get(ApplicationService.class); - for (Application app : service.getApplications()) { - print(FMT, service.getState(app.id()) == ACTIVE ? "*" : " ", - app.id().id(), app.id().name(), app.version(), app.origin(), - app.description(), app.features(), app.featuresRepo(), app.permissions()); + List apps = newArrayList(service.getApplications()); + Collections.sort(apps, Comparators.APP_COMPARATOR); + + if (outputJson()) { + print("%s", json(service, apps)); + } else { + for (Application app : apps) { + print(FMT, service.getState(app.id()) == ACTIVE ? "*" : " ", + app.id().id(), app.id().name(), app.version(), app.origin(), + app.description(), app.features(), + app.featuresRepo().isPresent() ? app.featuresRepo().get().toString() : "", + app.permissions()); + } } } + private JsonNode json(ApplicationService service, List apps) { + ObjectMapper mapper = new ObjectMapper(); + ArrayNode result = mapper.createArrayNode(); + for (Application app : apps) { + result.add(json(service, mapper, app)); + } + return result; + } + + protected JsonNode json(ApplicationService service, ObjectMapper mapper, + Application app) { + return mapper.createObjectNode() + .put("name", app.id().name()) + .put("id", app.id().id()) + .put("version", app.version().toString()) + .put("description", app.description()) + .put("origin", app.origin()) + .put("permissions", app.permissions().toString()) + .put("featuresRepo", app.featuresRepo().isPresent() ? + app.featuresRepo().get().toString() : "") + .put("features", app.features().toString()) + .put("state", service.getState(app.id()).toString()); + } + } diff --git a/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java b/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java index ec7958d631..64f04a618c 100644 --- a/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java +++ b/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java @@ -19,6 +19,7 @@ import org.onosproject.core.Permission; import org.onosproject.core.Version; import java.net.URI; +import java.util.List; import java.util.Optional; import java.util.Set; @@ -71,10 +72,10 @@ public interface ApplicationDescription { Optional featuresRepo(); /** - * Returns the set of features comprising the application. At least one + * Returns the list of features comprising the application. At least one * feature must be given. * * @return application features */ - Set features(); + List features(); } diff --git a/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java b/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java index 9c53542652..78b902b4b5 100644 --- a/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java +++ b/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java @@ -19,6 +19,7 @@ import org.onosproject.core.Permission; import org.onosproject.core.Version; import java.net.URI; +import java.util.List; import java.util.Optional; import java.util.Set; @@ -37,7 +38,7 @@ public class DefaultApplicationDescription implements ApplicationDescription { private final String origin; private final Set permissions; private final Optional featuresRepo; - private final Set features; + private final List features; /** * Creates a new application descriptor using the supplied data. @@ -53,7 +54,7 @@ public class DefaultApplicationDescription implements ApplicationDescription { public DefaultApplicationDescription(String name, Version version, String description, String origin, Set permissions, - URI featuresRepo, Set features) { + URI featuresRepo, List features) { this.name = checkNotNull(name, "Name cannot be null"); this.version = checkNotNull(version, "Version cannot be null"); this.description = checkNotNull(description, "Description cannot be null"); @@ -95,7 +96,7 @@ public class DefaultApplicationDescription implements ApplicationDescription { } @Override - public Set features() { + public List features() { return features; } diff --git a/core/api/src/main/java/org/onosproject/core/Application.java b/core/api/src/main/java/org/onosproject/core/Application.java index d876a67d20..da2be13a23 100644 --- a/core/api/src/main/java/org/onosproject/core/Application.java +++ b/core/api/src/main/java/org/onosproject/core/Application.java @@ -16,6 +16,7 @@ package org.onosproject.core; import java.net.URI; +import java.util.List; import java.util.Optional; import java.util.Set; @@ -68,10 +69,10 @@ public interface Application { Optional featuresRepo(); /** - * Returns the set of features comprising the application. At least one + * Returns the list of features comprising the application. At least one * feature must be given. * * @return application features */ - Set features(); + List features(); } diff --git a/core/api/src/main/java/org/onosproject/core/DefaultApplication.java b/core/api/src/main/java/org/onosproject/core/DefaultApplication.java index 4da85a5701..b765e70fd3 100644 --- a/core/api/src/main/java/org/onosproject/core/DefaultApplication.java +++ b/core/api/src/main/java/org/onosproject/core/DefaultApplication.java @@ -16,6 +16,7 @@ package org.onosproject.core; import java.net.URI; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -35,7 +36,7 @@ public class DefaultApplication implements Application { private final String origin; private final Set permissions; private final Optional featuresRepo; - private final Set features; + private final List features; /** * Creates a new application descriptor using the supplied data. @@ -51,7 +52,7 @@ public class DefaultApplication implements Application { public DefaultApplication(ApplicationId appId, Version version, String description, String origin, Set permissions, - Optional featuresRepo, Set features) { + Optional featuresRepo, List features) { this.appId = checkNotNull(appId, "ID cannot be null"); this.version = checkNotNull(version, "Version cannot be null"); this.description = checkNotNull(description, "Description cannot be null"); @@ -93,7 +94,7 @@ public class DefaultApplication implements Application { } @Override - public Set features() { + public List features() { return features; } diff --git a/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java b/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java index 70794273a2..3c33a7f33a 100644 --- a/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java +++ b/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java @@ -15,12 +15,14 @@ */ package org.onosproject.app; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import org.junit.Test; import org.onosproject.core.Permission; import org.onosproject.core.Version; import java.net.URI; +import java.util.List; import java.util.Set; import static org.junit.Assert.assertEquals; @@ -37,7 +39,7 @@ public class DefaultApplicationDescriptionTest { public static final String ORIGIN = "Circus"; public static final Set PERMS = ImmutableSet.of(); public static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features"); - public static final Set FEATURES = ImmutableSet.of("foo"); + public static final List FEATURES = ImmutableList.of("foo", "bar"); @Test public void basics() { diff --git a/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java index 61cb2e3420..0260863e05 100644 --- a/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java +++ b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java @@ -15,6 +15,7 @@ */ package org.onosproject.common.app; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.io.ByteStreams; import com.google.common.io.Files; @@ -40,6 +41,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.nio.file.NoSuchFileException; +import java.util.List; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -191,8 +193,7 @@ public class ApplicationArchive ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { if (entry.getName().equals(APP_XML)) { - byte[] data = new byte[(int) entry.getSize()]; - ByteStreams.readFully(zis, data); + byte[] data = ByteStreams.toByteArray(zis); XMLConfiguration cfg = new XMLConfiguration(); try { cfg.load(new ByteArrayInputStream(data)); @@ -209,6 +210,7 @@ public class ApplicationArchive private ApplicationDescription loadAppDescription(XMLConfiguration cfg) { cfg.setAttributeSplittingDisabled(true); + cfg.setDelimiterParsingDisabled(true); String name = cfg.getString(NAME); Version version = Version.version(cfg.getString(VERSION)); String desc = cfg.getString(DESCRIPTION); @@ -216,7 +218,7 @@ public class ApplicationArchive Set perms = ImmutableSet.of(); String featRepo = cfg.getString(FEATURES_REPO); URI featuresRepo = featRepo != null ? URI.create(featRepo) : null; - Set features = ImmutableSet.copyOf(cfg.getString(FEATURES).split(",")); + List features = ImmutableList.copyOf(cfg.getStringArray(FEATURES)); return new DefaultApplicationDescription(name, version, desc, origin, perms, featuresRepo, features); @@ -229,13 +231,14 @@ public class ApplicationArchive ZipEntry entry; File appDir = new File(appsDir, desc.name()); while ((entry = zis.getNextEntry()) != null) { - byte[] data = new byte[(int) entry.getSize()]; - ByteStreams.readFully(zis, data); - zis.closeEntry(); + if (!entry.isDirectory()) { + byte[] data = ByteStreams.toByteArray(zis); + zis.closeEntry(); - File file = new File(appDir, entry.getName()); - createParentDirs(file); - write(data, file); + File file = new File(appDir, entry.getName()); + createParentDirs(file); + write(data, file); + } } zis.close(); } diff --git a/tools/build/onos-package b/tools/build/onos-package index 5a528badeb..31551ea1f9 100755 --- a/tools/build/onos-package +++ b/tools/build/onos-package @@ -46,9 +46,16 @@ sed "s/\$KARAF_VERSION/$KARAF_VERSION/g" \ sed "s/\$KARAF_VERSION/$KARAF_VERSION/g" \ $ONOS_ROOT/tools/package/bin/onos > bin/onos -# Stage the ONOS bundles +# Stage the ONOS bundles, but only those that match the version mkdir -p $KARAF_DIST/system/org/onosproject -cp -r $M2_REPO/org/onosproject $KARAF_DIST/system/org/ +# cp -r $M2_REPO/org/onosproject/ $KARAF_DIST/system/org/ +find $M2_REPO/org/onosproject/ -type d -name $ONOS_POM_VERSION | while read line; do + path=${line#*/onosproject/} + artifact=${path%/$ONOS_POM_VERSION} + mkdir -p $KARAF_DIST/system/org/onosproject/$artifact + cp -r $M2_REPO/org/onosproject/$artifact/$ONOS_POM_VERSION \ + $KARAF_DIST/system/org/onosproject/$artifact/$ONOS_POM_VERSION +done export ONOS_FEATURES="${ONOS_FEATURES:-webconsole,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-openflow,onos-app-fwd,onos-app-foo}" diff --git a/web/api/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java b/web/api/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java index 7a148de531..4812154934 100644 --- a/web/api/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java +++ b/web/api/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java @@ -40,7 +40,7 @@ public final class ApplicationCodec extends JsonCodec { .put("origin", app.origin()) .put("permissions", app.permissions().toString()) .put("featuresRepo", app.featuresRepo().isPresent() ? - app.featuresRepo().toString() : "") + app.featuresRepo().get().toString() : "") .put("features", app.features().toString()) .put("state", service.getState(app.id()).toString()); return result; diff --git a/web/api/src/test/java/org/onosproject/rest/ApplicationsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/ApplicationsResourceTest.java index 132a739554..45ee612836 100644 --- a/web/api/src/test/java/org/onosproject/rest/ApplicationsResourceTest.java +++ b/web/api/src/test/java/org/onosproject/rest/ApplicationsResourceTest.java @@ -15,10 +15,11 @@ */ package org.onosproject.rest; -import java.io.InputStream; -import java.net.URI; -import java.util.Optional; - +import com.eclipsesource.json.JsonArray; +import com.eclipsesource.json.JsonObject; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.sun.jersey.api.client.WebResource; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.After; @@ -40,22 +41,14 @@ import org.onosproject.core.DefaultApplication; import org.onosproject.core.DefaultApplicationId; import org.onosproject.core.Version; -import com.eclipsesource.json.JsonArray; -import com.eclipsesource.json.JsonObject; -import com.google.common.collect.ImmutableSet; -import com.sun.jersey.api.client.WebResource; +import java.io.InputStream; +import java.net.URI; +import java.util.Optional; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.*; import static org.easymock.EasyMock.isA; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.*; /** * Unit tests for applications REST APIs. @@ -88,20 +81,20 @@ public class ApplicationsResourceTest extends ResourceTest { private Application app1 = new DefaultApplication(id1, VER, - "app1", "origin1", ImmutableSet.of(), Optional.of(FURL), - ImmutableSet.of("My Feature")); + "app1", "origin1", ImmutableSet.of(), Optional.of(FURL), + ImmutableList.of("My Feature")); private Application app2 = new DefaultApplication(id2, VER, - "app2", "origin2", ImmutableSet.of(), Optional.of(FURL), - ImmutableSet.of("My Feature")); + "app2", "origin2", ImmutableSet.of(), Optional.of(FURL), + ImmutableList.of("My Feature")); private Application app3 = new DefaultApplication(id3, VER, - "app3", "origin3", ImmutableSet.of(), Optional.of(FURL), - ImmutableSet.of("My Feature")); + "app3", "origin3", ImmutableSet.of(), Optional.of(FURL), + ImmutableList.of("My Feature")); private Application app4 = new DefaultApplication(id4, VER, - "app4", "origin4", ImmutableSet.of(), Optional.of(FURL), - ImmutableSet.of("My Feature")); + "app4", "origin4", ImmutableSet.of(), Optional.of(FURL), + ImmutableList.of("My Feature")); /** * Hamcrest matcher to check that an device representation in JSON matches