ONOS-542 Defining application subsystem interfaces & public constructs.
Change-Id: Iba0d2cb69dace5beee8a68def9918059ce755b5c
diff --git a/cli/src/main/java/org/onosproject/cli/ApplicationInstallCommand.java b/cli/src/main/java/org/onosproject/cli/ApplicationInstallCommand.java
new file mode 100644
index 0000000..f520804
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/ApplicationInstallCommand.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.cli;
+
+import org.apache.karaf.shell.commands.Command;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * Lists application ID information.
+ */
+@Command(scope = "onos", name = "app-install",
+ description = "Lists application ID information")
+public class ApplicationInstallCommand extends AbstractShellCommand {
+
+ @Override
+ protected void execute() {
+ // FIXME: merely an experiment for now
+ try (InputStreamReader isr = new InputStreamReader(System.in);
+ BufferedReader br = new BufferedReader(isr)) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ print("%s", line.toUpperCase());
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 1350a4a..5e4e98c 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -21,6 +21,10 @@
</command>
<command>
+ <action class="org.onosproject.cli.ApplicationInstallCommand"/>
+ </command>
+
+ <command>
<action class="org.onosproject.cli.MetricsListCommand"/>
</command>
diff --git a/core/api/src/main/java/org/onosproject/app/ApplicationAdminService.java b/core/api/src/main/java/org/onosproject/app/ApplicationAdminService.java
new file mode 100644
index 0000000..18babd5
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationAdminService.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.Permission;
+
+import java.io.InputStream;
+import java.util.Set;
+
+/**
+ * Service for managing network control applications.
+ */
+public interface ApplicationAdminService extends ApplicationService {
+
+ /**
+ * Installs the application contained in the specified application archive
+ * input stream.
+ *
+ * @param appDescStream application descriptor input stream
+ * @return installed application descriptor
+ * @throws org.onosproject.app.ApplicationException if unable to read the app archive stream
+ */
+ Application install(InputStream appDescStream);
+
+ /**
+ * Uninstalls the specified application.
+ *
+ * @param appId application identifier
+ */
+ void uninstall(ApplicationId appId);
+
+ /**
+ * Activates the specified application.
+ *
+ * @param appId application identifier
+ */
+ void activate(ApplicationId appId);
+
+ /**
+ * Deactivates the specified application.
+ *
+ * @param appId application identifier
+ */
+ void deactivate(ApplicationId appId);
+
+ /**
+ * Updates the permissions granted to the applications.
+ *
+ * @param appId application identifier
+ * @param permissions set of granted permissions
+ */
+ void setPermissions(ApplicationId appId, Set<Permission> permissions);
+}
diff --git a/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java b/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java
new file mode 100644
index 0000000..ec7958d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationDescription.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Permission;
+import org.onosproject.core.Version;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Description of a network control/management application.
+ */
+public interface ApplicationDescription {
+
+ /**
+ * Returns the application name id.
+ *
+ * @return application identifier
+ */
+ String name();
+
+ /**
+ * Returns the application version.
+ *
+ * @return application version
+ */
+ Version version();
+
+ /**
+ * Returns description of the application.
+ *
+ * @return application description text
+ */
+ String description();
+
+ /**
+ * Returns the name of the application origin, group or company.
+ *
+ * @return application origin
+ */
+ String origin();
+
+ /**
+ * Returns the permissions requested by the application.
+ *
+ * @return requested permissions
+ */
+ Set<Permission> permissions();
+
+ /**
+ * Returns the feature repository URI. Null value signifies that the
+ * application did not provide its own features repository.
+ *
+ * @return optional feature repo URL
+ */
+ Optional<URI> featuresRepo();
+
+ /**
+ * Returns the set of features comprising the application. At least one
+ * feature must be given.
+ *
+ * @return application features
+ */
+ Set<String> features();
+}
diff --git a/core/api/src/main/java/org/onosproject/app/ApplicationEvent.java b/core/api/src/main/java/org/onosproject/app/ApplicationEvent.java
new file mode 100644
index 0000000..5bf1323
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationEvent.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes application lifecycle event.
+ */
+public class ApplicationEvent extends AbstractEvent<ApplicationEvent.Type, Application> {
+
+ public enum Type {
+ /**
+ * Signifies that an application has been installed.
+ */
+ APP_INSTALLED,
+
+ /**
+ * Signifies that an application has been activated.
+ */
+ APP_ACTIVATED,
+
+ /**
+ * Signifies that an application has been deactivated.
+ */
+ APP_DEACTIVATED,
+
+ /**
+ * Signifies that an application has been uninstalled.
+ */
+ APP_UNINSTALLED,
+
+ /**
+ * Signifies that application granted permissions have changed.
+ */
+ APP_PERMISSIONS_CHANGED
+ }
+
+ /**
+ * Creates an event of a given type and for the specified app and the
+ * current time.
+ *
+ * @param type app event type
+ * @param app event app subject
+ */
+ public ApplicationEvent(Type type, Application app) {
+ super(type, app);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified app and time.
+ *
+ * @param type app event type
+ * @param app event app subject
+ * @param time occurrence time
+ */
+ public ApplicationEvent(Type type, Application app, long time) {
+ super(type, app, time);
+ }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/app/ApplicationException.java b/core/api/src/main/java/org/onosproject/app/ApplicationException.java
new file mode 100644
index 0000000..2888c70
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationException.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+/**
+ * Represents class of errors related to application management.
+ */
+public class ApplicationException extends RuntimeException {
+
+ private static final long serialVersionUID = -2287403908433720122L;
+
+ /**
+ * Constructs an exception with no message and no underlying cause.
+ */
+ public ApplicationException() {
+ }
+
+ /**
+ * Constructs an exception with the specified message.
+ *
+ * @param message the message describing the specific nature of the error
+ */
+ public ApplicationException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs an exception with the specified message and the underlying cause.
+ *
+ * @param message the message describing the specific nature of the error
+ * @param cause the underlying cause of this error
+ */
+ public ApplicationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java b/core/api/src/main/java/org/onosproject/app/ApplicationListener.java
similarity index 68%
copy from core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
copy to core/api/src/main/java/org/onosproject/app/ApplicationListener.java
index e39533c..7a68057 100644
--- a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.json.impl;
+package org.onosproject.app;
+
+import org.onosproject.event.EventListener;
/**
- * Created by tom on 10/16/14.
+ * Entity capable of receiving application related events.
*/
-public class DeleteMe {
+public interface ApplicationListener extends EventListener<ApplicationEvent> {
}
diff --git a/core/api/src/main/java/org/onosproject/app/ApplicationService.java b/core/api/src/main/java/org/onosproject/app/ApplicationService.java
new file mode 100644
index 0000000..1aaf092
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationService.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.Permission;
+
+import java.util.Set;
+
+/**
+ * Service for inspecting inventory of network control applications.
+ */
+public interface ApplicationService {
+
+ /**
+ * Returns the set of all installed applications.
+ *
+ * @return set of installed apps
+ */
+ Set<Application> getApplications();
+
+ /**
+ * Returns the registered id of the application with the given name.
+ *
+ * @param name application name
+ * @return registered application id
+ */
+ ApplicationId getId(String name);
+
+ /**
+ * Returns the application with the supplied application identifier.
+ *
+ * @param appId application identifier
+ * @return application descriptor
+ */
+ Application getApplication(ApplicationId appId);
+
+ /**
+ * Return the application state.
+ *
+ * @param appId application identifier
+ * @return application state
+ */
+ ApplicationState getState(ApplicationId appId);
+
+ /**
+ * Returns the permissions currently granted to the applications.
+ *
+ * @param appId application identifier
+ * @return set of granted permissions
+ */
+ Set<Permission> getPermissions(ApplicationId appId);
+
+ /**
+ * Adds the given listener for application lifecycle events.
+ *
+ * @param listener listener to be added
+ */
+ void addListener(ApplicationListener listener);
+
+ /**
+ * Removes the specified listener for application lifecycle events.
+ *
+ * @param listener listener to be removed
+ */
+ void removeListener(ApplicationListener listener);
+
+}
diff --git a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java b/core/api/src/main/java/org/onosproject/app/ApplicationState.java
similarity index 63%
copy from core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
copy to core/api/src/main/java/org/onosproject/app/ApplicationState.java
index e39533c..c480a0c 100644
--- a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationState.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.json.impl;
+package org.onosproject.app;
/**
- * Created by tom on 10/16/14.
+ * Representation of an application state.
*/
-public class DeleteMe {
+public enum ApplicationState {
+
+ /**
+ * Indicates that application has been installed, but is not running.
+ */
+ INSTALLED,
+
+ /**
+ * Indicates that application is active.
+ */
+ ACTIVE
+
}
diff --git a/core/api/src/main/java/org/onosproject/app/ApplicationStore.java b/core/api/src/main/java/org/onosproject/app/ApplicationStore.java
new file mode 100644
index 0000000..d20adb5
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationStore.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.Permission;
+import org.onosproject.store.Store;
+
+import java.io.InputStream;
+import java.util.Set;
+
+/**
+ * Service for managing network control applications.
+ */
+public interface ApplicationStore extends Store<ApplicationEvent, ApplicationStoreDelegate> {
+
+ /**
+ * Returns the set of all installed applications.
+ *
+ * @return set of installed apps
+ */
+ Set<Application> getApplications();
+
+ /**
+ * Returns the registered id of the application with the given name.
+ *
+ * @param name application name
+ * @return registered application id
+ */
+ ApplicationId getId(String name);
+
+ /**
+ * Returns the application with the supplied application identifier.
+ *
+ * @param appId application identifier
+ * @return application descriptor
+ */
+ Application getApplication(ApplicationId appId);
+
+ /**
+ * Returns the current application state.
+ *
+ * @param appId application identifier
+ * @return application state
+ */
+ ApplicationState getState(ApplicationId appId);
+
+ /**
+ * Creates the application from the specified application descriptor
+ * input stream.
+ *
+ * @param appDescStream application archive input stream
+ * @return application descriptor
+ */
+ Application create(InputStream appDescStream);
+
+ /**
+ * Removes the specified application.
+ *
+ * @param appId application identifier
+ */
+ void remove(ApplicationId appId);
+
+ /**
+ * Mark the application as actived.
+ *
+ * @param appId application identifier
+ */
+ void activate(ApplicationId appId);
+
+ /**
+ * Mark the application as deactivated.
+ *
+ * @param appId application identifier
+ */
+ void deactivate(ApplicationId appId);
+
+ /**
+ * Returns the permissions granted to the applications.
+ *
+ * @param appId application identifier
+ * @return set of granted permissions
+ */
+ Set<Permission> getPermissions(ApplicationId appId);
+
+ /**
+ * Updates the permissions granted to the applications.
+ *
+ * @param appId application identifier
+ * @param permissions set of granted permissions
+ */
+ void setPermissions(ApplicationId appId, Set<Permission> permissions);
+
+}
diff --git a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java b/core/api/src/main/java/org/onosproject/app/ApplicationStoreDelegate.java
similarity index 69%
copy from core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
copy to core/api/src/main/java/org/onosproject/app/ApplicationStoreDelegate.java
index e39533c..f339e68 100644
--- a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
+++ b/core/api/src/main/java/org/onosproject/app/ApplicationStoreDelegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.json.impl;
+package org.onosproject.app;
+
+import org.onosproject.store.StoreDelegate;
/**
- * Created by tom on 10/16/14.
+ * Application store delegate abstraction.
*/
-public class DeleteMe {
+public interface ApplicationStoreDelegate extends StoreDelegate<ApplicationEvent> {
}
diff --git a/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java b/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java
new file mode 100644
index 0000000..9c53542
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Permission;
+import org.onosproject.core.Version;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of network control/management application descriptor.
+ */
+public class DefaultApplicationDescription implements ApplicationDescription {
+
+ private final String name;
+ private final Version version;
+ private final String description;
+ private final String origin;
+ private final Set<Permission> permissions;
+ private final Optional<URI> featuresRepo;
+ private final Set<String> features;
+
+ /**
+ * Creates a new application descriptor using the supplied data.
+ *
+ * @param name application name
+ * @param version application version
+ * @param description application description
+ * @param origin origin company
+ * @param permissions requested permissions
+ * @param featuresRepo optional features repo URI
+ * @param features application features
+ */
+ public DefaultApplicationDescription(String name, Version version,
+ String description, String origin,
+ Set<Permission> permissions,
+ URI featuresRepo, Set<String> 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");
+ this.origin = checkNotNull(origin, "Origin cannot be null");
+ this.permissions = checkNotNull(permissions, "Permissions cannot be null");
+ this.featuresRepo = Optional.ofNullable(featuresRepo);
+ this.features = checkNotNull(features, "Features cannot be null");
+ checkArgument(!features.isEmpty(), "There must be at least one feature");
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public Version version() {
+ return version;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public String origin() {
+ return origin;
+ }
+
+ @Override
+ public Set<Permission> permissions() {
+ return permissions;
+ }
+
+ @Override
+ public Optional<URI> featuresRepo() {
+ return featuresRepo;
+ }
+
+ @Override
+ public Set<String> features() {
+ return features;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("name", name)
+ .add("version", version)
+ .add("description", description)
+ .add("origin", origin)
+ .add("permissions", permissions)
+ .add("featuresRepo", featuresRepo)
+ .add("features", features)
+ .toString();
+ }
+}
diff --git a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java b/core/api/src/main/java/org/onosproject/app/package-info.java
similarity index 79%
copy from core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
copy to core/api/src/main/java/org/onosproject/app/package-info.java
index e39533c..f8e5465 100644
--- a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
+++ b/core/api/src/main/java/org/onosproject/app/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.json.impl;
/**
- * Created by tom on 10/16/14.
+ * Set of abstractions for managing network control applications.
*/
-public class DeleteMe {
-}
+package org.onosproject.app;
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/core/Application.java b/core/api/src/main/java/org/onosproject/core/Application.java
new file mode 100644
index 0000000..d876a67
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/core/Application.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.core;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Abstraction of a network control/management application.
+ */
+public interface Application {
+
+ /**
+ * Returns the application name id.
+ *
+ * @return application identifier
+ */
+ ApplicationId id();
+
+ /**
+ * Returns the application version.
+ *
+ * @return application version
+ */
+ Version version();
+
+ /**
+ * Returns description of the application.
+ *
+ * @return application description text
+ */
+ String description();
+
+ /**
+ * Returns the name of the application origin, group or company.
+ *
+ * @return application origin
+ */
+ String origin();
+
+ /**
+ * Returns the permissions requested by the application.
+ *
+ * @return requested permissions
+ */
+ Set<Permission> permissions();
+
+ /**
+ * Returns the feature repository URI. Null value signifies that the
+ * application did not provide its own features repository.
+ *
+ * @return optional feature repo URL
+ */
+ Optional<URI> featuresRepo();
+
+ /**
+ * Returns the set of features comprising the application. At least one
+ * feature must be given.
+ *
+ * @return application features
+ */
+ Set<String> features();
+}
diff --git a/core/api/src/main/java/org/onosproject/core/ApplicationIdStore.java b/core/api/src/main/java/org/onosproject/core/ApplicationIdStore.java
index cef3f15..2236fc5 100644
--- a/core/api/src/main/java/org/onosproject/core/ApplicationIdStore.java
+++ b/core/api/src/main/java/org/onosproject/core/ApplicationIdStore.java
@@ -14,6 +14,7 @@
* limitations under the License.
*/
package org.onosproject.core;
+// FIXME: Move to org.onosproject.app package
import java.util.Set;
@@ -31,12 +32,21 @@
/**
* Returns an existing application id from a given id.
+ *
* @param id the short value of the id
- * @return an application id
+ * @return an application id; null if no such app registered
*/
ApplicationId getAppId(Short id);
/**
+ * Returns registered application id from the given name.
+ *
+ * @param name application name
+ * @return an application id; null if no such app registered
+ */
+ ApplicationId getAppId(String name);
+
+ /**
* Registers a new application by its name, which is expected
* to follow the reverse DNS convention, e.g.
* {@code org.flying.circus.app}
diff --git a/core/api/src/main/java/org/onosproject/core/DefaultApplication.java b/core/api/src/main/java/org/onosproject/core/DefaultApplication.java
new file mode 100644
index 0000000..4da85a5
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/core/DefaultApplication.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.core;
+
+import java.net.URI;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default implementation of network control/management application descriptor.
+ */
+public class DefaultApplication implements Application {
+
+ private final ApplicationId appId;
+ private final Version version;
+ private final String description;
+ private final String origin;
+ private final Set<Permission> permissions;
+ private final Optional<URI> featuresRepo;
+ private final Set<String> features;
+
+ /**
+ * Creates a new application descriptor using the supplied data.
+ *
+ * @param appId application identifier
+ * @param version application version
+ * @param description application description
+ * @param origin origin company
+ * @param permissions requested permissions
+ * @param featuresRepo optional features repo URI
+ * @param features application features
+ */
+ public DefaultApplication(ApplicationId appId, Version version,
+ String description, String origin,
+ Set<Permission> permissions,
+ Optional<URI> featuresRepo, Set<String> 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");
+ this.origin = checkNotNull(origin, "Origin cannot be null");
+ this.permissions = checkNotNull(permissions, "Permissions cannot be null");
+ this.featuresRepo = checkNotNull(featuresRepo, "Features repo cannot be null");
+ this.features = checkNotNull(features, "Features cannot be null");
+ checkArgument(!features.isEmpty(), "There must be at least one feature");
+ }
+
+ @Override
+ public ApplicationId id() {
+ return appId;
+ }
+
+ @Override
+ public Version version() {
+ return version;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public String origin() {
+ return origin;
+ }
+
+ @Override
+ public Set<Permission> permissions() {
+ return permissions;
+ }
+
+ @Override
+ public Optional<URI> featuresRepo() {
+ return featuresRepo;
+ }
+
+ @Override
+ public Set<String> features() {
+ return features;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(appId, version, description, origin, permissions,
+ featuresRepo, features);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final DefaultApplication other = (DefaultApplication) obj;
+ return Objects.equals(this.appId, other.appId) &&
+ Objects.equals(this.version, other.version) &&
+ Objects.equals(this.description, other.description) &&
+ Objects.equals(this.origin, other.origin) &&
+ Objects.equals(this.permissions, other.permissions) &&
+ Objects.equals(this.featuresRepo, other.featuresRepo) &&
+ Objects.equals(this.features, other.features);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("appId", appId)
+ .add("version", version)
+ .add("description", description)
+ .add("origin", origin)
+ .add("permissions", permissions)
+ .add("featuresRepo", featuresRepo)
+ .add("features", features)
+ .toString();
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java b/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java
index e6f448e..3a07b2b 100644
--- a/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java
+++ b/core/api/src/main/java/org/onosproject/core/DefaultApplicationId.java
@@ -18,6 +18,7 @@
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
/**
* Application identifier.
@@ -33,8 +34,9 @@
* @param id application identifier
* @param name application name
*/
- public DefaultApplicationId(Short id, String name) {
- this.id = id;
+ public DefaultApplicationId(int id, String name) {
+ checkArgument(0 <= id && id <= Short.MAX_VALUE, "id is outside range");
+ this.id = (short) id;
this.name = name;
}
diff --git a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java b/core/api/src/main/java/org/onosproject/core/Permission.java
similarity index 75%
copy from core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
copy to core/api/src/main/java/org/onosproject/core/Permission.java
index e39533c..d32d059 100644
--- a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
+++ b/core/api/src/main/java/org/onosproject/core/Permission.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.json.impl;
+package org.onosproject.core;
/**
- * Created by tom on 10/16/14.
+ * Representation of an application permission.
*/
-public class DeleteMe {
+public interface Permission {
+ // TODO: to be fleshed out
}
diff --git a/core/api/src/test/java/org/onosproject/app/ApplicationAdminServiceAdapter.java b/core/api/src/test/java/org/onosproject/app/ApplicationAdminServiceAdapter.java
new file mode 100644
index 0000000..4e5ccf8
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/app/ApplicationAdminServiceAdapter.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.Permission;
+
+import java.io.InputStream;
+import java.util.Set;
+
+/**
+ * Adapter for testing against application admin service.
+ */
+public class ApplicationAdminServiceAdapter extends ApplicationServiceAdapter
+ implements ApplicationAdminService {
+ @Override
+ public Set<Application> getApplications() {
+ return null;
+ }
+
+ @Override
+ public Application getApplication(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public ApplicationState getState(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public Set<Permission> getPermissions(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public void addListener(ApplicationListener listener) {
+ }
+
+ @Override
+ public void removeListener(ApplicationListener listener) {
+ }
+
+ @Override
+ public Application install(InputStream appDescStream) {
+ return null;
+ }
+
+ @Override
+ public void uninstall(ApplicationId appId) {
+ }
+
+ @Override
+ public void activate(ApplicationId appId) {
+ }
+
+ @Override
+ public void deactivate(ApplicationId appId) {
+ }
+
+ @Override
+ public void setPermissions(ApplicationId appId, Set<Permission> permissions) {
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java b/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java
new file mode 100644
index 0000000..4a882c3
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.junit.Test;
+import org.onosproject.core.Application;
+import org.onosproject.core.DefaultApplication;
+import org.onosproject.event.AbstractEventTest;
+
+import java.util.Optional;
+
+import static org.onosproject.app.ApplicationEvent.Type.APP_ACTIVATED;
+import static org.onosproject.app.DefaultApplicationDescriptionTest.*;
+import static org.onosproject.core.DefaultApplicationTest.APP_ID;
+
+/**
+ * Test of the application event.
+ */
+public class ApplicationEventTest extends AbstractEventTest {
+
+ private Application createApp() {
+ return new DefaultApplication(APP_ID, VER, DESC, ORIGIN,
+ PERMS, Optional.of(FURL), FEATURES);
+ }
+
+ @Test
+ public void withoutTime() {
+ Application app = createApp();
+ ApplicationEvent event = new ApplicationEvent(APP_ACTIVATED, app, 123L);
+ validateEvent(event, APP_ACTIVATED, app, 123L);
+ }
+
+ @Test
+ public void withTime() {
+ Application app = createApp();
+ long before = System.currentTimeMillis();
+ ApplicationEvent event = new ApplicationEvent(APP_ACTIVATED, app);
+ long after = System.currentTimeMillis();
+ validateEvent(event, APP_ACTIVATED, app, before, after);
+ }
+
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/app/ApplicationExceptionTest.java b/core/api/src/test/java/org/onosproject/app/ApplicationExceptionTest.java
new file mode 100644
index 0000000..a0c7ef1
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/app/ApplicationExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onlab.junit.ExceptionTest;
+
+public class ApplicationExceptionTest extends ExceptionTest {
+
+ @Override
+ protected Exception getDefault() {
+ return new ApplicationException();
+ }
+
+ @Override
+ protected Exception getWithMessage() {
+ return new ApplicationException(MESSAGE);
+ }
+
+ @Override
+ protected Exception getWithMessageAndCause() {
+ return new ApplicationException(MESSAGE, CAUSE);
+ }
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/app/ApplicationServiceAdapter.java b/core/api/src/test/java/org/onosproject/app/ApplicationServiceAdapter.java
new file mode 100644
index 0000000..ff1822a
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/app/ApplicationServiceAdapter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.Permission;
+
+import java.util.Set;
+
+/**
+ * Adapter for testing against application service.
+ */
+public class ApplicationServiceAdapter implements ApplicationService {
+ @Override
+ public Set<Application> getApplications() {
+ return null;
+ }
+
+ @Override
+ public ApplicationId getId(String name) {
+ return null;
+ }
+
+ @Override
+ public Application getApplication(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public ApplicationState getState(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public Set<Permission> getPermissions(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public void addListener(ApplicationListener listener) {
+ }
+
+ @Override
+ public void removeListener(ApplicationListener listener) {
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/app/ApplicationStoreAdapter.java b/core/api/src/test/java/org/onosproject/app/ApplicationStoreAdapter.java
new file mode 100644
index 0000000..265c2a6
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/app/ApplicationStoreAdapter.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.Permission;
+import org.onosproject.store.AbstractStore;
+
+import java.io.InputStream;
+import java.util.Set;
+
+/**
+ * Adapter for application testing against application store.
+ */
+public class ApplicationStoreAdapter
+ extends AbstractStore<ApplicationEvent, ApplicationStoreDelegate>
+ implements ApplicationStore {
+ @Override
+ public Set<Application> getApplications() {
+ return null;
+ }
+
+ @Override
+ public ApplicationId getId(String name) {
+ return null;
+ }
+
+ @Override
+ public Application getApplication(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public ApplicationState getState(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public Application create(InputStream appDescStream) {
+ return null;
+ }
+
+ @Override
+ public void remove(ApplicationId appId) {
+ }
+
+ @Override
+ public void activate(ApplicationId appId) {
+ }
+
+ @Override
+ public void deactivate(ApplicationId appId) {
+ }
+
+ @Override
+ public Set<Permission> getPermissions(ApplicationId appId) {
+ return null;
+ }
+
+ @Override
+ public void setPermissions(ApplicationId appId, Set<Permission> permissions) {
+ }
+
+}
diff --git a/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java b/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java
new file mode 100644
index 0000000..7079427
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app;
+
+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.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Basic tests of the default app description.
+ */
+public class DefaultApplicationDescriptionTest {
+
+ public static final String APP_NAME = "org.foo.app";
+ public static final Version VER = Version.version(1, 2, "a", null);
+ public static final String DESC = "Awesome application from Circus";
+ public static final String ORIGIN = "Circus";
+ public static final Set<Permission> PERMS = ImmutableSet.of();
+ public static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features");
+ public static final Set<String> FEATURES = ImmutableSet.of("foo");
+
+ @Test
+ public void basics() {
+ ApplicationDescription app =
+ new DefaultApplicationDescription(APP_NAME, VER, DESC, ORIGIN,
+ PERMS, FURL, FEATURES);
+ assertEquals("incorrect id", APP_NAME, app.name());
+ assertEquals("incorrect version", VER, app.version());
+ assertEquals("incorrect description", DESC, app.description());
+ assertEquals("incorrect origin", ORIGIN, app.origin());
+ assertEquals("incorrect permissions", PERMS, app.permissions());
+ assertEquals("incorrect features repo", FURL, app.featuresRepo().get());
+ assertEquals("incorrect features", FEATURES, app.features());
+ assertTrue("incorrect toString", app.toString().contains(APP_NAME));
+ }
+
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/core/ApplicationIdStoreAdapter.java b/core/api/src/test/java/org/onosproject/core/ApplicationIdStoreAdapter.java
new file mode 100644
index 0000000..c3d0f23
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/core/ApplicationIdStoreAdapter.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.core;
+
+import java.util.Set;
+
+/**
+ * Adapter for testing against app id store.
+ */
+public class ApplicationIdStoreAdapter implements ApplicationIdStore {
+ @Override
+ public Set<ApplicationId> getAppIds() {
+ return null;
+ }
+
+ @Override
+ public ApplicationId getAppId(Short id) {
+ return null;
+ }
+
+ @Override
+ public ApplicationId getAppId(String name) {
+ return null;
+ }
+
+ @Override
+ public ApplicationId registerApplication(String identifier) {
+ return null;
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java b/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java
new file mode 100644
index 0000000..ed0fe6d
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.core;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.app.DefaultApplicationDescriptionTest.*;
+
+/**
+ * Basic tests of the default app descriptor.
+ */
+public class DefaultApplicationTest {
+
+ public static final ApplicationId APP_ID = new DefaultApplicationId(2, APP_NAME);
+
+ @Test
+ public void basics() {
+ Application app = new DefaultApplication(APP_ID, VER, DESC, ORIGIN,
+ PERMS, Optional.of(FURL), FEATURES);
+ assertEquals("incorrect id", APP_ID, app.id());
+ assertEquals("incorrect version", VER, app.version());
+ assertEquals("incorrect description", DESC, app.description());
+ assertEquals("incorrect origin", ORIGIN, app.origin());
+ assertEquals("incorrect permissions", PERMS, app.permissions());
+ assertEquals("incorrect features repo", FURL, app.featuresRepo().get());
+ assertEquals("incorrect features", FEATURES, app.features());
+ assertTrue("incorrect toString", app.toString().contains(APP_NAME));
+ }
+
+ @Test
+ public void testEquality() {
+ Application a1 = new DefaultApplication(APP_ID, VER, DESC, ORIGIN,
+ PERMS, Optional.of(FURL), FEATURES);
+ Application a2 = new DefaultApplication(APP_ID, VER, DESC, ORIGIN,
+ PERMS, Optional.of(FURL), FEATURES);
+ Application a3 = new DefaultApplication(APP_ID, VER, DESC, ORIGIN,
+ PERMS, Optional.empty(), FEATURES);
+ Application a4 = new DefaultApplication(APP_ID, VER, DESC, ORIGIN + "asd",
+ PERMS, Optional.of(FURL), FEATURES);
+ new EqualsTester().addEqualityGroup(a1, a2)
+ .addEqualityGroup(a3).addEqualityGroup(a4).testEquals();
+ }
+
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/core/UnavailableIdExceptionTest.java b/core/api/src/test/java/org/onosproject/core/UnavailableIdExceptionTest.java
new file mode 100644
index 0000000..ac565d8
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/core/UnavailableIdExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.core;
+
+import org.onlab.junit.ExceptionTest;
+
+public class UnavailableIdExceptionTest extends ExceptionTest {
+
+ @Override
+ protected Exception getDefault() {
+ return new UnavailableIdException();
+ }
+
+ @Override
+ protected Exception getWithMessage() {
+ return new UnavailableIdException(MESSAGE);
+ }
+
+ @Override
+ protected Exception getWithMessageAndCause() {
+ return new UnavailableIdException(MESSAGE, CAUSE);
+ }
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentOperationsTest.java b/core/api/src/test/java/org/onosproject/net/intent/IntentOperationsTest.java
index ec0ddae..484a44a 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentOperationsTest.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentOperationsTest.java
@@ -45,7 +45,7 @@
final TrafficSelector selector = new IntentTestsMocks.MockSelector();
final IntentTestsMocks.MockTreatment treatment = new IntentTestsMocks.MockTreatment();
- private final ApplicationId appId = new DefaultApplicationId((short) 1, "IntentOperationsTest");
+ private final ApplicationId appId = new DefaultApplicationId(1, "IntentOperationsTest");
private Intent intent;
protected IdGenerator idGenerator = new MockIdGenerator();
diff --git a/core/json/pom.xml b/core/common/pom.xml
similarity index 84%
rename from core/json/pom.xml
rename to core/common/pom.xml
index d9a84c1..8c5b80f 100644
--- a/core/json/pom.xml
+++ b/core/common/pom.xml
@@ -26,16 +26,17 @@
<relativePath>../pom.xml</relativePath>
</parent>
- <artifactId>onos-json</artifactId>
+ <artifactId>onos-core-common</artifactId>
<packaging>bundle</packaging>
- <description>ONOS JSON encode/decode facilities</description>
+ <description>ONOS utilities common to the core modules</description>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
</dependency>
+
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
@@ -44,13 +45,17 @@
</dependency>
<dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-core-trivial</artifactId>
- <version>${project.version}</version>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
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
new file mode 100644
index 0000000..90e6005
--- /dev/null
+++ b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.common.app;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.io.ByteStreams;
+import com.google.common.io.Files;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.onlab.util.Tools;
+import org.onosproject.app.ApplicationDescription;
+import org.onosproject.app.ApplicationEvent;
+import org.onosproject.app.ApplicationException;
+import org.onosproject.app.ApplicationStoreDelegate;
+import org.onosproject.app.DefaultApplicationDescription;
+import org.onosproject.core.Permission;
+import org.onosproject.core.Version;
+import org.onosproject.store.AbstractStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import static com.google.common.io.ByteStreams.toByteArray;
+import static com.google.common.io.Files.createParentDirs;
+import static com.google.common.io.Files.write;
+
+/**
+ * Facility for reading application archive stream and managing application
+ * directory structure.
+ */
+public class ApplicationArchive
+ extends AbstractStore<ApplicationEvent, ApplicationStoreDelegate> {
+
+ private static final String NAME = "[@name]";
+ private static final String ORIGIN = "[@origin]";
+ private static final String VERSION = "[@version]";
+ private static final String FEATURES_REPO = "[@featuresRepo]";
+ private static final String FEATURES = "[@features]";
+ private static final String DESCRIPTION = "description";
+
+ private static Logger log = LoggerFactory.getLogger(ApplicationArchive.class);
+ private static final String APP_XML = "app.xml";
+ private static final String APPS_ROOT = "data/apps/";
+
+ private File appsDir = new File(APPS_ROOT);
+
+ /**
+ * Sets the root directory where application artifacts are kept.
+ *
+ * @param appsRoot top-level applications directory path
+ */
+ protected void setAppsRoot(String appsRoot) {
+ this.appsDir = new File(appsRoot);
+ }
+
+ /**
+ * Returns the root directory where application artifacts are kept.
+ *
+ * @return top-level applications directory path
+ */
+ protected String getAppsRoot() {
+ return appsDir.getPath();
+ }
+
+ /**
+ * Returns the set of installed application names.
+ *
+ * @return installed application names
+ */
+ public Set<String> getApplicationNames() {
+ ImmutableSet.Builder<String> names = ImmutableSet.builder();
+ File[] files = appsDir.listFiles(File::isDirectory);
+ if (files != null) {
+ for (File file : files) {
+ names.add(file.getName());
+ }
+ }
+ return names.build();
+ }
+
+ /**
+ * Loads the application descriptor from the specified application archive
+ * stream and saves the stream in the appropriate application archive
+ * directory.
+ *
+ * @param appName application name
+ * @return application descriptor
+ * @throws org.onosproject.app.ApplicationException if unable to read application description
+ */
+ public ApplicationDescription getApplicationDescription(String appName) {
+ try {
+ return loadAppDescription(new XMLConfiguration(appFile(appName, APP_XML)));
+ } catch (Exception e) {
+ throw new ApplicationException("Unable to get app description", e);
+ }
+ }
+
+ /**
+ * Loads the application descriptor from the specified application archive
+ * stream and saves the stream in the appropriate application archive
+ * directory.
+ *
+ * @param stream application archive stream
+ * @return application descriptor
+ * @throws org.onosproject.app.ApplicationException if unable to read the
+ * archive stream or store
+ * the application archive
+ */
+ public ApplicationDescription saveApplication(InputStream stream) {
+ try (InputStream ais = stream) {
+ byte[] cache = toByteArray(ais);
+ InputStream bis = new ByteArrayInputStream(cache);
+ ApplicationDescription desc = parseAppDescription(bis);
+ bis.reset();
+
+ expandApplication(bis, desc);
+ bis.reset();
+
+ saveApplication(bis, desc);
+ installArtifacts(desc);
+ return desc;
+ } catch (IOException e) {
+ throw new ApplicationException("Unable to save application", e);
+ }
+ }
+
+ /**
+ * Purges the application archive directory.
+ *
+ * @param appName application name
+ */
+ public void purgeApplication(String appName) {
+ try {
+ Tools.removeDirectory(new File(appsDir, appName));
+ } catch (IOException e) {
+ throw new ApplicationException("Unable to purge application " + appName, e);
+ }
+ }
+
+ /**
+ * Returns application archive stream for the specified application.
+ *
+ * @param appName application name
+ * @return application archive stream
+ */
+ public InputStream getApplicationInputStream(String appName) {
+ try {
+ return new FileInputStream(appFile(appName, appName + ".zip"));
+ } catch (FileNotFoundException e) {
+ throw new ApplicationException("Application " + appName + " not found");
+ }
+ }
+
+ // Scans the specified ZIP stream for app.xml entry and parses it producing
+ // an application descriptor.
+ private ApplicationDescription parseAppDescription(InputStream stream)
+ throws IOException {
+ try (ZipInputStream zis = new ZipInputStream(stream)) {
+ ZipEntry entry;
+ while ((entry = zis.getNextEntry()) != null) {
+ if (entry.getName().equals(APP_XML)) {
+ byte[] data = new byte[(int) entry.getSize()];
+ ByteStreams.readFully(zis, data);
+ XMLConfiguration cfg = new XMLConfiguration();
+ try {
+ cfg.load(new ByteArrayInputStream(data));
+ return loadAppDescription(cfg);
+ } catch (ConfigurationException e) {
+ throw new IOException("Unable to parse " + APP_XML, e);
+ }
+ }
+ zis.closeEntry();
+ }
+ }
+ throw new IOException("Unable to locate " + APP_XML);
+ }
+
+ private ApplicationDescription loadAppDescription(XMLConfiguration cfg) {
+ cfg.setAttributeSplittingDisabled(true);
+ String name = cfg.getString(NAME);
+ Version version = Version.version(cfg.getString(VERSION));
+ String desc = cfg.getString(DESCRIPTION);
+ String origin = cfg.getString(ORIGIN);
+ Set<Permission> perms = ImmutableSet.of();
+ String featRepo = cfg.getString(FEATURES_REPO);
+ URI featuresRepo = featRepo != null ? URI.create(featRepo) : null;
+ Set<String> features = ImmutableSet.copyOf(cfg.getString(FEATURES).split(","));
+
+ return new DefaultApplicationDescription(name, version, desc, origin,
+ perms, featuresRepo, features);
+ }
+
+ // Expands the specified ZIP stream into app-specific directory.
+ private void expandApplication(InputStream stream, ApplicationDescription desc)
+ throws IOException {
+ ZipInputStream zis = new ZipInputStream(stream);
+ 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();
+
+ File file = new File(appDir, entry.getName());
+ createParentDirs(file);
+ write(data, file);
+ }
+ zis.close();
+ }
+
+ // Saves the specified ZIP stream into a file under app-specific directory.
+ private void saveApplication(InputStream stream, ApplicationDescription desc)
+ throws IOException {
+ Files.write(toByteArray(stream), appFile(desc.name(), desc.name() + ".zip"));
+ }
+
+ // Installs application artifacts into M2 repository.
+ private void installArtifacts(ApplicationDescription desc) {
+ // FIXME: implement M2 repository copy
+ }
+
+ protected boolean setActive(String appName) {
+ try {
+ return appFile(appName, "active").createNewFile();
+ } catch (IOException e) {
+ throw new ApplicationException("Unable to mark app as active", e);
+ }
+ }
+
+ protected boolean clearActive(String appName) {
+ return appFile(appName, "active").delete();
+ }
+
+ protected boolean isActive(String appName) {
+ return appFile(appName, "active").exists();
+ }
+
+
+ // Returns the name of the file located under the specified app directory.
+ private File appFile(String appName, String fileName) {
+ return new File(new File(appsDir, appName), fileName);
+ }
+
+}
diff --git a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java b/core/common/src/main/java/org/onosproject/common/app/package-info.java
similarity index 78%
copy from core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
copy to core/common/src/main/java/org/onosproject/common/app/package-info.java
index e39533c..898bad7 100644
--- a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
+++ b/core/common/src/main/java/org/onosproject/common/app/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.json.impl;
/**
- * Created by tom on 10/16/14.
+ * Common facilities for construction of application management subsystem.
*/
-public class DeleteMe {
-}
+package org.onosproject.common.app;
\ No newline at end of file
diff --git a/core/common/src/test/java/org/onosproject/common/app/ApplicationArchiveTest.java b/core/common/src/test/java/org/onosproject/common/app/ApplicationArchiveTest.java
new file mode 100644
index 0000000..c1b8e82
--- /dev/null
+++ b/core/common/src/test/java/org/onosproject/common/app/ApplicationArchiveTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.common.app;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.io.ByteStreams;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.app.ApplicationDescription;
+import org.onosproject.app.ApplicationException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Set;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.onosproject.app.DefaultApplicationDescriptionTest.*;
+
+public class ApplicationArchiveTest {
+
+ static final String ROOT = "/tmp/app-junit";
+
+ private ApplicationArchive aar = new ApplicationArchive();
+
+ @Before
+ public void setUp() {
+ aar.setAppsRoot(ROOT);
+ }
+
+ private void validate(ApplicationDescription app) {
+ assertEquals("incorrect name", APP_NAME, app.name());
+ assertEquals("incorrect version", VER, app.version());
+ assertEquals("incorrect origin", ORIGIN, app.origin());
+
+ assertEquals("incorrect description", DESC, app.description());
+ assertEquals("incorrect features URI", FURL, app.featuresRepo().get());
+ assertEquals("incorrect permissions", PERMS, app.permissions());
+ assertEquals("incorrect features", FEATURES, app.features());
+ }
+
+ @Test
+ public void saveApp() throws IOException {
+ InputStream stream = getClass().getResourceAsStream("app.zip");
+ ApplicationDescription app = aar.saveApplication(stream);
+ validate(app);
+ }
+
+ @Test
+ public void loadApp() throws IOException {
+ saveApp();
+ ApplicationDescription app = aar.getApplicationDescription(APP_NAME);
+ validate(app);
+ }
+
+ @Test
+ public void getAppNames() throws IOException {
+ saveApp();
+ Set<String> names = aar.getApplicationNames();
+ assertEquals("incorrect names", ImmutableSet.of(APP_NAME), names);
+ }
+
+ @Test
+ public void purgeApp() throws IOException {
+ saveApp();
+ aar.purgeApplication(APP_NAME);
+ assertEquals("incorrect names", ImmutableSet.of(), aar.getApplicationNames());
+ }
+
+ @Test
+ public void getAppStream() throws IOException {
+ saveApp();
+ InputStream stream = aar.getApplicationInputStream(APP_NAME);
+ byte[] orig = ByteStreams.toByteArray(getClass().getResourceAsStream("app.zip"));
+ byte[] loaded = ByteStreams.toByteArray(stream);
+ assertArrayEquals("incorrect stream", orig, loaded);
+ }
+
+ @Test(expected = ApplicationException.class)
+ public void getBadAppDesc() throws IOException {
+ aar.getApplicationDescription("org.foo.BAD");
+ }
+
+ @Test(expected = ApplicationException.class)
+ public void getBadAppStream() throws IOException {
+ aar.getApplicationInputStream("org.foo.BAD");
+ }
+
+}
\ No newline at end of file
diff --git a/core/common/src/test/resources/org/onosproject/common/app/app.xml b/core/common/src/test/resources/org/onosproject/common/app/app.xml
new file mode 100644
index 0000000..3b8bc62
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/common/app/app.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ Copyright 2015 Open Networking Laboratory
+ ~
+ ~ Licensed 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.
+ -->
+<app name="org.foo.app" origin="Circus" version="1.2.a"
+ featuresRepo="mvn:org.foo-features/1.2a/xml/features"
+ features="foo,bar">
+ <description>Awesome application from Circus, Inc.</description>
+</app>
diff --git a/core/common/src/test/resources/org/onosproject/common/app/app.zip b/core/common/src/test/resources/org/onosproject/common/app/app.zip
new file mode 100644
index 0000000..07705e7
--- /dev/null
+++ b/core/common/src/test/resources/org/onosproject/common/app/app.zip
Binary files differ
diff --git a/core/json/src/main/java/org/onosproject/json/impl/package-info.java b/core/json/src/main/java/org/onosproject/json/impl/package-info.java
deleted file mode 100644
index 11fa30d..0000000
--- a/core/json/src/main/java/org/onosproject/json/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2014 Open Networking Laboratory
- *
- * Licensed 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.
- */
-
-/**
- * Implementation of JSON codec factory and of the builtin codecs.
- */
-package org.onosproject.json.impl;
diff --git a/core/net/pom.xml b/core/net/pom.xml
index 4150ec0..2bc6a60 100644
--- a/core/net/pom.xml
+++ b/core/net/pom.xml
@@ -52,6 +52,14 @@
</dependency>
<dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-common</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
@@ -66,6 +74,12 @@
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>org.apache.karaf.features.core</artifactId>
+ <version>3.0.2</version>
+ </dependency>
</dependencies>
<build>
diff --git a/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java b/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java
new file mode 100644
index 0000000..08c91a4
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/app/impl/ApplicationManager.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.karaf.features.FeaturesService;
+import org.onosproject.app.ApplicationAdminService;
+import org.onosproject.app.ApplicationEvent;
+import org.onosproject.app.ApplicationListener;
+import org.onosproject.app.ApplicationService;
+import org.onosproject.app.ApplicationState;
+import org.onosproject.app.ApplicationStore;
+import org.onosproject.app.ApplicationStoreDelegate;
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.Permission;
+import org.onosproject.event.AbstractListenerRegistry;
+import org.onosproject.event.EventDeliveryService;
+import org.slf4j.Logger;
+
+import java.io.InputStream;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.app.ApplicationEvent.Type.*;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of the application management service.
+ */
+@Component(immediate = true)
+@Service
+public class ApplicationManager implements ApplicationService, ApplicationAdminService {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String APP_ID_NULL = "Application ID cannot be null";
+
+ protected final AbstractListenerRegistry<ApplicationEvent, ApplicationListener>
+ listenerRegistry = new AbstractListenerRegistry<>();
+
+ private final ApplicationStoreDelegate delegate = new InternalStoreDelegate();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ApplicationStore store;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FeaturesService featuresService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected EventDeliveryService eventDispatcher;
+
+ @Activate
+ public void activate() {
+ store.setDelegate(delegate);
+ eventDispatcher.addSink(ApplicationEvent.class, listenerRegistry);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ store.unsetDelegate(delegate);
+ eventDispatcher.removeSink(ApplicationEvent.class);
+ log.info("Stopped");
+ }
+
+ @Override
+ public Set<Application> getApplications() {
+ return store.getApplications();
+ }
+
+ @Override
+ public ApplicationId getId(String name) {
+ checkNotNull(name, "Name cannot be null");
+ return store.getId(name);
+ }
+
+ @Override
+ public Application getApplication(ApplicationId appId) {
+ checkNotNull(appId, APP_ID_NULL);
+ return store.getApplication(appId);
+ }
+
+ @Override
+ public ApplicationState getState(ApplicationId appId) {
+ checkNotNull(appId, APP_ID_NULL);
+ return store.getState(appId);
+ }
+
+ @Override
+ public Set<Permission> getPermissions(ApplicationId appId) {
+ checkNotNull(appId, APP_ID_NULL);
+ return store.getPermissions(appId);
+ }
+
+ @Override
+ public Application install(InputStream appDescStream) {
+ checkNotNull(appDescStream, "Application archive stream cannot be null");
+ return store.create(appDescStream);
+ }
+
+ @Override
+ public void uninstall(ApplicationId appId) {
+ checkNotNull(appId, APP_ID_NULL);
+ try {
+ store.remove(appId);
+ } catch (Exception e) {
+ log.warn("Unable to purge application directory for {}", appId.name());
+ }
+ }
+
+ @Override
+ public void activate(ApplicationId appId) {
+ checkNotNull(appId, APP_ID_NULL);
+ store.activate(appId);
+ }
+
+ @Override
+ public void deactivate(ApplicationId appId) {
+ checkNotNull(appId, APP_ID_NULL);
+ store.deactivate(appId);
+ }
+
+ @Override
+ public void setPermissions(ApplicationId appId, Set<Permission> permissions) {
+ checkNotNull(appId, APP_ID_NULL);
+ checkNotNull(permissions, "Permissions cannot be null");
+ store.setPermissions(appId, permissions);
+ }
+
+ @Override
+ public void addListener(ApplicationListener listener) {
+ listenerRegistry.addListener(listener);
+ }
+
+ @Override
+ public void removeListener(ApplicationListener listener) {
+ listenerRegistry.removeListener(listener);
+ }
+
+ private class InternalStoreDelegate implements ApplicationStoreDelegate {
+ @Override
+ public void notify(ApplicationEvent event) {
+ ApplicationEvent.Type type = event.type();
+ Application app = event.subject();
+ try {
+ if (type == APP_ACTIVATED) {
+ installAppFeatures(app);
+ log.info("Application {} has been activated", app.id().name());
+
+ } else if (type == APP_DEACTIVATED) {
+ uninstallAppFeatures(app);
+ log.info("Application {} has been deactivated", app.id().name());
+
+ } else if (type == APP_INSTALLED) {
+ installAppArtifacts(app);
+ log.info("Application {} has been installed", app.id().name());
+
+ } else if (type == APP_UNINSTALLED) {
+ uninstallAppFeatures(app);
+ uninstallAppArtifacts(app);
+ log.info("Application {} has been uninstalled", app.id().name());
+
+ }
+ eventDispatcher.post(event);
+
+ } catch (Exception e) {
+ log.warn("Unable to perform operation on application " + app.id().name(), e);
+ }
+ }
+ }
+
+ private void installAppArtifacts(Application app) throws Exception {
+ if (app.featuresRepo().isPresent()) {
+ featuresService.addRepository(app.featuresRepo().get());
+ }
+ }
+
+ private void uninstallAppArtifacts(Application app) throws Exception {
+ if (app.featuresRepo().isPresent()) {
+ featuresService.removeRepository(app.featuresRepo().get());
+ }
+ }
+
+ private void installAppFeatures(Application app) throws Exception {
+ for (String name : app.features()) {
+ featuresService.installFeature(name);
+ }
+ }
+
+ private void uninstallAppFeatures(Application app) throws Exception {
+ for (String name : app.features()) {
+ featuresService.uninstallFeature(name);
+ }
+ }
+
+}
diff --git a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java b/core/net/src/main/java/org/onosproject/app/impl/package-info.java
similarity index 80%
rename from core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
rename to core/net/src/main/java/org/onosproject/app/impl/package-info.java
index e39533c..d5f3037 100644
--- a/core/json/src/main/java/org/onosproject/json/impl/DeleteMe.java
+++ b/core/net/src/main/java/org/onosproject/app/impl/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.json.impl;
/**
- * Created by tom on 10/16/14.
+ * Subsystem for managing applications.
*/
-public class DeleteMe {
-}
+package org.onosproject.app.impl;
\ No newline at end of file
diff --git a/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java b/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java
new file mode 100644
index 0000000..3477207
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app.impl;
+
+import com.google.common.collect.ImmutableSet;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.app.ApplicationEvent;
+import org.onosproject.app.ApplicationListener;
+import org.onosproject.app.ApplicationState;
+import org.onosproject.app.ApplicationStoreAdapter;
+import org.onosproject.common.app.ApplicationArchive;
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultApplication;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.event.impl.TestEventDispatcher;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.onosproject.app.ApplicationEvent.Type.*;
+import static org.onosproject.app.ApplicationState.ACTIVE;
+import static org.onosproject.app.ApplicationState.INSTALLED;
+import static org.onosproject.app.DefaultApplicationDescriptionTest.*;
+
+/**
+ * Test of the application manager implementation.
+ */
+public class ApplicationManagerTest {
+
+ public static final DefaultApplicationId APP_ID = new DefaultApplicationId(1, APP_NAME);
+
+ private ApplicationManager mgr = new ApplicationManager();
+ private ApplicationListener listener = new TestListener();
+
+ @Before
+ public void setUp() {
+ mgr.eventDispatcher = new TestEventDispatcher();
+ mgr.featuresService = new TestFeaturesService();
+ mgr.store = new TestStore();
+ mgr.activate();
+ mgr.addListener(listener);
+ }
+
+ @After
+ public void tearDown() {
+ mgr.removeListener(listener);
+ mgr.deactivate();
+ }
+
+ private void validate(Application app) {
+ assertEquals("incorrect name", APP_NAME, app.id().name());
+ assertEquals("incorrect version", VER, app.version());
+ assertEquals("incorrect origin", ORIGIN, app.origin());
+
+ assertEquals("incorrect description", DESC, app.description());
+ assertEquals("incorrect features URI", FURL, app.featuresRepo().get());
+ assertEquals("incorrect features", FEATURES, app.features());
+ }
+
+ @Test
+ public void install() {
+ InputStream stream = ApplicationArchive.class.getResourceAsStream("app.zip");
+ Application app = mgr.install(stream);
+ validate(app);
+ assertEquals("incorrect features URI used", app.featuresRepo().get(),
+ ((TestFeaturesService) mgr.featuresService).uri);
+ assertEquals("incorrect app count", 1, mgr.getApplications().size());
+ assertEquals("incorrect app", app, mgr.getApplication(APP_ID));
+ assertEquals("incorrect app state", INSTALLED, mgr.getState(APP_ID));
+ }
+
+ @Test
+ public void uninstall() {
+ install();
+ mgr.uninstall(APP_ID);
+ assertEquals("incorrect app count", 0, mgr.getApplications().size());
+ }
+
+ @Test
+ public void activate() {
+ install();
+ mgr.activate(APP_ID);
+ assertEquals("incorrect app state", ACTIVE, mgr.getState(APP_ID));
+ }
+
+ @Test
+ public void deactivate() {
+ activate();
+ mgr.deactivate(APP_ID);
+ assertEquals("incorrect app state", INSTALLED, mgr.getState(APP_ID));
+ }
+
+
+ private class TestListener implements ApplicationListener {
+ private ApplicationEvent event;
+
+ @Override
+ public void event(ApplicationEvent event) {
+ this.event = event;
+ }
+ }
+
+ private class TestStore extends ApplicationStoreAdapter {
+
+ private Application app;
+ private ApplicationState state;
+
+ @Override
+ public Application create(InputStream appDescStream) {
+ app = new DefaultApplication(APP_ID, VER, DESC, ORIGIN, PERMS,
+ Optional.of(FURL), FEATURES);
+ state = INSTALLED;
+ delegate.notify(new ApplicationEvent(APP_INSTALLED, app));
+ return app;
+ }
+
+ @Override
+ public Set<Application> getApplications() {
+ return app != null ? ImmutableSet.of(app) : ImmutableSet.of();
+ }
+
+ @Override
+ public Application getApplication(ApplicationId appId) {
+ return app;
+ }
+
+ @Override
+ public void remove(ApplicationId appId) {
+ delegate.notify(new ApplicationEvent(APP_UNINSTALLED, app));
+ app = null;
+ state = null;
+ }
+
+ @Override
+ public ApplicationState getState(ApplicationId appId) {
+ return state;
+ }
+
+ @Override
+ public void activate(ApplicationId appId) {
+ state = ApplicationState.ACTIVE;
+ delegate.notify(new ApplicationEvent(APP_ACTIVATED, app));
+ }
+
+ @Override
+ public void deactivate(ApplicationId appId) {
+ state = INSTALLED;
+ delegate.notify(new ApplicationEvent(APP_DEACTIVATED, app));
+ }
+ }
+
+ private class TestFeaturesService extends FeaturesServiceAdapter {
+ private URI uri;
+ private Set<String> features = new HashSet<>();
+
+ @Override
+ public void addRepository(URI uri) throws Exception {
+ this.uri = uri;
+ }
+
+ @Override
+ public void removeRepository(URI uri) throws Exception {
+ this.uri = null;
+ }
+
+ @Override
+ public void installFeature(String name) throws Exception {
+ features.add(name);
+ }
+
+ @Override
+ public void uninstallFeature(String name) throws Exception {
+ features.remove(name);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/net/src/test/java/org/onosproject/app/impl/FeaturesServiceAdapter.java b/core/net/src/test/java/org/onosproject/app/impl/FeaturesServiceAdapter.java
new file mode 100644
index 0000000..f527bd4
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/app/impl/FeaturesServiceAdapter.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.app.impl;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Repository;
+
+import java.net.URI;
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * Adapter for testing against Apache Karaf feature service.
+ */
+public class FeaturesServiceAdapter implements org.apache.karaf.features.FeaturesService {
+ @Override
+ public void validateRepository(URI uri) throws Exception {
+
+ }
+
+ @Override
+ public void addRepository(URI uri) throws Exception {
+
+ }
+
+ @Override
+ public void addRepository(URI uri, boolean install) throws Exception {
+
+ }
+
+ @Override
+ public void removeRepository(URI uri) throws Exception {
+
+ }
+
+ @Override
+ public void removeRepository(URI uri, boolean uninstall) throws Exception {
+
+ }
+
+ @Override
+ public void restoreRepository(URI uri) throws Exception {
+
+ }
+
+ @Override
+ public Repository[] listRepositories() {
+ return new Repository[0];
+ }
+
+ @Override
+ public Repository getRepository(String repoName) {
+ return null;
+ }
+
+ @Override
+ public void installFeature(String name) throws Exception {
+
+ }
+
+ @Override
+ public void installFeature(String name, EnumSet<Option> options) throws Exception {
+
+ }
+
+ @Override
+ public void installFeature(String name, String version) throws Exception {
+
+ }
+
+ @Override
+ public void installFeature(String name, String version, EnumSet<Option> options) throws Exception {
+
+ }
+
+ @Override
+ public void installFeature(Feature f, EnumSet<Option> options) throws Exception {
+
+ }
+
+ @Override
+ public void installFeatures(Set<Feature> features, EnumSet<Option> options) throws Exception {
+
+ }
+
+ @Override
+ public void uninstallFeature(String name, EnumSet<Option> options) throws Exception {
+
+ }
+
+ @Override
+ public void uninstallFeature(String name) throws Exception {
+
+ }
+
+ @Override
+ public void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception {
+
+ }
+
+ @Override
+ public void uninstallFeature(String name, String version) throws Exception {
+
+ }
+
+ @Override
+ public Feature[] listFeatures() throws Exception {
+ return new Feature[0];
+ }
+
+ @Override
+ public Feature[] listInstalledFeatures() {
+ return new Feature[0];
+ }
+
+ @Override
+ public boolean isInstalled(Feature f) {
+ return false;
+ }
+
+ @Override
+ public Feature getFeature(String name, String version) throws Exception {
+ return null;
+ }
+
+ @Override
+ public Feature getFeature(String name) throws Exception {
+ return null;
+ }
+
+ @Override
+ public void refreshRepository(URI uri) throws Exception {
+
+ }
+}
diff --git a/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
index 974af66..5a79b43 100644
--- a/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
@@ -110,7 +110,7 @@
mgr.addListener(listener);
provider = new TestProvider(PID);
providerService = registry.register(provider);
- appId = new TestApplicationId((short) 0, "FlowRuleManagerTest");
+ appId = new TestApplicationId(0, "FlowRuleManagerTest");
assertTrue("provider should be registered",
registry.getProviders().contains(provider.id()));
}
@@ -639,8 +639,7 @@
}
public class TestApplicationId extends DefaultApplicationId {
-
- public TestApplicationId(short id, String name) {
+ public TestApplicationId(int id, String name) {
super(id, name);
}
}
diff --git a/core/pom.xml b/core/pom.xml
index c826b3b..5e2058b 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -33,9 +33,9 @@
<modules>
<module>api</module>
+ <module>common</module>
<module>net</module>
<module>store</module>
- <module>json</module>
</modules>
<dependencies>
diff --git a/core/store/dist/src/main/java/org/onosproject/store/core/impl/DistributedApplicationIdStore.java b/core/store/dist/src/main/java/org/onosproject/store/core/impl/DistributedApplicationIdStore.java
index f55ea54..186fb4e 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/core/impl/DistributedApplicationIdStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/core/impl/DistributedApplicationIdStore.java
@@ -103,6 +103,11 @@
return appId;
}
+ @Override
+ public ApplicationId getAppId(String name) {
+ return appIdsByName.get(name);
+ }
+
private void primeAppIds() {
for (DefaultApplicationId appId : appIdsByName.values()) {
appIds.put(appId.id(), appId);
@@ -113,7 +118,7 @@
public ApplicationId registerApplication(String name) {
DefaultApplicationId appId = appIdsByName.get(name);
if (appId == null) {
- short id = (short) lastAppId.getAndIncrement();
+ int id = (int) lastAppId.getAndIncrement();
appId = putIfAbsent(appIdsByName, name,
new DefaultApplicationId(id, name));
}
diff --git a/core/store/pom.xml b/core/store/pom.xml
index 334832f..e5078b9 100644
--- a/core/store/pom.xml
+++ b/core/store/pom.xml
@@ -44,6 +44,14 @@
</dependency>
<dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-common</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
diff --git a/core/store/trivial/pom.xml b/core/store/trivial/pom.xml
index 5e82ee8..2842ead 100644
--- a/core/store/trivial/pom.xml
+++ b/core/store/trivial/pom.xml
@@ -38,6 +38,11 @@
</dependency>
<dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-common</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<classifier>tests</classifier>
diff --git a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleApplicationIdStore.java b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleApplicationIdStore.java
index 34abd44..d6a9310 100644
--- a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleApplicationIdStore.java
+++ b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleApplicationIdStore.java
@@ -51,6 +51,11 @@
}
@Override
+ public ApplicationId getAppId(String name) {
+ return appIdsByName.get(name);
+ }
+
+ @Override
public ApplicationId registerApplication(String name) {
DefaultApplicationId appId = appIdsByName.get(name);
if (appId == null) {
diff --git a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleApplicationStore.java b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleApplicationStore.java
new file mode 100644
index 0000000..cecf5fd
--- /dev/null
+++ b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleApplicationStore.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.store.trivial.impl;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.app.ApplicationDescription;
+import org.onosproject.app.ApplicationEvent;
+import org.onosproject.app.ApplicationState;
+import org.onosproject.app.ApplicationStore;
+import org.onosproject.common.app.ApplicationArchive;
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.ApplicationIdStore;
+import org.onosproject.core.DefaultApplication;
+import org.onosproject.core.Permission;
+import org.slf4j.Logger;
+
+import java.io.InputStream;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.onosproject.app.ApplicationEvent.Type.*;
+import static org.onosproject.app.ApplicationState.ACTIVE;
+import static org.onosproject.app.ApplicationState.INSTALLED;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Manages inventory of network control applications.
+ */
+@Component(immediate = true)
+@Service
+public class SimpleApplicationStore extends ApplicationArchive implements ApplicationStore {
+
+ private final Logger log = getLogger(getClass());
+
+ // App inventory & states
+ private final ConcurrentMap<ApplicationId, DefaultApplication> apps = new ConcurrentHashMap<>();
+ private final ConcurrentMap<ApplicationId, ApplicationState> states = new ConcurrentHashMap<>();
+ private final ConcurrentMap<ApplicationId, Set<Permission>> permissions = new ConcurrentHashMap<>();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ApplicationIdStore idStore;
+
+ @Activate
+ public void activate() {
+ loadFromDisk();
+ log.info("Started");
+ }
+
+ private void loadFromDisk() {
+ for (String name : getApplicationNames()) {
+ ApplicationId appId = idStore.registerApplication(name);
+ ApplicationDescription appDesc = getApplicationDescription(name);
+ DefaultApplication app =
+ new DefaultApplication(appId, appDesc.version(),
+ appDesc.description(), appDesc.origin(),
+ appDesc.permissions(),
+ appDesc.featuresRepo(), appDesc.features());
+ apps.put(appId, app);
+ states.put(appId, isActive(name) ? INSTALLED : ACTIVE);
+ // load app permissions
+ }
+ }
+
+ @Deactivate
+ public void deactivate() {
+ apps.clear();
+ states.clear();
+ permissions.clear();
+ log.info("Stopped");
+ }
+
+ @Override
+ public Set<Application> getApplications() {
+ return ImmutableSet.copyOf(apps.values());
+ }
+
+ @Override
+ public ApplicationId getId(String name) {
+ return idStore.getAppId(name);
+ }
+
+ @Override
+ public Application getApplication(ApplicationId appId) {
+ return apps.get(appId);
+ }
+
+ @Override
+ public ApplicationState getState(ApplicationId appId) {
+ return states.get(appId);
+ }
+
+ @Override
+ public Application create(InputStream appDescStream) {
+ ApplicationDescription appDesc = saveApplication(appDescStream);
+ ApplicationId appId = idStore.registerApplication(appDesc.name());
+ DefaultApplication app =
+ new DefaultApplication(appId, appDesc.version(), appDesc.description(),
+ appDesc.origin(), appDesc.permissions(),
+ appDesc.featuresRepo(), appDesc.features());
+ apps.put(appId, app);
+ states.put(appId, INSTALLED);
+ delegate.notify(new ApplicationEvent(APP_INSTALLED, app));
+ return app;
+ }
+
+ @Override
+ public void remove(ApplicationId appId) {
+ Application app = apps.remove(appId);
+ if (app != null) {
+ states.remove(appId);
+ delegate.notify(new ApplicationEvent(APP_UNINSTALLED, app));
+ purgeApplication(app.id().name());
+ }
+ }
+
+ @Override
+ public void activate(ApplicationId appId) {
+ Application app = apps.get(appId);
+ if (app != null) {
+ setActive(appId.name());
+ states.put(appId, ACTIVE);
+ delegate.notify(new ApplicationEvent(APP_ACTIVATED, app));
+ }
+ }
+
+ @Override
+ public void deactivate(ApplicationId appId) {
+ Application app = apps.get(appId);
+ if (app != null) {
+ clearActive(appId.name());
+ states.put(appId, INSTALLED);
+ delegate.notify(new ApplicationEvent(APP_DEACTIVATED, app));
+ }
+ }
+
+ @Override
+ public Set<Permission> getPermissions(ApplicationId appId) {
+ return permissions.get(appId);
+ }
+
+ @Override
+ public void setPermissions(ApplicationId appId, Set<Permission> permissions) {
+ Application app = getApplication(appId);
+ if (app != null) {
+ this.permissions.put(appId, permissions);
+ delegate.notify(new ApplicationEvent(APP_PERMISSIONS_CHANGED, app));
+ }
+ }
+}
diff --git a/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleApplicationStoreTest.java b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleApplicationStoreTest.java
new file mode 100644
index 0000000..29006c4
--- /dev/null
+++ b/core/store/trivial/src/test/java/org/onosproject/store/trivial/impl/SimpleApplicationStoreTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.store.trivial.impl;
+
+import com.google.common.collect.ImmutableSet;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.app.ApplicationEvent;
+import org.onosproject.app.ApplicationStoreDelegate;
+import org.onosproject.common.app.ApplicationArchive;
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.ApplicationIdStoreAdapter;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.core.Permission;
+
+import static org.junit.Assert.assertEquals;
+import static org.onosproject.app.ApplicationEvent.Type.*;
+import static org.onosproject.app.ApplicationState.ACTIVE;
+import static org.onosproject.app.ApplicationState.INSTALLED;
+
+/**
+ * Test of the trivial application store implementation.
+ */
+public class SimpleApplicationStoreTest {
+
+ private SimpleApplicationStore store = new SimpleApplicationStore();
+ private TestDelegate delegate = new TestDelegate();
+
+ @Before
+ public void setUp() {
+ store.idStore = new TestIdStore();
+ store.setDelegate(delegate);
+ store.activate();
+ }
+
+ @After
+ public void tearDown() {
+ store.deactivate();
+ }
+
+ private Application createTestApp() {
+ return store.create(ApplicationArchive.class.getResourceAsStream("app.zip"));
+ }
+
+ @Test
+ public void create() {
+ Application app = createTestApp();
+ assertEquals("incorrect name", "org.foo.app", app.id().name());
+ assertEquals("incorrect app count", 1, store.getApplications().size());
+ assertEquals("incorrect app", app, store.getApplication(app.id()));
+ assertEquals("incorrect app state", INSTALLED, store.getState(app.id()));
+ assertEquals("incorrect event type", APP_INSTALLED, delegate.event.type());
+ assertEquals("incorrect event app", app, delegate.event.subject());
+ }
+
+ @Test
+ public void remove() {
+ Application app = createTestApp();
+ store.remove(app.id());
+ assertEquals("incorrect app count", 0, store.getApplications().size());
+ assertEquals("incorrect event type", APP_UNINSTALLED, delegate.event.type());
+ assertEquals("incorrect event app", app, delegate.event.subject());
+ }
+
+ @Test
+ public void activate() {
+ Application app = createTestApp();
+ store.activate(app.id());
+ assertEquals("incorrect app count", 1, store.getApplications().size());
+ assertEquals("incorrect app state", ACTIVE, store.getState(app.id()));
+ assertEquals("incorrect event type", APP_ACTIVATED, delegate.event.type());
+ assertEquals("incorrect event app", app, delegate.event.subject());
+ }
+
+ @Test
+ public void deactivate() {
+ Application app = createTestApp();
+ store.deactivate(app.id());
+ assertEquals("incorrect app count", 1, store.getApplications().size());
+ assertEquals("incorrect app state", INSTALLED, store.getState(app.id()));
+ assertEquals("incorrect event type", APP_DEACTIVATED, delegate.event.type());
+ assertEquals("incorrect event app", app, delegate.event.subject());
+ }
+
+ @Test
+ public void permissions() {
+ Application app = createTestApp();
+ ImmutableSet<Permission> permissions = ImmutableSet.of(new Permission() {
+ });
+ store.setPermissions(app.id(), permissions);
+ assertEquals("incorrect app perms", 1, store.getPermissions(app.id()).size());
+ assertEquals("incorrect app state", INSTALLED, store.getState(app.id()));
+ assertEquals("incorrect event type", APP_PERMISSIONS_CHANGED, delegate.event.type());
+ assertEquals("incorrect event app", app, delegate.event.subject());
+ }
+
+ private class TestIdStore extends ApplicationIdStoreAdapter {
+ @Override
+ public ApplicationId registerApplication(String name) {
+ return new DefaultApplicationId(1, name);
+ }
+
+ @Override
+ public ApplicationId getAppId(String name) {
+ return new DefaultApplicationId(1, name);
+ }
+ }
+
+ private class TestDelegate implements ApplicationStoreDelegate {
+ private ApplicationEvent event;
+
+ @Override
+ public void notify(ApplicationEvent event) {
+ this.event = event;
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/external.xml b/docs/external.xml
index f8fa7bd..c730c90 100644
--- a/docs/external.xml
+++ b/docs/external.xml
@@ -49,7 +49,7 @@
<version>2.10.1</version>
<configuration>
<show>package</show>
- <excludePackageNames>org.onlab.thirdparty:*.impl:*.impl.*:org.onosproject.provider.*:org.onosproject.gui:org.onosproject.rest:org.onosproject.cli*:org.onosproject.tvue:org.onosproject.foo:org.onosproject.mobility:org.onosproject.proxyarp:org.onosproject.fwd:org.onosproject.ifwd:org.onosproject.optical:org.onosproject.config:org.onosproject.calendar:org.onosproject.sdnip*:org.onosproject.oecfg:org.onosproject.metrics:org.onosproject.store.*:org.onosproject.openflow.*</excludePackageNames>
+ <excludePackageNames>org.onlab.thirdparty:*.impl:*.impl.*:org.onosproject.provider.*:org.onosproject.gui:org.onosproject.rest:org.onosproject.cli*:org.onosproject.tvue:org.onosproject.foo:org.onosproject.mobility:org.onosproject.proxyarp:org.onosproject.fwd:org.onosproject.ifwd:org.onosproject.optical:org.onosproject.config:org.onosproject.calendar:org.onosproject.sdnip*:org.onosproject.oecfg:org.onosproject.metrics:org.onosproject.store.*:org.onosproject.openflow.*:org.onosproject.common.*</excludePackageNames>
<docfilessubdirs>true</docfilessubdirs>
<doctitle>ONOS Java API</doctitle>
<groups>
diff --git a/docs/pom.xml b/docs/pom.xml
index bb7515e..3a1bfb9 100644
--- a/docs/pom.xml
+++ b/docs/pom.xml
@@ -61,7 +61,7 @@
<group>
<title>Core Subsystems</title>
<packages>
- org.onosproject.impl:org.onosproject.core.impl:org.onosproject.cluster.impl:org.onosproject.net.device.impl:org.onosproject.net.link.impl:org.onosproject.net.host.impl:org.onosproject.net.topology.impl:org.onosproject.net.packet.impl:org.onosproject.net.flow.impl:org.onosproject.net.*.impl:org.onosproject.event.impl:org.onosproject.net.intent.impl:org.onosproject.net.proxyarp.impl:org.onosproject.mastership.impl:org.onosproject.net.resource.impl:org.onosproject.json:org.onosproject.json.*:org.onosproject.provider.host.impl:org.onosproject.provider.lldp.impl:org.onosproject.net.statistic.impl
+ org.onosproject.impl:org.onosproject.core.impl:org.onosproject.cluster.impl:org.onosproject.net.device.impl:org.onosproject.net.link.impl:org.onosproject.net.host.impl:org.onosproject.net.topology.impl:org.onosproject.net.packet.impl:org.onosproject.net.flow.impl:org.onosproject.net.*.impl:org.onosproject.event.impl:org.onosproject.net.intent.impl:org.onosproject.net.proxyarp.impl:org.onosproject.mastership.impl:org.onosproject.net.resource.impl:org.onosproject.json:org.onosproject.json.*:org.onosproject.provider.host.impl:org.onosproject.provider.lldp.impl:org.onosproject.net.statistic.impl:org.onosproject.app.impl:org.onosproject.common.*
</packages>
</group>
<group>
diff --git a/features/features.xml b/features/features.xml
index b16b57f..26b61e6 100644
--- a/features/features.xml
+++ b/features/features.xml
@@ -22,6 +22,7 @@
description="ONOS 3rd party dependencies">
<bundle>mvn:commons-lang/commons-lang/2.6</bundle>
<bundle>mvn:org.apache.commons/commons-lang3/3.3.2</bundle>
+ <bundle>mvn:commons-configuration/commons-configuration/1.10</bundle>
<bundle>mvn:com.google.guava/guava/18.0</bundle>
<bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
<bundle>mvn:io.netty/netty-common/4.0.23.Final</bundle>
@@ -86,6 +87,7 @@
description="ONOS core components">
<feature>onos-api</feature>
<bundle>mvn:org.onosproject/onos-core-net/@ONOS-VERSION</bundle>
+ <bundle>mvn:org.onosproject/onos-core-common/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-core-dist/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-core-serializers/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onlab-netty/@ONOS-VERSION</bundle>
@@ -95,6 +97,7 @@
description="ONOS core components">
<feature>onos-api</feature>
<bundle>mvn:org.onosproject/onos-core-net/@ONOS-VERSION</bundle>
+ <bundle>mvn:org.onosproject/onos-core-common/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-core-trivial/@ONOS-VERSION</bundle>
</feature>
diff --git a/pom.xml b/pom.xml
index 062b049..ad4ae60 100644
--- a/pom.xml
+++ b/pom.xml
@@ -161,6 +161,12 @@
</dependency>
<dependency>
+ <groupId>commons-configuration</groupId>
+ <artifactId>commons-configuration</artifactId>
+ <version>1.10</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
@@ -315,6 +321,13 @@
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-of-api</artifactId>
diff --git a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
index ac46a26..c048b8a 100644
--- a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
+++ b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
@@ -133,8 +133,8 @@
private CoreService coreService;
private TestHostProviderService providerService;
- private ApplicationId appId = new DefaultApplicationId((short) 100,
- "org.onosproject.provider.host");
+ private ApplicationId appId =
+ new DefaultApplicationId(100, "org.onosproject.provider.host");
@Before
public void setUp() {
diff --git a/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java b/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
index ce5e048..b48af6a 100644
--- a/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
+++ b/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
@@ -97,8 +97,8 @@
private PacketProcessor testProcessor;
private DeviceListener deviceListener;
- private ApplicationId appId = new DefaultApplicationId((short) 100,
- "org.onosproject.provider.lldp");
+ private ApplicationId appId =
+ new DefaultApplicationId(100, "org.onosproject.provider.lldp");
@Before
public void setUp() {
diff --git a/tools/test/bin/onos-app b/tools/test/bin/onos-app
new file mode 100755
index 0000000..d474ef3
--- /dev/null
+++ b/tools/test/bin/onos-app
@@ -0,0 +1,20 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Tool to manage ONOS applications using REST API.
+# -----------------------------------------------------------------------------
+
+node=${1:-$OCI}
+cmd=${2:-list}
+app=${3}
+
+export URL=http://$node:8181/onos/v1/applications
+export HDR="-HContent-Type:application/octet-stream"
+export curl="curl -sS"
+
+case $cmd in
+ list) $curl -X GET $URL;;
+ install) $curl -X POST $HDR $URL --data-binary @$app;;
+ uninstall) $curl -X DELETE $URL/$app;;
+ activate) $curl -X POST $URL/$app/active;;
+ deactivate) $curl -X DELETE $URL/$app/active;;
+esac
diff --git a/tools/test/topos/chordal.py b/tools/test/topos/chordal.py
new file mode 100644
index 0000000..22f9ca1
--- /dev/null
+++ b/tools/test/topos/chordal.py
@@ -0,0 +1,402 @@
+"""
+"""
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import RemoteController
+from mininet.node import Node
+from mininet.node import CPULimitedHost
+from mininet.link import TCLink
+from mininet.cli import CLI
+from mininet.log import setLogLevel
+from mininet.util import dumpNodeConnections
+
+class chordalTopo( Topo ):
+
+ def __init__( self, **opts ):
+ "Create a topology."
+
+ # Initialize Topology
+ Topo.__init__( self, **opts )
+
+ # add nodes, switches first...
+ s1 = self.addSwitch( 's1' )
+ s2 = self.addSwitch( 's2' )
+ s3 = self.addSwitch( 's3' )
+ s4 = self.addSwitch( 's4' )
+ s5 = self.addSwitch( 's5' )
+ s6 = self.addSwitch( 's6' )
+ s7 = self.addSwitch( 's7' )
+ s8 = self.addSwitch( 's8' )
+ s9 = self.addSwitch( 's9' )
+ s10 = self.addSwitch( 's10' )
+ s11 = self.addSwitch( 's11' )
+ s12 = self.addSwitch( 's12' )
+ s13 = self.addSwitch( 's13' )
+ s14 = self.addSwitch( 's14' )
+ s15 = self.addSwitch( 's15' )
+ s16 = self.addSwitch( 's16' )
+ s17 = self.addSwitch( 's17' )
+ s18 = self.addSwitch( 's18' )
+ s19 = self.addSwitch( 's19' )
+ s20 = self.addSwitch( 's20' )
+ s21 = self.addSwitch( 's21' )
+ s22 = self.addSwitch( 's22' )
+ s23 = self.addSwitch( 's23' )
+ s24 = self.addSwitch( 's24' )
+ s25 = self.addSwitch( 's25' )
+
+ # ... and now hosts
+ s1_host = self.addHost( 'h1' )
+ s2_host = self.addHost( 'h2' )
+ s3_host = self.addHost( 'h3' )
+ s4_host = self.addHost( 'h4' )
+ s5_host = self.addHost( 'h5' )
+ s6_host = self.addHost( 'h6' )
+ s7_host = self.addHost( 'h7' )
+ s8_host = self.addHost( 'h8' )
+ s9_host = self.addHost( 'h9' )
+ s10_host = self.addHost( 'h10' )
+ s11_host = self.addHost( 'h11' )
+ s12_host = self.addHost( 'h12' )
+ s13_host = self.addHost( 'h13' )
+ s14_host = self.addHost( 'h14' )
+ s15_host = self.addHost( 'h15' )
+ s16_host = self.addHost( 'h16' )
+ s17_host = self.addHost( 'h17' )
+ s18_host = self.addHost( 'h18' )
+ s19_host = self.addHost( 'h19' )
+ s20_host = self.addHost( 'h20' )
+ s21_host = self.addHost( 'h21' )
+ s22_host = self.addHost( 'h22' )
+ s23_host = self.addHost( 'h23' )
+ s24_host = self.addHost( 'h24' )
+ s25_host = self.addHost( 'h25' )
+
+ # add edges between switch and corresponding host
+ self.addLink( s1 , s1_host )
+ self.addLink( s2 , s2_host )
+ self.addLink( s3 , s3_host )
+ self.addLink( s4 , s4_host )
+ self.addLink( s5 , s5_host )
+ self.addLink( s6 , s6_host )
+ self.addLink( s7 , s7_host )
+ self.addLink( s8 , s8_host )
+ self.addLink( s9 , s9_host )
+ self.addLink( s10 , s10_host )
+ self.addLink( s11 , s11_host )
+ self.addLink( s12 , s12_host )
+ self.addLink( s13 , s13_host )
+ self.addLink( s14 , s14_host )
+ self.addLink( s15 , s15_host )
+ self.addLink( s16 , s16_host )
+ self.addLink( s17 , s17_host )
+ self.addLink( s18 , s18_host )
+ self.addLink( s19 , s19_host )
+ self.addLink( s20 , s20_host )
+ self.addLink( s21 , s21_host )
+ self.addLink( s22 , s22_host )
+ self.addLink( s23 , s23_host )
+ self.addLink( s24 , s24_host )
+ self.addLink( s25 , s25_host )
+ self.addLink(s1, s2)
+ self.addLink(s1, s3)
+ self.addLink(s1, s4)
+ self.addLink(s1, s5)
+ self.addLink(s1, s6)
+ self.addLink(s1, s7)
+ self.addLink(s1, s8)
+ self.addLink(s1, s9)
+ self.addLink(s1, s10)
+ self.addLink(s1, s11)
+ self.addLink(s1, s12)
+ self.addLink(s1, s13)
+ self.addLink(s1, s14)
+ self.addLink(s1, s15)
+ self.addLink(s1, s16)
+ self.addLink(s1, s17)
+ self.addLink(s1, s18)
+ self.addLink(s1, s19)
+ self.addLink(s1, s20)
+ self.addLink(s1, s21)
+ self.addLink(s1, s22)
+ self.addLink(s1, s23)
+ self.addLink(s1, s24)
+ self.addLink(s1, s25)
+ self.addLink(s2, s3)
+ self.addLink(s2, s4)
+ self.addLink(s2, s5)
+ self.addLink(s2, s6)
+ self.addLink(s2, s7)
+ self.addLink(s2, s8)
+ self.addLink(s2, s9)
+ self.addLink(s2, s10)
+ self.addLink(s2, s11)
+ self.addLink(s2, s12)
+ self.addLink(s2, s13)
+ self.addLink(s2, s14)
+ self.addLink(s2, s15)
+ self.addLink(s2, s16)
+ self.addLink(s2, s17)
+ self.addLink(s2, s18)
+ self.addLink(s2, s19)
+ self.addLink(s2, s20)
+ self.addLink(s2, s21)
+ self.addLink(s2, s22)
+ self.addLink(s2, s23)
+ self.addLink(s2, s24)
+ self.addLink(s2, s25)
+ self.addLink(s3, s4)
+ self.addLink(s3, s5)
+ self.addLink(s3, s6)
+ self.addLink(s3, s7)
+ self.addLink(s3, s8)
+ self.addLink(s3, s9)
+ self.addLink(s3, s10)
+ self.addLink(s3, s11)
+ self.addLink(s3, s12)
+ self.addLink(s3, s13)
+ self.addLink(s3, s14)
+ self.addLink(s3, s15)
+ self.addLink(s3, s16)
+ self.addLink(s3, s17)
+ self.addLink(s3, s18)
+ self.addLink(s3, s19)
+ self.addLink(s3, s20)
+ self.addLink(s3, s21)
+ self.addLink(s3, s22)
+ self.addLink(s3, s23)
+ self.addLink(s3, s24)
+ self.addLink(s3, s25)
+ self.addLink(s4, s5)
+ self.addLink(s4, s6)
+ self.addLink(s4, s7)
+ self.addLink(s4, s8)
+ self.addLink(s4, s9)
+ self.addLink(s4, s10)
+ self.addLink(s4, s11)
+ self.addLink(s4, s12)
+ self.addLink(s4, s13)
+ self.addLink(s4, s14)
+ self.addLink(s4, s15)
+ self.addLink(s4, s16)
+ self.addLink(s4, s17)
+ self.addLink(s4, s18)
+ self.addLink(s4, s19)
+ self.addLink(s4, s20)
+ self.addLink(s4, s21)
+ self.addLink(s4, s22)
+ self.addLink(s4, s23)
+ self.addLink(s4, s24)
+ self.addLink(s4, s25)
+ self.addLink(s5, s6)
+ self.addLink(s5, s7)
+ self.addLink(s5, s8)
+ self.addLink(s5, s9)
+ self.addLink(s5, s10)
+ self.addLink(s5, s11)
+ self.addLink(s5, s12)
+ self.addLink(s5, s13)
+ self.addLink(s5, s14)
+ self.addLink(s5, s15)
+ self.addLink(s5, s16)
+ self.addLink(s5, s17)
+ self.addLink(s5, s18)
+ self.addLink(s5, s19)
+ self.addLink(s5, s20)
+ self.addLink(s5, s21)
+ self.addLink(s5, s22)
+ self.addLink(s5, s23)
+ self.addLink(s5, s24)
+ self.addLink(s5, s25)
+ self.addLink(s6, s7)
+ self.addLink(s6, s8)
+ self.addLink(s6, s9)
+ self.addLink(s6, s10)
+ self.addLink(s6, s11)
+ self.addLink(s6, s12)
+ self.addLink(s6, s13)
+ self.addLink(s6, s14)
+ self.addLink(s6, s15)
+ self.addLink(s6, s16)
+ self.addLink(s6, s17)
+ self.addLink(s6, s18)
+ self.addLink(s6, s19)
+ self.addLink(s6, s20)
+ self.addLink(s6, s21)
+ self.addLink(s6, s22)
+ self.addLink(s6, s23)
+ self.addLink(s6, s24)
+ self.addLink(s6, s25)
+ self.addLink(s7, s8)
+ self.addLink(s7, s9)
+ self.addLink(s7, s10)
+ self.addLink(s7, s11)
+ self.addLink(s7, s12)
+ self.addLink(s7, s13)
+ self.addLink(s7, s14)
+ self.addLink(s7, s15)
+ self.addLink(s7, s16)
+ self.addLink(s7, s17)
+ self.addLink(s7, s18)
+ self.addLink(s7, s19)
+ self.addLink(s7, s20)
+ self.addLink(s7, s21)
+ self.addLink(s7, s22)
+ self.addLink(s7, s23)
+ self.addLink(s7, s24)
+ self.addLink(s7, s25)
+ self.addLink(s8, s9)
+ self.addLink(s8, s10)
+ self.addLink(s8, s11)
+ self.addLink(s8, s12)
+ self.addLink(s8, s13)
+ self.addLink(s8, s14)
+ self.addLink(s8, s15)
+ self.addLink(s8, s16)
+ self.addLink(s8, s17)
+ self.addLink(s8, s18)
+ self.addLink(s8, s19)
+ self.addLink(s8, s20)
+ self.addLink(s8, s21)
+ self.addLink(s8, s22)
+ self.addLink(s8, s23)
+ self.addLink(s8, s24)
+ self.addLink(s8, s25)
+ self.addLink(s9, s10)
+ self.addLink(s9, s11)
+ self.addLink(s9, s12)
+ self.addLink(s9, s13)
+ self.addLink(s9, s14)
+ self.addLink(s9, s15)
+ self.addLink(s9, s16)
+ self.addLink(s9, s17)
+ self.addLink(s9, s18)
+ self.addLink(s9, s19)
+ self.addLink(s9, s20)
+ self.addLink(s9, s21)
+ self.addLink(s9, s22)
+ self.addLink(s9, s23)
+ self.addLink(s9, s24)
+ self.addLink(s9, s25)
+ self.addLink(s10, s11)
+ self.addLink(s10, s12)
+ self.addLink(s10, s13)
+ self.addLink(s10, s14)
+ self.addLink(s10, s15)
+ self.addLink(s10, s16)
+ self.addLink(s10, s17)
+ self.addLink(s10, s18)
+ self.addLink(s10, s19)
+ self.addLink(s10, s20)
+ self.addLink(s10, s21)
+ self.addLink(s10, s22)
+ self.addLink(s10, s23)
+ self.addLink(s10, s24)
+ self.addLink(s10, s25)
+ self.addLink(s11, s12)
+ self.addLink(s11, s13)
+ self.addLink(s11, s14)
+ self.addLink(s11, s15)
+ self.addLink(s11, s16)
+ self.addLink(s11, s17)
+ self.addLink(s11, s18)
+ self.addLink(s11, s19)
+ self.addLink(s11, s20)
+ self.addLink(s11, s21)
+ self.addLink(s11, s22)
+ self.addLink(s11, s23)
+ self.addLink(s11, s24)
+ self.addLink(s11, s25)
+ self.addLink(s12, s13)
+ self.addLink(s12, s14)
+ self.addLink(s12, s15)
+ self.addLink(s12, s16)
+ self.addLink(s12, s17)
+ self.addLink(s12, s18)
+ self.addLink(s12, s19)
+ self.addLink(s12, s20)
+ self.addLink(s12, s21)
+ self.addLink(s12, s22)
+ self.addLink(s12, s23)
+ self.addLink(s12, s24)
+ self.addLink(s12, s25)
+ self.addLink(s13, s14)
+ self.addLink(s13, s15)
+ self.addLink(s13, s16)
+ self.addLink(s13, s17)
+ self.addLink(s13, s18)
+ self.addLink(s13, s19)
+ self.addLink(s13, s20)
+ self.addLink(s13, s21)
+ self.addLink(s13, s22)
+ self.addLink(s13, s23)
+ self.addLink(s13, s24)
+ self.addLink(s13, s25)
+ self.addLink(s14, s15)
+ self.addLink(s14, s16)
+ self.addLink(s14, s17)
+ self.addLink(s14, s18)
+ self.addLink(s14, s19)
+ self.addLink(s14, s20)
+ self.addLink(s14, s21)
+ self.addLink(s14, s22)
+ self.addLink(s14, s23)
+ self.addLink(s14, s24)
+ self.addLink(s14, s25)
+ self.addLink(s15, s16)
+ self.addLink(s15, s17)
+ self.addLink(s15, s18)
+ self.addLink(s15, s19)
+ self.addLink(s15, s20)
+ self.addLink(s15, s21)
+ self.addLink(s15, s22)
+ self.addLink(s15, s23)
+ self.addLink(s15, s24)
+ self.addLink(s15, s25)
+ self.addLink(s16, s17)
+ self.addLink(s16, s18)
+ self.addLink(s16, s19)
+ self.addLink(s16, s20)
+ self.addLink(s16, s21)
+ self.addLink(s16, s22)
+ self.addLink(s16, s23)
+ self.addLink(s16, s24)
+ self.addLink(s16, s25)
+ self.addLink(s17, s18)
+ self.addLink(s17, s19)
+ self.addLink(s17, s20)
+ self.addLink(s17, s21)
+ self.addLink(s17, s22)
+ self.addLink(s17, s23)
+ self.addLink(s17, s24)
+ self.addLink(s17, s25)
+ self.addLink(s18, s19)
+ self.addLink(s18, s20)
+ self.addLink(s18, s21)
+ self.addLink(s18, s22)
+ self.addLink(s18, s23)
+ self.addLink(s18, s24)
+ self.addLink(s18, s25)
+ self.addLink(s19, s20)
+ self.addLink(s19, s21)
+ self.addLink(s19, s22)
+ self.addLink(s19, s23)
+ self.addLink(s19, s24)
+ self.addLink(s19, s25)
+ self.addLink(s20, s21)
+ self.addLink(s20, s22)
+ self.addLink(s20, s23)
+ self.addLink(s20, s24)
+ self.addLink(s20, s25)
+ self.addLink(s21, s22)
+ self.addLink(s21, s23)
+ self.addLink(s21, s24)
+ self.addLink(s21, s25)
+ self.addLink(s22, s23)
+ self.addLink(s22, s24)
+ self.addLink(s22, s25)
+ self.addLink(s23, s24)
+ self.addLink(s23, s25)
+ self.addLink(s24, s25)
+
+topos = { 'chordal': ( lambda: chordalTopo() ) }
diff --git a/utils/junit/src/main/java/org/onlab/junit/ExceptionTest.java b/utils/junit/src/main/java/org/onlab/junit/ExceptionTest.java
new file mode 100644
index 0000000..09b3fe3
--- /dev/null
+++ b/utils/junit/src/main/java/org/onlab/junit/ExceptionTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onlab.junit;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+/**
+ * Base for exception tests.
+ */
+public abstract class ExceptionTest {
+
+ protected static final Throwable CAUSE = new RuntimeException("boom");
+ protected static final String MESSAGE = "Uh oh.... boom";
+
+ protected abstract Exception getDefault();
+ protected abstract Exception getWithMessage();
+ protected abstract Exception getWithMessageAndCause();
+
+ @Test
+ public void noMessageNoCause() {
+ Exception e = getDefault();
+ assertEquals("incorrect message", null, e.getMessage());
+ assertEquals("incorrect cause", null, e.getCause());
+ }
+
+ @Test
+ public void withMessage() {
+ Exception e = getWithMessage();
+ assertEquals("incorrect message", MESSAGE, e.getMessage());
+ assertEquals("incorrect cause", null, e.getCause());
+ }
+
+ @Test
+ public void withCause() {
+ Exception e = getWithMessageAndCause();
+ assertEquals("incorrect message", MESSAGE, e.getMessage());
+ assertSame("incorrect cause", CAUSE, e.getCause());
+ }
+}
diff --git a/utils/junit/src/main/java/org/onlab/junit/TestTools.java b/utils/junit/src/main/java/org/onlab/junit/TestTools.java
index 550a028..400f710 100644
--- a/utils/junit/src/main/java/org/onlab/junit/TestTools.java
+++ b/utils/junit/src/main/java/org/onlab/junit/TestTools.java
@@ -15,6 +15,14 @@
*/
package org.onlab.junit;
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.Files;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Random;
+
import static com.google.common.base.Preconditions.checkArgument;
import static org.junit.Assert.fail;
@@ -23,6 +31,8 @@
*/
public final class TestTools {
+ private static final Random RANDOM = new Random();
+
// Prohibit construction
private TestTools() {
}
@@ -109,4 +119,92 @@
assertAfter(0, duration, assertions);
}
+
+ /**
+ * Creates a directory tree of test files. To signify creating a directory
+ * file path should end with '/'.
+ *
+ * @param paths list of file paths
+ * @return list of created files
+ * @throws java.io.IOException if there is an issue
+ */
+ public static List<File> createTestFiles(List<String> paths) throws IOException {
+ return createTestFiles(paths, 32, 1024);
+ }
+
+ /**
+ * Creates a directory tree of test files. To signify creating a directory
+ * file path should end with '/'.
+ *
+ * @param paths list of file paths
+ * @param minSize minimum file size in bytes
+ * @param maxSize maximum file size in bytes
+ * @return list of created files
+ * @throws java.io.IOException if there is an issue
+ */
+ public static List<File> createTestFiles(List<String> paths,
+ int minSize, int maxSize) throws IOException {
+ ImmutableList.Builder<File> files = ImmutableList.builder();
+ for (String p : paths) {
+ File f = new File(p);
+ if (p.endsWith("/")) {
+ if (f.mkdirs()) {
+ files.add(f);
+ }
+ } else {
+ Files.createParentDirs(f);
+ if (f.createNewFile()) {
+ writeRandomFile(f, minSize, maxSize);
+ files.add(f);
+ }
+ }
+ }
+ return files.build();
+ }
+
+ /**
+ * Writes random binary content into the specified file. The number of
+ * bytes will be random between the given minimum and maximum.
+ *
+ * @param file file to write data to
+ * @param minSize minimum number of bytes to write
+ * @param maxSize maximum number of bytes to write
+ * @throws IOException if there is an issue
+ */
+ public static void writeRandomFile(File file, int minSize, int maxSize) throws IOException {
+ int size = minSize + (minSize == maxSize ? 0 : RANDOM.nextInt(maxSize - minSize));
+ byte[] data = new byte[size];
+ tweakBytes(RANDOM, data, size / 4);
+ Files.write(data, file);
+ }
+
+
+ /**
+ * Tweaks the given number of bytes in a byte array.
+ *
+ * @param random random number generator
+ * @param data byte array to be tweaked
+ * @param count number of bytes to tweak
+ */
+ public static void tweakBytes(Random random, byte[] data, int count) {
+ tweakBytes(random, data, count, 0, data.length);
+ }
+
+ /**
+ * Tweaks the given number of bytes in the specified range of a byte array.
+ *
+ * @param random random number generator
+ * @param data byte array to be tweaked
+ * @param count number of bytes to tweak
+ * @param start index at beginning of range (inclusive)
+ * @param end index at end of range (exclusive)
+ */
+ public static void tweakBytes(Random random, byte[] data, int count,
+ int start, int end) {
+ int len = end - start;
+ for (int i = 0; i < count; i++) {
+ data[start + random.nextInt(len)] = (byte) random.nextInt();
+ }
+ }
+
}
diff --git a/utils/misc/src/main/java/org/onlab/util/Tools.java b/utils/misc/src/main/java/org/onlab/util/Tools.java
index e908300..498f3b1 100644
--- a/utils/misc/src/main/java/org/onlab/util/Tools.java
+++ b/utils/misc/src/main/java/org/onlab/util/Tools.java
@@ -15,6 +15,8 @@
*/
package org.onlab.util;
+import static java.nio.file.Files.delete;
+import static java.nio.file.Files.walkFileTree;
import static org.slf4j.LoggerFactory.getLogger;
import java.io.BufferedReader;
@@ -24,6 +26,11 @@
import java.io.InputStreamReader;
import java.lang.Thread.UncaughtExceptionHandler;
import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadFactory;
@@ -39,7 +46,7 @@
private Tools() {
}
- private static final Logger TOOLS_LOG = getLogger(Tools.class);
+ private static final Logger log = getLogger(Tools.class);
/**
* Returns a thread factory that produces threads named according to the
@@ -51,12 +58,12 @@
public static ThreadFactory namedThreads(String pattern) {
return new ThreadFactoryBuilder()
.setNameFormat(pattern)
- // FIXME remove UncaughtExceptionHandler before release
+ // FIXME remove UncaughtExceptionHandler before release
.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
- TOOLS_LOG.error("Uncaught exception on {}", t.getName(), e);
+ log.error("Uncaught exception on {}", t.getName(), e);
}
}).build();
}
@@ -69,9 +76,9 @@
*/
public static ThreadFactory minPriority(ThreadFactory factory) {
return new ThreadFactoryBuilder()
- .setThreadFactory(factory)
- .setPriority(Thread.MIN_PRIORITY)
- .build();
+ .setThreadFactory(factory)
+ .setPriority(Thread.MIN_PRIORITY)
+ .build();
}
/**
@@ -127,7 +134,7 @@
public static List<String> slurp(File path) {
try {
BufferedReader br = new BufferedReader(
- new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8));
+ new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8));
List<String> lines = new ArrayList<>();
String line;
@@ -141,4 +148,56 @@
}
}
+
+ /**
+ * Purges the specified directory path. Use with great caution since
+ * no attempt is made to check for symbolic links, which could result in
+ * deletion of unintended files.
+ *
+ * @param path directory to be removed
+ * @throws java.io.IOException if unable to remove contents
+ */
+ public static void removeDirectory(String path) throws IOException {
+ walkFileTree(Paths.get(path), new DirectoryDeleter());
+ }
+
+ /**
+ * Purges the specified directory path. Use with great caution since
+ * no attempt is made to check for symbolic links, which could result in
+ * deletion of unintended files.
+ *
+ * @param dir directory to be removed
+ * @throws java.io.IOException if unable to remove contents
+ */
+ public static void removeDirectory(File dir) throws IOException {
+ walkFileTree(Paths.get(dir.getAbsolutePath()), new DirectoryDeleter());
+ }
+
+
+ private static class DirectoryDeleter extends SimpleFileVisitor<Path> {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attributes)
+ throws IOException {
+ if (attributes.isRegularFile()) {
+ delete(file);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path directory, IOException ioe)
+ throws IOException {
+ delete(directory);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException ioe)
+ throws IOException {
+ log.warn("Unable to delete file {}", file);
+ log.warn("Boom", ioe);
+ return FileVisitResult.CONTINUE;
+ }
+ }
+
}
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
new file mode 100644
index 0000000..4cf0b7c
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.codec.impl;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.app.ApplicationService;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.Application;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Application JSON codec.
+ */
+public class ApplicationCodec extends JsonCodec<Application> {
+
+ @Override
+ public ObjectNode encode(Application app, CodecContext context) {
+ checkNotNull(app, "Application cannot be null");
+ ApplicationService service = context.get(ApplicationService.class);
+ ObjectNode result = context.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().toString() : "")
+ .put("features", app.features().toString())
+ .put("state", service.getState(app.id()).toString());
+ return result;
+ }
+
+}
diff --git a/web/api/src/main/java/org/onosproject/codec/impl/CodecManager.java b/web/api/src/main/java/org/onosproject/codec/impl/CodecManager.java
index d176077..88fb8dd 100644
--- a/web/api/src/main/java/org/onosproject/codec/impl/CodecManager.java
+++ b/web/api/src/main/java/org/onosproject/codec/impl/CodecManager.java
@@ -26,6 +26,7 @@
import org.onlab.packet.Ethernet;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.Application;
import org.onosproject.net.Annotations;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
@@ -64,6 +65,7 @@
@Activate
public void activate() {
codecs.clear();
+ registerCodec(Application.class, new ApplicationCodec());
registerCodec(Annotations.class, new AnnotationsCodec());
registerCodec(Device.class, new DeviceCodec());
registerCodec(Port.class, new PortCodec());
diff --git a/web/api/src/main/java/org/onosproject/rest/ApplicationsWebResource.java b/web/api/src/main/java/org/onosproject/rest/ApplicationsWebResource.java
new file mode 100644
index 0000000..6177bab
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/rest/ApplicationsWebResource.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed 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.onosproject.rest;
+
+import org.onosproject.app.ApplicationAdminService;
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.InputStream;
+import java.util.Set;
+
+/**
+ * REST resource for interacting with the inventory of applications.
+ */
+@Path("applications")
+public class ApplicationsWebResource extends AbstractWebResource {
+
+ @GET
+ public Response getApplications() {
+ ApplicationAdminService service = get(ApplicationAdminService.class);
+ Set<Application> apps = service.getApplications();
+ return ok(encodeArray(Application.class, "applications", apps)).build();
+ }
+
+ @GET
+ @Path("{name}")
+ public Response getApplication(@PathParam("id") String name) {
+ ApplicationAdminService service = get(ApplicationAdminService.class);
+ ApplicationId appId = service.getId(name);
+ return response(service, appId);
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_OCTET_STREAM)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response installApplication(InputStream stream) {
+ ApplicationAdminService service = get(ApplicationAdminService.class);
+ Application app = service.install(stream);
+ return ok(codec(Application.class).encode(app, this)).build();
+ }
+
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{name}")
+ public Response uninstallApplication(@PathParam("name") String name) {
+ ApplicationAdminService service = get(ApplicationAdminService.class);
+ ApplicationId appId = service.getId(name);
+ service.uninstall(appId);
+ return Response.ok().build();
+ }
+
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{name}/active")
+ public Response activateApplication(@PathParam("name") String name) {
+ ApplicationAdminService service = get(ApplicationAdminService.class);
+ ApplicationId appId = service.getId(name);
+ service.activate(appId);
+ return response(service, appId);
+ }
+
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{name}/active")
+ public Response deactivateApplication(@PathParam("name") String name) {
+ ApplicationAdminService service = get(ApplicationAdminService.class);
+ ApplicationId appId = service.getId(name);
+ service.deactivate(appId);
+ return response(service, appId);
+ }
+
+ private Response response(ApplicationAdminService service, ApplicationId appId) {
+ Application app = service.getApplication(appId);
+ return ok(codec(Application.class).encode(app, this)).build();
+ }
+
+}
diff --git a/web/api/src/main/webapp/WEB-INF/web.xml b/web/api/src/main/webapp/WEB-INF/web.xml
index d8fb9e7..e0e4737 100644
--- a/web/api/src/main/webapp/WEB-INF/web.xml
+++ b/web/api/src/main/webapp/WEB-INF/web.xml
@@ -35,6 +35,7 @@
org.onosproject.rest.exceptions.ServerErrorMapper,
org.onosproject.rest.JsonBodyWriter,
+ org.onosproject.rest.ApplicationsWebResource,
org.onosproject.rest.DevicesWebResource,
org.onosproject.rest.LinksWebResource,
org.onosproject.rest.HostsWebResource,
diff --git a/web/api/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java b/web/api/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
index a230273..d96f481 100644
--- a/web/api/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
+++ b/web/api/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
@@ -66,8 +66,7 @@
private final HostId id1 = hid("12:34:56:78:91:ab/1");
private final HostId id2 = hid("12:34:56:78:92:ab/1");
- private final ApplicationId appId =
- new DefaultApplicationId((short) 3, "test");
+ private final ApplicationId appId = new DefaultApplicationId(3, "test");
final TrafficSelector emptySelector =
DefaultTrafficSelector.builder().build();
final TrafficTreatment emptyTreatment =
diff --git a/web/api/src/test/java/org/onosproject/rest/IntentsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/IntentsResourceTest.java
index 2d650a5..b2eee81 100644
--- a/web/api/src/test/java/org/onosproject/rest/IntentsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/IntentsResourceTest.java
@@ -62,8 +62,7 @@
public class IntentsResourceTest extends ResourceTest {
final IntentService mockIntentService = createMock(IntentService.class);
final HashSet<Intent> intents = new HashSet<>();
- private static final ApplicationId APP_ID =
- new DefaultApplicationId((short) 1, "test");
+ private static final ApplicationId APP_ID = new DefaultApplicationId(1, "test");
private IdGenerator mockGenerator;
/**