You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/15 15:33:03 UTC
[01/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master 083953f1c -> 6caee5899
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
index a14bc22..bfe82ba 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -50,6 +50,8 @@ import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.ConfigKey;
@@ -61,8 +63,6 @@ import brooklyn.entity.basic.BasicApplication;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.trait.Startable;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
import brooklyn.policy.basic.AbstractPolicy;
import org.apache.brooklyn.rest.domain.ApplicationSpec;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java
index f8b2402..491c1a7 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/DefaultExceptionMapper.java
@@ -30,10 +30,10 @@ import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.error.YAMLException;
-
-import brooklyn.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.rest.domain.ApiError;
import org.apache.brooklyn.rest.domain.ApiError.Builder;
+
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.UserFacingException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonJsonProvider.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonJsonProvider.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonJsonProvider.java
index 70b72f8..4c3ad5e 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonJsonProvider.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/json/BrooklynJacksonJsonProvider.java
@@ -23,6 +23,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import org.codehaus.jackson.map.ObjectMapper;
@@ -36,7 +37,6 @@ import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServiceAttributes;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.management.ManagementContextInjectable;
public class BrooklynJacksonJsonProvider extends JacksonJsonProvider implements ManagementContextInjectable {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java
index e4fc53a..5bf673d 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java
@@ -33,6 +33,8 @@ import javax.servlet.Filter;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.FilterHolder;
@@ -46,8 +48,6 @@ import org.slf4j.LoggerFactory;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.BrooklynServiceAttributes;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
import org.apache.brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
import org.apache.brooklyn.rest.filter.HaMasterCheckFilter;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTestFixture.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTestFixture.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTestFixture.java
index 6d6996c..2a2a569 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTestFixture.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncherTestFixture.java
@@ -28,9 +28,9 @@ import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.BrooklynServiceAttributes;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.rest.security.provider.AnyoneSecurityProvider;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaHotCheckTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaHotCheckTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaHotCheckTest.java
index e0ad096..e51fbbe 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaHotCheckTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/HaHotCheckTest.java
@@ -25,13 +25,11 @@ import javax.ws.rs.core.MediaType;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-
import org.apache.brooklyn.api.management.ha.HighAvailabilityManager;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.rest.filter.HaHotCheckResourceFilter;
import org.apache.brooklyn.rest.filter.HaMasterCheckFilter;
import org.apache.brooklyn.rest.testing.BrooklynRestResourceTest;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
index de4d778..e60e16a 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
@@ -42,9 +42,9 @@ import org.testng.annotations.Test;
import org.testng.reporters.Files;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.management.osgi.OsgiStandaloneTest;
import brooklyn.policy.autoscaling.AutoScalerPolicy;
import org.apache.brooklyn.rest.domain.CatalogEntitySummary;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java
index 6ab034d..c228b95 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceIntegrationTest.java
@@ -33,10 +33,10 @@ import org.eclipse.jetty.server.Server;
import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.rest.BrooklynRestApiLauncher;
import org.apache.brooklyn.rest.BrooklynRestApiLauncherTestFixture;
import org.apache.brooklyn.rest.security.provider.TestSecurityProvider;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java
index 8059278..13de9e9 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/ServerResourceTest.java
@@ -43,10 +43,10 @@ import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.EmptySoftwareProcess;
import brooklyn.entity.basic.EmptySoftwareProcessDriver;
import brooklyn.entity.basic.EmptySoftwareProcessImpl;
-import brooklyn.management.internal.ManagementContextInternal;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.rest.domain.HighAvailabilitySummary;
import org.apache.brooklyn.rest.domain.VersionSummary;
import org.apache.brooklyn.rest.testing.BrooklynRestResourceTest;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/UsageResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/UsageResourceTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/UsageResourceTest.java
index 42d1717..fd3504d 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/UsageResourceTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/UsageResourceTest.java
@@ -42,12 +42,10 @@ import brooklyn.entity.basic.SoftwareProcessEntityTest;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.LocalUsageManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-
-import brooklyn.management.internal.LocalUsageManager;
-import brooklyn.management.internal.ManagementContextInternal;
-
import org.apache.brooklyn.rest.domain.ApplicationSpec;
import org.apache.brooklyn.rest.domain.EntitySpec;
import org.apache.brooklyn.rest.domain.Status;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestApiTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestApiTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestApiTest.java
index 9d1e9bd..d6a8829 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestApiTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestApiTest.java
@@ -21,6 +21,8 @@ package org.apache.brooklyn.rest.testing;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.codehaus.jackson.map.ObjectMapper;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeMethod;
@@ -35,10 +37,6 @@ import com.sun.jersey.test.framework.LowLevelAppDescriptor;
import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.basic.BasicLocationRegistry;
-
-import brooklyn.management.ManagementContextInjectable;
-import brooklyn.management.internal.LocalManagementContext;
-
import org.apache.brooklyn.rest.BrooklynRestApi;
import org.apache.brooklyn.rest.BrooklynRestApiLauncherTest;
import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
index 71e161a..989ea3e 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import brooklyn.catalog.internal.CatalogItemBuilder;
import brooklyn.catalog.internal.CatalogTemplateItemDto;
@@ -40,7 +41,6 @@ import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.proxying.EntityProxy;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.policy.basic.AbstractPolicy;
import org.apache.brooklyn.rest.domain.ApplicationSpec;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/utils/test-support/src/main/java/org/apache/brooklyn/test/BrooklynLeakListener.java
----------------------------------------------------------------------
diff --git a/utils/test-support/src/main/java/org/apache/brooklyn/test/BrooklynLeakListener.java b/utils/test-support/src/main/java/org/apache/brooklyn/test/BrooklynLeakListener.java
index 7064153..4f95feb 100644
--- a/utils/test-support/src/main/java/org/apache/brooklyn/test/BrooklynLeakListener.java
+++ b/utils/test-support/src/main/java/org/apache/brooklyn/test/BrooklynLeakListener.java
@@ -48,7 +48,7 @@ public class BrooklynLeakListener extends TestListenerAdapter {
* depend on brooklyn-core, so LocalManagementContext may not be on the classpath.
*/
private void tryTerminateAll(String context, ITestContext testContext) {
- String clazzName = "brooklyn.management.internal.LocalManagementContext";
+ String clazzName = "org.apache.brooklyn.core.management.internal.LocalManagementContext";
String message;
int level;
try {
[26/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/catalog
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java
index a8a8f5e..da84841 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/WebResourceUtils.java
@@ -30,10 +30,10 @@ import javax.ws.rs.core.Response;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import brooklyn.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.rest.domain.ApiError;
import org.apache.brooklyn.rest.util.json.BrooklynJacksonJsonProvider;
+
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.net.Urls;
import brooklyn.util.text.StringEscapes.JavaStringEscapes;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
index e60e16a..83690d8 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
@@ -42,9 +42,9 @@ import org.testng.annotations.Test;
import org.testng.reporters.Files;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.policy.autoscaling.AutoScalerPolicy;
import org.apache.brooklyn.rest.domain.CatalogEntitySummary;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
index 989ea3e..484f6ab 100644
--- a/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
+++ b/usage/rest-server/src/test/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtilsTest.java
@@ -32,11 +32,11 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
+import org.apache.brooklyn.core.catalog.internal.CatalogTemplateItemDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
-import brooklyn.catalog.internal.CatalogItemBuilder;
-import brooklyn.catalog.internal.CatalogTemplateItemDto;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.entity.basic.Entities;
[28/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/catalog
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
new file mode 100644
index 0000000..3914427
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import brooklyn.basic.BrooklynObjectInternal;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.rebind.RebindSupport;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.mementos.CatalogItemMemento;
+
+import brooklyn.config.ConfigKey;
+
+import com.google.common.base.Preconditions;
+
+public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObjectInternal {
+
+ protected final CatalogDo catalog;
+ protected final CatalogItemDtoAbstract<T,SpecT> itemDto;
+
+ protected volatile Class<T> javaClass;
+
+ public CatalogItemDo(CatalogDo catalog, CatalogItem<T,SpecT> itemDto) {
+ this.catalog = Preconditions.checkNotNull(catalog, "catalog");
+ this.itemDto = (CatalogItemDtoAbstract<T, SpecT>) Preconditions.checkNotNull(itemDto, "itemDto");
+ }
+
+ public CatalogItem<T,SpecT> getDto() {
+ return itemDto;
+ }
+
+ /**
+ * Config not supported for catalog item. See {@link #getPlanYaml()}.
+ */
+ @Override
+ public ConfigurationSupportInternal config() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <U> U setConfig(ConfigKey<U> key, U val) {
+ return config().set(key, val);
+ }
+
+ @Override
+ public CatalogItemType getCatalogItemType() {
+ return itemDto.getCatalogItemType();
+ }
+
+ @Override
+ public Class<T> getCatalogItemJavaType() {
+ return itemDto.getCatalogItemJavaType();
+ }
+
+ @Override
+ public String getId() {
+ return itemDto.getId();
+ }
+
+ @Override
+ public String getCatalogItemId() {
+ return itemDto.getCatalogItemId();
+ }
+
+ @Override
+ public void setDeprecated(boolean deprecated) {
+ itemDto.setDeprecated(deprecated);
+ }
+
+ @Override
+ public boolean isDeprecated() {
+ return itemDto.isDeprecated();
+ }
+
+ @Override
+ public void setCatalogItemId(String id) {
+ itemDto.setCatalogItemId(id);
+ }
+
+ @Override
+ public String getJavaType() {
+ return itemDto.getJavaType();
+ }
+
+ @Deprecated
+ @Override
+ public String getName() {
+ return getDisplayName();
+ }
+
+ @Deprecated
+ @Override
+ public String getRegisteredTypeName() {
+ return getSymbolicName();
+ }
+
+ @Override
+ public String getDisplayName() {
+ return itemDto.getDisplayName();
+ }
+
+ @Override
+ public TagSupport tags() {
+ return itemDto.tags();
+ }
+
+ @Override
+ public String getDescription() {
+ return itemDto.getDescription();
+ }
+
+ @Override
+ public String getIconUrl() {
+ return itemDto.getIconUrl();
+ }
+
+ @Override
+ public String getSymbolicName() {
+ return itemDto.getSymbolicName();
+ }
+
+ @Override
+ public String getVersion() {
+ return itemDto.getVersion();
+ }
+
+ @Nonnull // but it is still null sometimes, see in CatalogDo.loadJavaClass
+ @Override
+ public Collection<CatalogBundle> getLibraries() {
+ return itemDto.getLibraries();
+ }
+
+ /** @deprecated since 0.7.0 this is the legacy mechanism; still needed for policies and apps, but being phased out.
+ * new items should use {@link #getPlanYaml} and {@link #newClassLoadingContext} */
+ @Deprecated
+ public Class<T> getJavaClass() {
+ if (javaClass==null) loadJavaClass(null);
+ return javaClass;
+ }
+
+ @SuppressWarnings("unchecked")
+ Class<? extends T> loadJavaClass(final ManagementContext mgmt) {
+ if (javaClass!=null) return javaClass;
+ javaClass = (Class<T>)CatalogUtils.newClassLoadingContext(mgmt, getId(), getLibraries(), catalog.getRootClassLoader()).loadClass(getJavaType());
+ return javaClass;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getCanonicalName()+"["+itemDto+"]";
+ }
+
+ @Override
+ public String toXmlString() {
+ return itemDto.toXmlString();
+ }
+
+ @Override
+ public Class<SpecT> getSpecType() {
+ return itemDto.getSpecType();
+ }
+
+ @Nullable @Override
+ public String getPlanYaml() {
+ return itemDto.getPlanYaml();
+ }
+
+ @Override
+ public RebindSupport<CatalogItemMemento> getRebindSupport() {
+ return itemDto.getRebindSupport();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
new file mode 100644
index 0000000..5aa073b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
@@ -0,0 +1,404 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.basic.AbstractBrooklynObject;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.rebind.RebindSupport;
+import org.apache.brooklyn.api.mementos.CatalogItemMemento;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.rebind.BasicCatalogItemRebindSupport;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.flags.FlagUtils;
+import brooklyn.util.flags.SetFromFlag;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynObject implements CatalogItem<T, SpecT> {
+
+ private static Logger LOG = LoggerFactory.getLogger(CatalogItemDtoAbstract.class);
+
+ private @SetFromFlag String symbolicName;
+ private @SetFromFlag String version = BasicBrooklynCatalog.NO_VERSION;
+
+ private @SetFromFlag String displayName;
+ private @SetFromFlag String description;
+ private @SetFromFlag String iconUrl;
+
+ private @SetFromFlag String javaType;
+ /**@deprecated since 0.7.0, left for deserialization backwards compatibility */
+ private @Deprecated @SetFromFlag String type;
+ private @SetFromFlag String planYaml;
+
+ private @SetFromFlag Collection<CatalogBundle> libraries;
+ private @SetFromFlag Set<Object> tags = Sets.newLinkedHashSet();
+ private @SetFromFlag boolean deprecated;
+
+ /**
+ * Config not supported for catalog item. See {@link #getPlanYaml()}.
+ */
+ @Override
+ public ConfigurationSupportInternal config() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <U> U setConfig(ConfigKey<U> key, U val) {
+ return config().set(key, val);
+ }
+
+ @Override
+ public String getId() {
+ return getCatalogItemId();
+ }
+
+ @Override
+ public String getCatalogItemId() {
+ return CatalogUtils.getVersionedId(getSymbolicName(), getVersion());
+ }
+
+ @Override
+ public String getJavaType() {
+ if (javaType != null) return javaType;
+ return type;
+ }
+
+ @Deprecated
+ public String getName() {
+ return getDisplayName();
+ }
+
+ @Deprecated
+ public String getRegisteredTypeName() {
+ return getSymbolicName();
+ }
+
+ @Override
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getIconUrl() {
+ return iconUrl;
+ }
+
+ @Override
+ public String getSymbolicName() {
+ if (symbolicName != null) return symbolicName;
+ return getJavaType();
+ }
+
+ @Override
+ public String getVersion() {
+ // The property is set to NO_VERSION when the object is initialized so it's not supposed to be null ever.
+ // But xstream doesn't call constructors when reading from the catalog.xml file which results in null value
+ // for the version property. That's why we have to fix it in the getter.
+ if (version != null) {
+ return version;
+ } else {
+ return BasicBrooklynCatalog.NO_VERSION;
+ }
+ }
+
+ @Override
+ public boolean isDeprecated() {
+ return deprecated;
+ }
+
+ @Override
+ public void setDeprecated(boolean deprecated) {
+ this.deprecated = deprecated;
+ }
+
+ @Nonnull
+ @Override
+ public Collection<CatalogBundle> getLibraries() {
+ if (libraries != null) {
+ return ImmutableList.copyOf(libraries);
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Nullable @Override
+ public String getPlanYaml() {
+ return planYaml;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(symbolicName, planYaml, javaType, nullIfEmpty(libraries), version, getCatalogItemId());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ CatalogItemDtoAbstract<?,?> other = (CatalogItemDtoAbstract<?,?>) obj;
+ if (!Objects.equal(symbolicName, other.symbolicName)) return false;
+ if (!Objects.equal(planYaml, other.planYaml)) return false;
+ if (!Objects.equal(javaType, other.javaType)) return false;
+ if (!Objects.equal(nullIfEmpty(libraries), nullIfEmpty(other.libraries))) return false;
+ if (!Objects.equal(getCatalogItemId(), other.getCatalogItemId())) return false;
+ if (!Objects.equal(version, other.version)) return false;
+ if (!Objects.equal(deprecated, other.deprecated)) return false;
+ if (!Objects.equal(description, other.description)) return false;
+ if (!Objects.equal(displayName, other.displayName)) return false;
+ if (!Objects.equal(iconUrl, other.iconUrl)) return false;
+ if (!Objects.equal(tags, other.tags)) return false;
+ // 'type' not checked, because deprecated,
+ // and in future we might want to allow it to be removed/blanked in some impls without affecting equality
+ // (in most cases it is the same as symbolicName so doesn't matter)
+ return true;
+ }
+
+ private static <T> Collection<T> nullIfEmpty(Collection<T> coll) {
+ if (coll==null || coll.isEmpty()) return null;
+ return coll;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()+"["+getId()+"/"+getDisplayName()+"]";
+ }
+
+ public abstract Class<SpecT> getSpecType();
+
+ transient CatalogXmlSerializer serializer;
+
+ @Override
+ public String toXmlString() {
+ if (serializer==null) loadSerializer();
+ return serializer.toString(this);
+ }
+
+ private synchronized void loadSerializer() {
+ if (serializer == null) {
+ serializer = new CatalogXmlSerializer();
+ }
+ }
+
+ @Override
+ public RebindSupport<CatalogItemMemento> getRebindSupport() {
+ return new BasicCatalogItemRebindSupport(this);
+ }
+
+ @Override
+ public void setDisplayName(String newName) {
+ this.displayName = newName;
+ }
+
+ @Override
+ protected AbstractBrooklynObject configure(Map<?, ?> flags) {
+ FlagUtils.setFieldsFromFlags(flags, this);
+ return this;
+ }
+
+ @Override
+ public TagSupport tags() {
+ return new BasicTagSupport();
+ }
+
+ /*
+ * Using a custom tag support class rather than the one in AbstractBrooklynObject because
+ * when XStream unmarshals a catalog item with no tags (e.g. from any catalog.xml file)
+ * super.tags will be null, and any call to getTags throws a NullPointerException on the
+ * synchronized (tags) statement. It can't just be initialised here because super.tags is
+ * final.
+ */
+ private class BasicTagSupport implements TagSupport {
+
+ private void setTagsIfNull() {
+ // Possible if the class was unmarshalled by Xstream with no tags
+ synchronized (CatalogItemDtoAbstract.this) {
+ if (tags == null) {
+ tags = Sets.newLinkedHashSet();
+ }
+ }
+ }
+
+ @Nonnull
+ @Override
+ public Set<Object> getTags() {
+ synchronized (CatalogItemDtoAbstract.this) {
+ setTagsIfNull();
+ return ImmutableSet.copyOf(tags);
+ }
+ }
+
+ @Override
+ public boolean containsTag(Object tag) {
+ synchronized (CatalogItemDtoAbstract.this) {
+ setTagsIfNull();
+ return tags.contains(tag);
+ }
+ }
+
+ @Override
+ public boolean addTag(Object tag) {
+ boolean result;
+ synchronized (CatalogItemDtoAbstract.this) {
+ setTagsIfNull();
+ result = tags.add(tag);
+ }
+ onTagsChanged();
+ return result;
+ }
+
+ @Override
+ public boolean addTags(Iterable<?> newTags) {
+ boolean result;
+ synchronized (CatalogItemDtoAbstract.this) {
+ setTagsIfNull();
+ result = Iterables.addAll(tags, newTags);
+ }
+ onTagsChanged();
+ return result;
+ }
+
+ @Override
+ public boolean removeTag(Object tag) {
+ boolean result;
+ synchronized (CatalogItemDtoAbstract.this) {
+ setTagsIfNull();
+ result = tags.remove(tag);
+ }
+ onTagsChanged();
+ return result;
+ }
+ }
+
+ @Override
+ @Deprecated
+ public void setCatalogItemId(String id) {
+ //no op, should be used by rebind code only
+ }
+
+ protected void setSymbolicName(String symbolicName) {
+ this.symbolicName = symbolicName;
+ }
+
+ protected void setVersion(String version) {
+ this.version = version;
+ }
+
+ protected void setDescription(String description) {
+ this.description = description;
+ }
+
+ protected void setIconUrl(String iconUrl) {
+ this.iconUrl = iconUrl;
+ }
+
+ protected void setJavaType(String javaType) {
+ this.javaType = javaType;
+ this.type = null;
+ }
+
+ protected void setPlanYaml(String planYaml) {
+ this.planYaml = planYaml;
+ }
+
+ protected void setLibraries(Collection<CatalogBundle> libraries) {
+ this.libraries = libraries;
+ }
+
+ protected void setTags(Set<Object> tags) {
+ this.tags = tags;
+ }
+
+ protected void setSerializer(CatalogXmlSerializer serializer) {
+ this.serializer = serializer;
+ }
+
+ /**
+ * Parses an instance of CatalogLibrariesDto from the given List. Expects the list entries
+ * to be either Strings or Maps of String -> String. Will skip items that are not.
+ */
+ public static Collection<CatalogBundle> parseLibraries(Collection<?> possibleLibraries) {
+ Collection<CatalogBundle> dto = MutableList.of();
+ for (Object object : possibleLibraries) {
+ if (object instanceof Map) {
+ Map<?, ?> entry = (Map<?, ?>) object;
+ String name = stringValOrNull(entry, "name");
+ String version = stringValOrNull(entry, "version");
+ String url = stringValOrNull(entry, "url");
+ dto.add(new CatalogBundleDto(name, version, url));
+ } else if (object instanceof String) {
+ String inlineRef = (String) object;
+
+ final String name;
+ final String version;
+ final String url;
+
+ //Infer reference type (heuristically)
+ if (inlineRef.contains("/") || inlineRef.contains("\\")) {
+ //looks like an url/file path
+ name = null;
+ version = null;
+ url = inlineRef;
+ } else if (CatalogUtils.looksLikeVersionedId(inlineRef)) {
+ //looks like a name+version ref
+ name = CatalogUtils.getIdFromVersionedId(inlineRef);
+ version = CatalogUtils.getVersionFromVersionedId(inlineRef);
+ url = null;
+ } else {
+ //assume it to be relative url
+ name = null;
+ version = null;
+ url = inlineRef;
+ }
+
+ dto.add(new CatalogBundleDto(name, version, url));
+ } else {
+ LOG.debug("Unexpected entry in libraries list neither string nor map: " + object);
+ }
+ }
+ return dto;
+ }
+
+ private static String stringValOrNull(Map<?, ?> map, String key) {
+ Object val = map.get(key);
+ return val != null ? String.valueOf(val) : null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLibrariesDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLibrariesDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLibrariesDo.java
new file mode 100644
index 0000000..99041d2
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLibrariesDo.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.Collection;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+
+import com.google.common.base.Preconditions;
+
+@Deprecated
+public class CatalogLibrariesDo implements CatalogItem.CatalogItemLibraries {
+
+ private final CatalogLibrariesDto librariesDto;
+
+
+ public CatalogLibrariesDo(CatalogLibrariesDto librariesDto) {
+ this.librariesDto = Preconditions.checkNotNull(librariesDto, "librariesDto");
+ }
+
+ @Override
+ public Collection<String> getBundles() {
+ return librariesDto.getBundles();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLibrariesDto.java
new file mode 100644
index 0000000..6f2aba8
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLibrariesDto.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+
+import com.google.common.collect.ImmutableList;
+
+@Deprecated
+public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
+
+ private final Collection<String> bundles;
+
+ public CatalogLibrariesDto() {
+ this.bundles = Collections.emptyList();
+ }
+
+ public CatalogLibrariesDto(Collection<String> bundles) {
+ this.bundles = bundles;
+ }
+
+ /**
+ * @return An immutable copy of the bundle URLs referenced by this object
+ */
+ @Override
+ public Collection<String> getBundles() {
+ if (bundles == null) {
+ // can be null on deserialization
+ return Collections.emptyList();
+ }
+ return ImmutableList.copyOf(bundles);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLocationItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLocationItemDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLocationItemDto.java
new file mode 100644
index 0000000..c8206ce
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogLocationItemDto.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+
+
+public class CatalogLocationItemDto extends CatalogItemDtoAbstract<Location,LocationSpec<?>> {
+
+ @Override
+ public CatalogItemType getCatalogItemType() {
+ return CatalogItemType.LOCATION;
+ }
+
+ @Override
+ public Class<Location> getCatalogItemJavaType() {
+ return Location.class;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Class<LocationSpec<?>> getSpecType() {
+ return (Class)LocationSpec.class;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogPolicyItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogPolicyItemDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogPolicyItemDto.java
new file mode 100644
index 0000000..1c7e6fe
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogPolicyItemDto.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
+
+
+public class CatalogPolicyItemDto extends CatalogItemDtoAbstract<Policy,PolicySpec<?>> {
+
+ @Override
+ public CatalogItemType getCatalogItemType() {
+ return CatalogItemType.POLICY;
+ }
+
+ @Override
+ public Class<Policy> getCatalogItemJavaType() {
+ return Policy.class;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Class<PolicySpec<?>> getSpecType() {
+ return (Class)PolicySpec.class;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogTemplateItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogTemplateItemDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogTemplateItemDto.java
new file mode 100644
index 0000000..229a39c
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogTemplateItemDto.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+
+public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,EntitySpec<? extends Application>> {
+
+ @Override
+ public CatalogItemType getCatalogItemType() {
+ return CatalogItemType.TEMPLATE;
+ }
+
+ @Override
+ public Class<Application> getCatalogItemJavaType() {
+ return Application.class;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Class<EntitySpec<? extends Application>> getSpecType() {
+ return (Class)EntitySpec.class;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
new file mode 100644
index 0000000..378e450
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.Collection;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.basic.BrooklynObjectInternal;
+
+import org.apache.brooklyn.api.basic.BrooklynObject;
+import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
+import org.apache.brooklyn.core.management.classloading.BrooklynClassLoadingContextSequential;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.classloading.OsgiBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.ha.OsgiManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
+import brooklyn.config.BrooklynLogging;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Joiner;
+import com.google.common.base.Stopwatch;
+
+public class CatalogUtils {
+ private static final Logger log = LoggerFactory.getLogger(CatalogUtils.class);
+
+ public static final char VERSION_DELIMITER = ':';
+
+ public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, CatalogItem<?, ?> item) {
+ // TODO getLibraries() should never be null but sometimes it is still
+ // e.g. run CatalogResourceTest without the above check
+ if (item.getLibraries() == null) {
+ log.debug("CatalogItemDtoAbstract.getLibraries() is null.", new Exception("Trace for null CatalogItemDtoAbstract.getLibraries()"));
+ }
+ return newClassLoadingContext(mgmt, item.getId(), item.getLibraries());
+ }
+
+ public static BrooklynClassLoadingContext getClassLoadingContext(Entity entity) {
+ ManagementContext mgmt = ((EntityInternal)entity).getManagementContext();
+ String catId = entity.getCatalogItemId();
+ if (Strings.isBlank(catId)) return JavaBrooklynClassLoadingContext.create(mgmt);
+ CatalogItem<?, ?> cat = getCatalogItemOptionalVersion(mgmt, catId);
+ if (cat==null) {
+ log.warn("Cannot load "+catId+" to get classloader for "+entity+"; will try with standard loader, but might fail subsequently");
+ return JavaBrooklynClassLoadingContext.create(mgmt);
+ }
+ return newClassLoadingContext(mgmt, cat);
+ }
+
+ public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<CatalogBundle> libraries) {
+ BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
+
+ if (libraries!=null && !libraries.isEmpty()) {
+ result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, libraries));
+ }
+
+ BrooklynClassLoadingContext loader = BrooklynLoaderTracker.getLoader();
+ if (loader != null) {
+ result.add(loader);
+ }
+
+ result.addSecondary(JavaBrooklynClassLoadingContext.create(mgmt));
+ return result;
+ }
+
+ /**
+ * @deprecated since 0.7.0 only for legacy catalog items which provide a non-osgi loader; see {@link #newDefault(ManagementContext)}
+ */ @Deprecated
+ public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<CatalogBundle> libraries, ClassLoader customClassLoader) {
+ BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
+
+ if (libraries!=null && !libraries.isEmpty()) {
+ result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, libraries));
+ }
+
+ BrooklynClassLoadingContext loader = BrooklynLoaderTracker.getLoader();
+ if (loader != null) {
+ result.add(loader);
+ }
+
+ result.addSecondary(JavaBrooklynClassLoadingContext.create(mgmt, customClassLoader));
+ return result;
+ }
+
+ /**
+ * Registers all bundles with the management context's OSGi framework.
+ */
+ public static void installLibraries(ManagementContext managementContext, @Nullable Collection<CatalogBundle> libraries) {
+ if (libraries == null) return;
+
+ ManagementContextInternal mgmt = (ManagementContextInternal) managementContext;
+ if (!libraries.isEmpty()) {
+ Maybe<OsgiManager> osgi = mgmt.getOsgiManager();
+ if (osgi.isAbsent()) {
+ throw new IllegalStateException("Unable to load bundles "+libraries+" because OSGi is not running.");
+ }
+ if (log.isDebugEnabled())
+ logDebugOrTraceIfRebinding(log,
+ "Loading bundles in {}: {}",
+ new Object[] {managementContext, Joiner.on(", ").join(libraries)});
+ Stopwatch timer = Stopwatch.createStarted();
+ for (CatalogBundle bundleUrl : libraries) {
+ osgi.get().registerBundle(bundleUrl);
+ }
+ if (log.isDebugEnabled())
+ logDebugOrTraceIfRebinding(log,
+ "Registered {} bundles in {}",
+ new Object[]{libraries.size(), Time.makeTimeStringRounded(timer)});
+ }
+ }
+
+ /** Scans the given {@link BrooklynClassLoadingContext} to detect what catalog item id is in effect. */
+ public static String getCatalogItemIdFromLoader(BrooklynClassLoadingContext loader) {
+ if (loader instanceof OsgiBrooklynClassLoadingContext) {
+ return ((OsgiBrooklynClassLoadingContext)loader).getCatalogItemId();
+ } else {
+ return null;
+ }
+ }
+
+ public static void setCatalogItemIdOnAddition(Entity entity, BrooklynObject itemBeingAdded) {
+ if (entity.getCatalogItemId()!=null) {
+ if (itemBeingAdded.getCatalogItemId()==null) {
+ if (log.isDebugEnabled())
+ BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(entity),
+ "Catalog item addition: "+entity+" from "+entity.getCatalogItemId()+" applying its catalog item ID to "+itemBeingAdded);
+ ((BrooklynObjectInternal)itemBeingAdded).setCatalogItemId(entity.getCatalogItemId());
+ } else {
+ if (!itemBeingAdded.getCatalogItemId().equals(entity.getCatalogItemId())) {
+ // not a problem, but something to watch out for
+ log.debug("Cross-catalog item detected: "+entity+" from "+entity.getCatalogItemId()+" has "+itemBeingAdded+" from "+itemBeingAdded.getCatalogItemId());
+ }
+ }
+ } else if (itemBeingAdded.getCatalogItemId()!=null) {
+ if (log.isDebugEnabled())
+ BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(entity),
+ "Catalog item addition: "+entity+" without catalog item ID has "+itemBeingAdded+" from "+itemBeingAdded.getCatalogItemId());
+ }
+ }
+
+ @Beta
+ public static void logDebugOrTraceIfRebinding(Logger log, String message, Object ...args) {
+ if (RebindTracker.isRebinding())
+ log.trace(message, args);
+ else
+ log.debug(message, args);
+ }
+
+ public static boolean looksLikeVersionedId(String versionedId) {
+ if (versionedId==null) return false;
+ int fi = versionedId.indexOf(VERSION_DELIMITER);
+ if (fi<0) return false;
+ int li = versionedId.lastIndexOf(VERSION_DELIMITER);
+ if (li!=fi) {
+ // if multiple colons, we say it isn't a versioned reference; the prefix in that case must understand any embedded versioning scheme
+ // this fixes the case of: http://localhost:8080
+ return false;
+ }
+ String candidateVersion = versionedId.substring(li+1);
+ if (!candidateVersion.matches("[0-9]+(|(\\.|_).*)")) {
+ // version must start with a number, followed if by anything with full stop or underscore before any other characters
+ // e.g. foo:1 or foo:1.1 or foo:1_SNAPSHOT all supported, but not e.g. foo:bar (or chef:cookbook or docker:my/image)
+ return false;
+ }
+ return true;
+ }
+
+ public static String getIdFromVersionedId(String versionedId) {
+ if (versionedId == null) return null;
+ int versionDelimiterPos = versionedId.lastIndexOf(VERSION_DELIMITER);
+ if (versionDelimiterPos != -1) {
+ return versionedId.substring(0, versionDelimiterPos);
+ } else {
+ return null;
+ }
+ }
+
+ public static String getVersionFromVersionedId(String versionedId) {
+ if (versionedId == null) return null;
+ int versionDelimiterPos = versionedId.lastIndexOf(VERSION_DELIMITER);
+ if (versionDelimiterPos != -1) {
+ return versionedId.substring(versionDelimiterPos+1);
+ } else {
+ return null;
+ }
+ }
+
+ public static String getVersionedId(String id, String version) {
+ // TODO null checks
+ return id + VERSION_DELIMITER + version;
+ }
+
+ //TODO Don't really like this, but it's better to have it here than on the interface to keep the API's
+ //surface minimal. Could instead have the interface methods accept VerionedId object and have the helpers
+ //construct it as needed.
+ public static CatalogItem<?, ?> getCatalogItemOptionalVersion(ManagementContext mgmt, String versionedId) {
+ if (versionedId == null) return null;
+ if (looksLikeVersionedId(versionedId)) {
+ String id = getIdFromVersionedId(versionedId);
+ String version = getVersionFromVersionedId(versionedId);
+ return mgmt.getCatalog().getCatalogItem(id, version);
+ } else {
+ return mgmt.getCatalog().getCatalogItem(versionedId, BrooklynCatalog.DEFAULT_VERSION);
+ }
+ }
+
+ public static boolean isBestVersion(ManagementContext mgmt, CatalogItem<?,?> item) {
+ CatalogItem<?, ?> bestVersion = getCatalogItemOptionalVersion(mgmt, item.getSymbolicName());
+ if (bestVersion==null) return false;
+ return (bestVersion.getVersion().equals(item.getVersion()));
+ }
+
+ public static <T,SpecT> CatalogItem<T, SpecT> getCatalogItemOptionalVersion(ManagementContext mgmt, Class<T> type, String versionedId) {
+ if (looksLikeVersionedId(versionedId)) {
+ String id = getIdFromVersionedId(versionedId);
+ String version = getVersionFromVersionedId(versionedId);
+ return mgmt.getCatalog().getCatalogItem(type, id, version);
+ } else {
+ return mgmt.getCatalog().getCatalogItem(type, versionedId, BrooklynCatalog.DEFAULT_VERSION);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java
new file mode 100644
index 0000000..462e00e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogXmlSerializer.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+
+import brooklyn.basic.AbstractBrooklynObject;
+import brooklyn.util.xstream.EnumCaseForgivingSingleValueConverter;
+import brooklyn.util.xstream.XmlSerializer;
+
+public class CatalogXmlSerializer extends XmlSerializer<Object> {
+
+ @SuppressWarnings("deprecation")
+ public CatalogXmlSerializer() {
+ xstream.addDefaultImplementation(ArrayList.class, Collection.class);
+
+ xstream.aliasType("list", List.class);
+ xstream.aliasType("map", Map.class);
+
+ xstream.useAttributeFor("id", String.class);
+
+ xstream.aliasType("catalog", CatalogDto.class);
+ xstream.useAttributeFor(CatalogDto.class, "url");
+ xstream.addImplicitCollection(CatalogDto.class, "catalogs", CatalogDto.class);
+ xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogTemplateItemDto.class);
+ xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogEntityItemDto.class);
+ xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogPolicyItemDto.class);
+ xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogLocationItemDto.class);
+
+ xstream.aliasType("template", CatalogTemplateItemDto.class);
+ xstream.aliasType("entity", CatalogEntityItemDto.class);
+ xstream.aliasType("policy", CatalogPolicyItemDto.class);
+ xstream.aliasType("location", CatalogPolicyItemDto.class);
+
+ xstream.aliasField("registeredType", CatalogItemDtoAbstract.class, "symbolicName");
+ xstream.aliasAttribute(CatalogItemDtoAbstract.class, "displayName", "name");
+ xstream.useAttributeFor(CatalogItemDtoAbstract.class, "type");
+ xstream.useAttributeFor(CatalogItemDtoAbstract.class, "version");
+ xstream.aliasType("bundle", CatalogBundleDto.class);
+ xstream.registerConverter(new CatalogBundleConverter(xstream.getMapper(), xstream.getReflectionProvider()));
+
+ xstream.useAttributeFor(CatalogClasspathDto.class, "scan");
+ xstream.addImplicitCollection(CatalogClasspathDto.class, "entries", "entry", String.class);
+ xstream.registerConverter(new EnumCaseForgivingSingleValueConverter(CatalogScanningModes.class));
+
+ // Note: the management context is being omitted because it is unnecessary for
+ // representations of catalogues generated with this serializer.
+ xstream.omitField(AbstractBrooklynObject.class, "managementContext");
+ xstream.omitField(AbstractBrooklynObject.class, "_legacyConstruction");
+ xstream.omitField(AbstractBrooklynObject.class, "hasWarnedOfNoManagementContextWhenPersistRequested");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java
index af5920b..84baa20 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java
@@ -26,11 +26,11 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.ha.OsgiManager;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.util.guava.Maybe;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
index 25d8281..bda7f6f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
@@ -42,6 +42,8 @@ import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
import org.apache.brooklyn.api.management.ha.MementoCopyMode;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister.Delta;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogDto;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.ha.BasicMasterChooser.AlphabeticMasterChooser;
import org.apache.brooklyn.core.management.internal.BrooklynObjectManagementMode;
@@ -53,8 +55,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.BrooklynVersion;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.internal.CatalogDto;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynTaskTags;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
index 1758846..58e2f60 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
@@ -50,13 +50,13 @@ import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
import org.apache.brooklyn.api.management.ha.HighAvailabilityManager;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.StringConfigMap;
import brooklyn.entity.basic.AbstractEntity;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
index 97a3d73..6c993d8 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
@@ -29,9 +29,9 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.ha.OsgiManager;
-import brooklyn.catalog.internal.CatalogInitialization;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.proxying.InternalEntityFactory;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java
index 9d98792..693e254 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java
@@ -59,10 +59,10 @@ import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.ha.OsgiManager;
-import brooklyn.catalog.internal.CatalogInitialization;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.StringConfigMap;
import brooklyn.entity.basic.AbstractEntity;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java b/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
index 9a6466e..3cb9f14 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
@@ -40,9 +40,9 @@ import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationResolver;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
import org.apache.brooklyn.core.management.internal.LocalLocationManager;
-import brooklyn.catalog.CatalogPredicates;
import brooklyn.config.ConfigMap;
import brooklyn.config.ConfigPredicates;
import brooklyn.config.ConfigUtils;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/location/basic/CatalogLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/CatalogLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/basic/CatalogLocationResolver.java
index 0866649..55902ee 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/CatalogLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/CatalogLocationResolver.java
@@ -30,8 +30,7 @@ import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationResolver;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
-
-import brooklyn.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
/**
* Given a location spec in the form {@code brooklyn.catalog:<symbolicName>:<version>},
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/BrooklynVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/BrooklynVersionTest.java b/core/src/test/java/brooklyn/BrooklynVersionTest.java
index 179e698..ebcfbd9 100644
--- a/core/src/test/java/brooklyn/BrooklynVersionTest.java
+++ b/core/src/test/java/brooklyn/BrooklynVersionTest.java
@@ -34,10 +34,9 @@ import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-import brooklyn.catalog.internal.CatalogEntityItemDto;
-import brooklyn.catalog.internal.CatalogItemBuilder;
-import brooklyn.catalog.internal.CatalogItemDtoAbstract;
-
+import org.apache.brooklyn.core.catalog.internal.CatalogEntityItemDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
import org.apache.brooklyn.test.TestResourceUnavailableException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index 73cf5ce..d5590fc 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -49,13 +49,13 @@ import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
-import brooklyn.catalog.CatalogPredicates;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.internal.CatalogDto;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
deleted file mode 100644
index 25a050e..0000000
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-import org.apache.brooklyn.core.management.internal.LocalManagementContext;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.apache.brooklyn.test.entity.TestEntity;
-
-import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-import brooklyn.entity.basic.Entities;
-import brooklyn.util.BrooklynMavenArtifacts;
-import brooklyn.util.maven.MavenRetriever;
-
-import com.google.common.collect.ImmutableList;
-
-public class CatalogDtoTest {
-
- private static final Logger log = LoggerFactory.getLogger(CatalogDtoTest.class);
-
- private LocalManagementContext managementContext;
-
- @BeforeMethod(alwaysRun = true)
- public void setUp() throws Exception {
- managementContext = LocalManagementContextForTests.newInstanceWithOsgi();
- }
-
- @AfterMethod(alwaysRun = true)
- public void tearDown() throws Exception {
- if (managementContext != null) Entities.destroyAll(managementContext);
- }
-
- @Test(groups="Integration")
- public void testCatalogLookup() {
- CatalogDto root = buildExampleCatalog();
- checkCatalogHealthy(root);
- }
-
- @Test(groups="Integration")
- public void testCatalogSerializeAndLookup() {
- CatalogDto root = buildExampleCatalog();
- CatalogXmlSerializer serializer = new CatalogXmlSerializer();
-
- String xml = serializer.toString(root);
- log.info("Example catalog serialized as:\n"+xml);
-
- CatalogDto root2 = (CatalogDto) serializer.fromString(xml);
- checkCatalogHealthy(root2);
- }
-
- protected void checkCatalogHealthy(CatalogDto root) {
- assertEquals(root.catalogs.size(), 4);
- CatalogDo loader = new CatalogDo(managementContext, root).load();
-
- // test app comes from jar, by default
- CatalogItemDo<?,?> worker = loader.getIdCache().get(CatalogUtils.getVersionedId(TestApplication.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION));
- assertNotNull(worker);
- assertEquals(worker.getDisplayName(), "Test App from JAR");
-
- // TODO can test scanned elements, links to other catalogs, etc
- }
-
- public CatalogDto buildExampleCatalog() {
- CatalogDo root = new CatalogDo(
- managementContext,
- CatalogDto.newNamedInstance("My Local Catalog",
- "My favourite local settings, including remote catalogs -- intended partly as a teaching " +
- "example for what can be expressed, and how", "contents-built-in-test"));
- root.setClasspathScanForEntities(CatalogScanningModes.NONE);
-
- String bundleUrl = MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests"));
- CatalogDo testEntitiesJavaCatalog = new CatalogDo(
- managementContext,
- CatalogDto.newNamedInstance("Test Entities from Java", null, "test-java"));
- testEntitiesJavaCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
- testEntitiesJavaCatalog.addToClasspath(bundleUrl);
- testEntitiesJavaCatalog.addEntry(CatalogItemBuilder.newTemplate(TestApplication.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION)
- .displayName("Test App from JAR")
- .javaType(TestApplication.class.getCanonicalName())
- .build());
- testEntitiesJavaCatalog.addEntry(CatalogItemBuilder.newEntity(TestEntity.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION)
- .displayName("Test Entity from JAR")
- .javaType(TestEntity.class.getCanonicalName())
- .build());
- root.addCatalog(testEntitiesJavaCatalog.dto);
-
- CatalogDo testEntitiesJavaCatalogScanning = new CatalogDo(
- managementContext,
- CatalogDto.newNamedInstance("Test Entities from Java Scanning", null, "test-java-scan"));
- testEntitiesJavaCatalogScanning.addToClasspath(bundleUrl);
- testEntitiesJavaCatalogScanning.setClasspathScanForEntities(CatalogScanningModes.ANNOTATIONS);
- root.addCatalog(testEntitiesJavaCatalogScanning.dto);
-
- CatalogDo osgiCatalog = new CatalogDo(
- managementContext,
- CatalogDto.newNamedInstance("Test Entities from OSGi",
- "A catalog whose entries define their libraries as a list of OSGi bundles", "test-osgi-defined"));
- osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
- CatalogEntityItemDto osgiEntity = CatalogItemBuilder.newEntity(TestEntity.class.getCanonicalName(), "Test Entity from OSGi")
- // NB: this is not actually an OSGi bundle, but it's okay as we don't instantiate the bundles ahead of time (currently)
- .libraries(ImmutableList.<CatalogBundle>of(new CatalogBundleDto(null, null, bundleUrl)))
- .build();
- testEntitiesJavaCatalog.addEntry(osgiEntity);
- root.addCatalog(osgiCatalog.dto);
-
- root.addCatalog(CatalogDto.newLinkedInstance("classpath://brooklyn-catalog-empty.xml"));
- return root.dto;
- }
-
- @Test
- public void testVersionedIdSplitter() {
- String id = "simple.id";
- String version = "0.1.2";
- String versionedId = CatalogUtils.getVersionedId(id, version);
-
- Assert.assertNull(CatalogUtils.getIdFromVersionedId(null));
- Assert.assertNull(CatalogUtils.getVersionFromVersionedId(null));
- Assert.assertNull(CatalogUtils.getIdFromVersionedId(id));
- Assert.assertNull(CatalogUtils.getVersionFromVersionedId(version));
- Assert.assertEquals(CatalogUtils.getIdFromVersionedId(versionedId), id);
- Assert.assertEquals(CatalogUtils.getVersionFromVersionedId(versionedId), version);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/catalog/internal/CatalogItemComparatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogItemComparatorTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogItemComparatorTest.java
deleted file mode 100644
index 3e6fe6b..0000000
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogItemComparatorTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import org.testng.annotations.Test;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-
-public class CatalogItemComparatorTest {
- private static final String RC2 = "10.5.8-rc2";
- private static final String STABLE = "10.5.8";
-
- @Test
- public void testComparison() {
- compare("0.0.1", "0.0.2", 1);
- compare("0.0.2", "0.0.1", -1);
- compare("0.0.1-qual", "0.0.2", 1);
- compare("0.0.1.qual", "0.0.2", 1);
- compare("0.0.1-qual", "0.0.1_qual", 0);
- compare("0.0.1.qual", "0.0.1.qual", 0);
- compare("0.0.1", "0.0.2-SNAPSHOT", -1);
- compare("0.0.1", "0.0.2.SNAPSHOT", -1);
- compare("0.0.0_SNAPSHOT", "0.0.1-SNAPSHOT-20141111114709760", 1);
- compare("0.0.0.SNAPSHOT", "0.0.1.SNAPSHOT-20141111114709760", 1);
- compare("2.0", "2.0.1-BUILD", 1);
- compare("2.0", "2.0.1.BUILD", 1);
- compare("2.0.1", "2.0-BUILD", -1);
- compare("2.0.1", "2.0.0.BUILD", -1);
- compare("2.0", "2.0-BUILD", -1);
- // Note not true for .qualifier: compare("2.0", "2.0.0.BUILD", -1);
- compare("2.1", "2.0-BUILD", -1);
- compare("2.1", "2.0.0.BUILD", -1);
- compare("1", "1.3", 1);
- compare("1-beta", "1-rc2", 1);
- // Note not true for .qualifier: compare("1.0.0.beta", "1.0.0.rc2", 1);
- compare("1-beta1", "1-beta10", 1);
-
- compare(STABLE, "10.5", -1);
- compare(STABLE, STABLE, 0);
-
- compare(STABLE, "10.6", 1);
- compare(STABLE, "10.5.8.1", 1);
-
- compare("10.5.8-rc2", "10.5.8-rc3", 1) ;
- compare("10.5.8-rc2", "10.5.8-rc1", -1);
-
- compare(STABLE, RC2, -1);
-
- CatalogItemComparator cmp = CatalogItemComparator.INSTANCE;
- assertTrue(cmp.compare(v(RC2), v("10.5.8-beta1")) == cmp.compare(v(RC2), v("10.5.8-beta3")));
- }
-
- private void compare(String v1, String v2, int expected) {
- CatalogItemComparator cmp = CatalogItemComparator.INSTANCE;
- assertEquals(cmp.compare(v(v1), v(v2)), expected);
- assertEquals(cmp.compare(v(v2), v(v1)), -expected);
- }
-
- private CatalogItem<?, ?> v(String version) {
- return CatalogItemBuilder.newEntity("xxx", version).build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
deleted file mode 100644
index 2e92897..0000000
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogLoadTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-
-import brooklyn.util.ResourceUtils;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.Iterables;
-
-public class CatalogLoadTest {
-
- CatalogXmlSerializer serializer;
-
- @BeforeMethod
- public void setUp() {
- serializer = new CatalogXmlSerializer();
- }
-
- private String loadFile(String file) {
- return ResourceUtils.create(this).getResourceAsString(file);
- }
-
- // CAMP YAML parsing not available in core, so YAML catalog tests are in camp, e.g. CatalogYamlEntitiesTest
-
- @Test
- public void testLoadXmlCatalog() {
- CatalogDto catalog = (CatalogDto) serializer.fromString(
- loadFile("classpath://brooklyn/catalog/internal/osgi-catalog.xml"));
- assertNotNull(catalog);
- assertEquals(catalog.name, "OSGi catalogue");
- assertEquals(Iterables.size(catalog.getUniqueEntries()), 1, "Catalog entries = " + Joiner.on(", ").join(catalog.getUniqueEntries()));
-
- CatalogItemDtoAbstract<?,?> template = Iterables.getOnlyElement(catalog.getUniqueEntries());
- assertEquals(template.getDisplayName(), "Entity name");
- assertEquals(template.getVersion(), "9.1.3");
- assertEquals(template.getJavaType(), "com.example.ExampleApp");
- assertEquals(template.getLibraries().size(), 2,
- "Template bundles=" + Joiner.on(", ").join(template.getLibraries()));
-
- boolean foundBundle1 = false, foundBundle2 = false;
- for (CatalogBundle bundle : template.getLibraries()) {
- if (bundle.getUrl().equals("file://path/to/bundle.jar")) {
- foundBundle1 = true;
- }
- if (bundle.getUrl().equals("http://www.url.com/for/bundle.jar")) {
- foundBundle2 = true;
- }
- }
- assertTrue(foundBundle1);
- assertTrue(foundBundle2);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
deleted file mode 100644
index c417421..0000000
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.net.URLEncoder;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-import org.apache.brooklyn.api.catalog.BrooklynCatalog;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.core.management.internal.LocalManagementContext;
-
-import brooklyn.catalog.CatalogPredicates;
-import brooklyn.catalog.internal.MyCatalogItems.MySillyAppTemplate;
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.entity.basic.Entities;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.net.Urls;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
-public class CatalogScanTest {
-
- private static final Logger log = LoggerFactory.getLogger(CatalogScanTest.class);
-
- private BrooklynCatalog defaultCatalog, annotsCatalog, fullCatalog;
-
- private List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList();
-
- @AfterMethod(alwaysRun = true)
- public void tearDown(){
- for (LocalManagementContext managementContext : managementContexts) {
- Entities.destroyAll(managementContext);
- }
- managementContexts.clear();
- }
-
- private LocalManagementContext newManagementContext(BrooklynProperties props) {
- LocalManagementContext result = new LocalManagementContext(props);
- managementContexts.add(result);
- return result;
- }
-
- private synchronized void loadFullCatalog() {
- if (fullCatalog!=null) return;
- BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
- props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(),
- "data:,"+Urls.encode("<catalog><classpath scan=\"types\"/></catalog>"));
- fullCatalog = newManagementContext(props).getCatalog();
- log.info("ENTITIES loaded for FULL: "+fullCatalog.getCatalogItems(Predicates.alwaysTrue()));
- }
-
- private synchronized void loadTheDefaultCatalog(boolean lookOnDiskForDefaultCatalog) {
- if (defaultCatalog!=null) return;
- BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
- props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(),
- // if default catalog is picked up from the system, we might get random stuff from ~/.brooklyn/ instead of the default;
- // useful as an integration check that we default correctly, but irritating for people to use if they have such a catalog installed
- (lookOnDiskForDefaultCatalog ? "" :
- "data:,"+Urls.encode(new ResourceUtils(this).getResourceAsString("classpath:/brooklyn/default.catalog.bom"))));
- LocalManagementContext managementContext = newManagementContext(props);
- defaultCatalog = managementContext.getCatalog();
- log.info("ENTITIES loaded for DEFAULT: "+defaultCatalog.getCatalogItems(Predicates.alwaysTrue()));
- }
-
- @SuppressWarnings("deprecation")
- private synchronized void loadAnnotationsOnlyCatalog() {
- if (annotsCatalog!=null) return;
- BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
- props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(),
- "data:,"+URLEncoder.encode("<catalog><classpath scan=\"annotations\"/></catalog>"));
- LocalManagementContext managementContext = newManagementContext(props);
- annotsCatalog = managementContext.getCatalog();
- log.info("ENTITIES loaded with annotation: "+annotsCatalog.getCatalogItems(Predicates.alwaysTrue()));
- }
-
- @Test
- public void testLoadAnnotations() {
- loadAnnotationsOnlyCatalog();
- BrooklynCatalog c = annotsCatalog;
-
- Iterable<CatalogItem<Object,Object>> bases = c.getCatalogItems(CatalogPredicates.displayName(Predicates.containsPattern("MyBaseEntity")));
- Assert.assertEquals(Iterables.size(bases), 0, "should have been empty: "+bases);
-
- Iterable<CatalogItem<Object,Object>> asdfjkls = c.getCatalogItems(CatalogPredicates.displayName(Predicates.containsPattern("__asdfjkls__shouldnotbefound")));
- Assert.assertEquals(Iterables.size(asdfjkls), 0);
-
- Iterable<CatalogItem<Object,Object>> silly1 = c.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppTemplate")));
- Iterable<CatalogItem<Object,Object>> silly2 = c.getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(MySillyAppTemplate.class.getName())));
- CatalogItem<Object, Object> silly1El = Iterables.getOnlyElement(silly1);
- Assert.assertEquals(silly1El, Iterables.getOnlyElement(silly2));
-
- CatalogItem<Application,EntitySpec<? extends Application>> s1 = c.getCatalogItem(Application.class, silly1El.getSymbolicName(), silly1El.getVersion());
- Assert.assertEquals(s1, silly1El);
-
- Assert.assertEquals(s1.getDescription(), "Some silly app test");
-
- Class<? extends Application> app = c.loadClass(s1);
- Assert.assertEquals(MySillyAppTemplate.class, app);
-
- String xml = ((BasicBrooklynCatalog)c).toXmlString();
- log.info("Catalog is:\n"+xml);
- Assert.assertTrue(xml.indexOf("Some silly app test") >= 0);
- }
-
- @Test
- public void testAnnotationLoadsSomeApps() {
- loadAnnotationsOnlyCatalog();
- Iterable<CatalogItem<Object,Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppTemplate")));
- Assert.assertEquals(Iterables.getOnlyElement(silly1).getDescription(), "Some silly app test");
- }
-
- @Test
- public void testAnnotationLoadsSomeAppBuilders() {
- loadAnnotationsOnlyCatalog();
- Iterable<CatalogItem<Object,Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppBuilderTemplate")));
- Assert.assertEquals(Iterables.getOnlyElement(silly1).getDescription(), "Some silly app builder test");
- }
-
- @Test
- public void testMoreTypesThanAnnotations() {
- loadAnnotationsOnlyCatalog();
- loadFullCatalog();
-
- int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(Predicates.alwaysTrue()));
- int numFromTypes = Iterables.size(fullCatalog.getCatalogItems(Predicates.alwaysTrue()));
-
- Assert.assertTrue(numFromAnnots < numFromTypes, "full="+numFromTypes+" annots="+numFromAnnots);
- }
-
- @Test
- public void testMoreTypesThanAnnotationsForApps() {
- loadAnnotationsOnlyCatalog();
- loadFullCatalog();
-
- int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(CatalogPredicates.IS_TEMPLATE));
- int numFromTypes = Iterables.size(fullCatalog.getCatalogItems(CatalogPredicates.IS_TEMPLATE));
-
- Assert.assertTrue(numFromAnnots < numFromTypes, "full="+numFromTypes+" annots="+numFromAnnots);
- }
-
- @Test
- public void testAnnotationIsDefault() {
- doTestAnnotationIsDefault(false);
- }
-
- // see comment in load method; likely fails if a custom catalog is installed in ~/.brooklyn/
- @Test(groups="Integration", enabled=false)
- public void testAnnotationIsDefaultOnDisk() {
- doTestAnnotationIsDefault(true);
- }
-
- private void doTestAnnotationIsDefault(boolean lookOnDiskForDefaultCatalog) {
- loadTheDefaultCatalog(false);
- int numInDefault = Iterables.size(defaultCatalog.getCatalogItems(Predicates.alwaysTrue()));
-
- loadAnnotationsOnlyCatalog();
- int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(Predicates.alwaysTrue()));
-
- Assert.assertEquals(numInDefault, numFromAnnots);
- Assert.assertTrue(numInDefault>0, "Expected more than 0 entries");
- }
-
- // a simple test asserting no errors when listing the real catalog, and listing them for reference
- // also useful to test variants in a stored catalog to assert they all load
- // TODO integration tests which build up catalogs assuming other things are installed
- @Test
- public void testListCurrentCatalogItems() {
- LocalManagementContext mgmt = newManagementContext(BrooklynProperties.Factory.newDefault());
- log.info("ITEMS\n"+Strings.join(mgmt.getCatalog().getCatalogItems(), "\n"));
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/catalog/internal/CatalogTestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogTestUtils.java b/core/src/test/java/brooklyn/catalog/internal/CatalogTestUtils.java
deleted file mode 100644
index b420860..0000000
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogTestUtils.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-
-import com.google.common.annotations.Beta;
-
-public class CatalogTestUtils {
-
- /** creates entity spec with the java type of a catalog item;
- * would be nice to have this in {@link CatalogUtils},
- * but the logic for parsing the yaml is buried in camp code,
- * so it's a little bit hard to make this a first class method.
- * <p>
- * (this impl ignores many things, including config and location.)
- */
- @Beta
- public static EntitySpec<?> createEssentialEntitySpec(ManagementContext mgmt, CatalogItem<?, ?> catalogItem) {
- BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, catalogItem);
- @SuppressWarnings({ "unchecked", "rawtypes" })
- EntitySpec<?> spec = EntitySpec.create( (Class)loader.loadClass(catalogItem.getJavaType()) );
- spec.catalogItemId(catalogItem.getId());
- return spec;
- }
-
-}
[16/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/classloading/ClassLoaderFromBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/management/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
new file mode 100644
index 0000000..33aa4ca
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.classloading;
+
+import java.net.URL;
+
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+
+public class ClassLoaderFromBrooklynClassLoadingContext extends ClassLoader {
+
+ /** Constructs a {@link ClassLoader} which delegates to the given {@link BrooklynClassLoadingContext} */
+ public static ClassLoader of(BrooklynClassLoadingContext clc) {
+ return new ClassLoaderFromBrooklynClassLoadingContext(clc);
+ }
+
+ protected final BrooklynClassLoadingContext clc;
+
+ protected ClassLoaderFromBrooklynClassLoadingContext(BrooklynClassLoadingContext clc) {
+ this.clc = clc;
+ }
+
+ @Override
+ public Class<?> findClass(String className) throws ClassNotFoundException {
+ Class<?> result = clc.loadClass(className);
+ if (result!=null) return result;
+
+ // last resort. see comment in XStream CompositeClassLoader
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if (contextClassLoader != null) {
+ result = contextClassLoader.loadClass(className);
+ if (result!=null) return result;
+ }
+ return null;
+ }
+
+ @Override
+ protected URL findResource(String name) {
+ URL result = clc.getResource(name);
+ if (result!=null) return result;
+
+ // last resort. see comment in XStream CompositeClassLoader
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if (contextClassLoader != null) {
+ result = contextClassLoader.getResource(name);
+ if (result!=null) return result;
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/classloading/JavaBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/classloading/JavaBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/management/classloading/JavaBrooklynClassLoadingContext.java
new file mode 100644
index 0000000..99fa15b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/classloading/JavaBrooklynClassLoadingContext.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.classloading;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Objects;
+
+public class JavaBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
+
+ // on deserialization this loader is replaced with the catalog's root loader;
+ // may cause problems for non-osgi catalog items, but that's a reasonable trade-off,
+ // should this be serialized (e.g. in SpecialFlagsTransformer) in such a case!
+ private final transient ClassLoader loader;
+
+ /**
+ * @deprecated since 0.7.0 only for legacy catalog items which provide a non-osgi loader; see {@link #newDefault(ManagementContext)}
+ */ @Deprecated
+ public static JavaBrooklynClassLoadingContext create(ClassLoader loader) {
+ return new JavaBrooklynClassLoadingContext(null, checkNotNull(loader, "loader"));
+ }
+
+ /**
+ * At least one of mgmt or loader must not be null.
+ * @deprecated since 0.7.0 only for legacy catalog items which provide a non-osgi loader; see {@link #newDefault(ManagementContext)}
+ */ @Deprecated
+ public static JavaBrooklynClassLoadingContext create(ManagementContext mgmt, ClassLoader loader) {
+ checkState(mgmt != null || loader != null, "mgmt and loader must not both be null");
+ return new JavaBrooklynClassLoadingContext(mgmt, loader);
+ }
+
+ public static JavaBrooklynClassLoadingContext create(ManagementContext mgmt) {
+ return new JavaBrooklynClassLoadingContext(checkNotNull(mgmt, "mgmt"), null);
+ }
+
+ @Deprecated /** @deprecated since 0.7.0 use {@link #create(ManagementContext)} */
+ public static JavaBrooklynClassLoadingContext newDefault(ManagementContext mgmt) {
+ return new JavaBrooklynClassLoadingContext(checkNotNull(mgmt, "mgmt"), null);
+ }
+
+ @Deprecated /** @deprecated since 0.7.0 will become private; use one of the static methods to instantiate */
+ public JavaBrooklynClassLoadingContext(ManagementContext mgmt, ClassLoader loader) {
+ super(mgmt);
+ this.loader = loader;
+ }
+
+ private ClassLoader getClassLoader() {
+ if (loader != null) return loader;
+ if (mgmt!=null) return mgmt.getCatalogClassLoader();
+ return JavaBrooklynClassLoadingContext.class.getClassLoader();
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public Maybe<Class<?>> tryLoadClass(String className) {
+ try {
+ return (Maybe) Maybe.of(getClassLoader().loadClass(className));
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ return Maybe.absent("Invalid class: "+className, e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "java:"+getClassLoader();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), getClassLoader());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.equals(obj)) return false;
+ if (!(obj instanceof JavaBrooklynClassLoadingContext)) return false;
+ if (!Objects.equal(getClassLoader(), ((JavaBrooklynClassLoadingContext)obj).getClassLoader())) return false;
+ return true;
+ }
+
+ @Override
+ public URL getResource(String name) {
+ return getClassLoader().getResource(name);
+ }
+
+ @Override
+ public Iterable<URL> getResources(String name) {
+ Enumeration<URL> resources;
+ try {
+ resources = getClassLoader().getResources(name);
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ }
+ return Collections.list(resources);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java
new file mode 100644
index 0000000..af5920b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/classloading/OsgiBrooklynClassLoadingContext.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.classloading;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.ha.OsgiManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Objects;
+
+public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
+
+ private final String catalogItemId;
+ private boolean hasBundles = false;
+ private transient Collection<CatalogBundle> _bundles;
+
+ public OsgiBrooklynClassLoadingContext(ManagementContext mgmt, String catalogItemId, Collection<CatalogBundle> bundles) {
+ super(mgmt);
+ this._bundles = bundles;
+ this.hasBundles = bundles!=null && !bundles.isEmpty();
+ this.catalogItemId = catalogItemId;
+ }
+
+ public Collection<CatalogBundle> getBundles() {
+ if (_bundles!=null || !hasBundles) return _bundles;
+ CatalogItem<?, ?> cat = CatalogUtils.getCatalogItemOptionalVersion(mgmt, catalogItemId);
+ if (cat==null) {
+ throw new IllegalStateException("Catalog item not found for "+catalogItemId+"; cannot create loading context");
+ }
+ _bundles = cat.getLibraries();
+ return _bundles;
+ }
+
+ @Override
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Maybe<Class<?>> tryLoadClass(String className) {
+ Maybe<Class<Object>> clazz = null;
+ Maybe<OsgiManager> osgi = null;
+ if (mgmt!=null) {
+ osgi = ((ManagementContextInternal)mgmt).getOsgiManager();
+ if (osgi.isPresent() && getBundles()!=null && !getBundles().isEmpty()) {
+ if (!Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, catalogItemId))
+ return Maybe.absent("Not entitled to use this catalog entry");
+
+ clazz = osgi.get().tryResolveClass(className, getBundles());
+ if (clazz.isPresent())
+ return (Maybe)clazz;
+ }
+ }
+
+ if (clazz!=null) {
+ // if OSGi bundles were defined and failed, then use its error message
+ return (Maybe)clazz;
+ }
+ // else determine best message
+ if (mgmt==null) return Maybe.absent("No mgmt context available for loading "+className);
+ if (osgi!=null && osgi.isAbsent()) return Maybe.absent("OSGi not available on mgmt for loading "+className);
+ if (!hasBundles)
+ return Maybe.absent("No bundles available for loading "+className);
+ return Maybe.absent("Inconsistent state ("+mgmt+"/"+osgi+"/"+getBundles()+" loading "+className);
+ }
+
+ @Override
+ public String toString() {
+ return "OSGi:"+catalogItemId+"["+getBundles()+"]";
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), getBundles(), catalogItemId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.equals(obj)) return false;
+ if (!(obj instanceof OsgiBrooklynClassLoadingContext)) return false;
+
+ OsgiBrooklynClassLoadingContext other = (OsgiBrooklynClassLoadingContext)obj;
+ if (!catalogItemId.equals(other.catalogItemId)) return false;
+ if (!Objects.equal(getBundles(), other.getBundles())) return false;
+ return true;
+ }
+
+ @Override
+ public URL getResource(String name) {
+ if (mgmt != null && isEntitledToSeeCatalogItem()) {
+ Maybe<OsgiManager> osgi = ((ManagementContextInternal) mgmt).getOsgiManager();
+ if (osgi.isPresent() && hasBundles) {
+ return osgi.get().getResource(name, getBundles());
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Iterable<URL> getResources(String name) {
+ if (mgmt != null && isEntitledToSeeCatalogItem()) {
+ Maybe<OsgiManager> osgi = ((ManagementContextInternal) mgmt).getOsgiManager();
+ if (osgi.isPresent() && hasBundles) {
+ return osgi.get().getResources(name, getBundles());
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ public String getCatalogItemId() {
+ return catalogItemId;
+ }
+
+ /**
+ * @return true if the current entitlement context may {@link Entitlements#SEE_CATALOG_ITEM see}
+ * {@link #getCatalogItemId}.
+ */
+ private boolean isEntitledToSeeCatalogItem() {
+ return Entitlements.isEntitled(mgmt.getEntitlementManager(),
+ Entitlements.SEE_CATALOG_ITEM,
+ catalogItemId);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/entitlement/BasicEntitlementClassDefinition.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/BasicEntitlementClassDefinition.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/BasicEntitlementClassDefinition.java
new file mode 100644
index 0000000..07544a6
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/BasicEntitlementClassDefinition.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+
+import com.google.common.base.Objects;
+import com.google.common.reflect.TypeToken;
+
+
+public class BasicEntitlementClassDefinition<T> implements EntitlementClass<T> {
+
+ private final String identifier;
+ private final TypeToken<T> argumentType;
+
+ public BasicEntitlementClassDefinition(String identifier, TypeToken<T> argumentType) {
+ this.identifier = identifier;
+ this.argumentType = argumentType;
+ }
+
+ public BasicEntitlementClassDefinition(String identifier, Class<T> argumentType) {
+ this.identifier = identifier;
+ this.argumentType = TypeToken.of(argumentType);
+ }
+
+ @Override
+ public String entitlementClassIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public TypeToken<T> entitlementClassArgumentType() {
+ return argumentType;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).add("identitifier", identifier).add("argumentType", argumentType).toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/entitlement/EntitlementManagerAdapter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/EntitlementManagerAdapter.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/EntitlementManagerAdapter.java
new file mode 100644
index 0000000..a331a48
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/EntitlementManagerAdapter.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.EntitlementClassesHandler;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * provides an easy entry point to supplying entitlements, by providing the dispatch and defining the additional methods
+ * which have to be supplied.
+ * <p>
+ * note that this class may change as versions change, deliberately breaking backwards compatibility
+ * to ensure all permissions are used.
+ * <p>
+ * @since 0.7.0 */
+@Beta
+public abstract class EntitlementManagerAdapter implements EntitlementManager {
+
+ private static final Logger log = LoggerFactory.getLogger(EntitlementManagerAdapter.class);
+
+ protected class Handler implements EntitlementClassesHandler<Boolean> {
+ final EntitlementContext context;
+ protected Handler(EntitlementContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public Boolean handleSeeCatalogItem(String catalogItemId) {
+ return isEntitledToSeeCatalogItem(context, catalogItemId);
+ }
+ @Override
+ public Boolean handleAddCatalogItem(Object catalogItemBeingAdded) {
+ return isEntitledToAddCatalogItem(context, catalogItemBeingAdded);
+ }
+ @Override
+ public Boolean handleModifyCatalogItem(StringAndArgument catalogItemIdAndModification) {
+ return isEntitledToModifyCatalogItem(context, catalogItemIdAndModification==null ? null : catalogItemIdAndModification.getString(),
+ catalogItemIdAndModification==null ? null : catalogItemIdAndModification.getArgument());
+ }
+
+ @Override
+ public Boolean handleSeeEntity(Entity entity) {
+ return isEntitledToSeeEntity(context, entity);
+ }
+ @Override
+ public Boolean handleSeeSensor(EntityAndItem<String> sensorInfo) {
+ return isEntitledToSeeSensor(context, sensorInfo.getEntity(), sensorInfo.getItem());
+ }
+ @Override
+ public Boolean handleInvokeEffector(EntityAndItem<StringAndArgument> effectorInfo) {
+ StringAndArgument item = effectorInfo.getItem();
+ return isEntitledToInvokeEffector(context, effectorInfo.getEntity(), item==null ? null : item.getString(), item==null ? null : item.getArgument());
+ }
+ @Override
+ public Boolean handleModifyEntity(Entity entity) {
+ return isEntitledToModifyEntity(context, entity);
+ }
+
+ @Override
+ public Boolean handleDeployApplication(Object app) {
+ return isEntitledToDeployApplication(context, app);
+ }
+
+ @Override
+ public Boolean handleSeeAllServerInfo() {
+ return isEntitledToSeeAllServerInfo(context);
+ }
+
+ @Override
+ public Boolean handleSeeServerStatus() {
+ return isEntitledToSeeServerStatus(context);
+ }
+
+ @Override
+ public Boolean handleRoot() {
+ return isEntitledToRoot(context);
+ }
+ }
+
+ @Override
+ public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
+ if (log.isTraceEnabled()) {
+ log.trace("Checking entitlement of "+context+" to "+entitlementClass+" "+entitlementClassArgument);
+ }
+
+ if (isEntitledToRoot( context )) return true;
+
+ Handler handler = new Handler(context);
+ return Entitlements.EntitlementClassesEnum.of(entitlementClass).handle(
+ handler, entitlementClassArgument);
+ }
+
+ protected abstract boolean isEntitledToSeeCatalogItem(EntitlementContext context, String catalogItemId);
+ /** passes item to be added, either yaml, or possibly null if any addition allowed (eg when resetting) */
+ protected abstract boolean isEntitledToAddCatalogItem(EntitlementContext context, Object catalogItemBeingAdded);
+ /** passes item being modified, as ID and description of modification, both possibly null if any modification is allowed (eg when resetting) */
+ protected abstract boolean isEntitledToModifyCatalogItem(EntitlementContext context, String catalogItemId, Object catalogItemModification);
+ protected abstract boolean isEntitledToSeeSensor(EntitlementContext context, Entity entity, String sensorName);
+ protected abstract boolean isEntitledToSeeEntity(EntitlementContext context, Entity entity);
+ /** arguments might be null, a map, or a list, depending how/where invoked */
+ protected abstract boolean isEntitledToInvokeEffector(EntitlementContext context, Entity entity, String effectorName, Object arguments);
+ protected abstract boolean isEntitledToModifyEntity(EntitlementContext context, Entity entity);
+ protected abstract boolean isEntitledToDeployApplication(EntitlementContext context, Object app);
+ protected abstract boolean isEntitledToSeeAllServerInfo(EntitlementContext context);
+ protected abstract boolean isEntitledToSeeServerStatus(EntitlementContext context);
+ protected abstract boolean isEntitledToRoot(EntitlementContext context);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/entitlement/EntitlementPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/EntitlementPredicates.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/EntitlementPredicates.java
new file mode 100644
index 0000000..085fb9e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/EntitlementPredicates.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+
+import com.google.common.base.Predicate;
+
+public class EntitlementPredicates {
+
+ public static <T> Predicate<T> isEntitled(final EntitlementManager entitlementManager, final EntitlementClass<T> entitlementClass) {
+
+ return new Predicate<T>() {
+ @Override
+ public boolean apply(@Nullable T t) {
+ return Entitlements.isEntitled(entitlementManager, entitlementClass, t);
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java
new file mode 100644
index 0000000..6bf9329
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/Entitlements.java
@@ -0,0 +1,418 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.TypeToken;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.javalang.Reflections;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.text.Strings;
+
+/** @since 0.7.0 */
+@Beta
+public class Entitlements {
+
+ private static final Logger log = LoggerFactory.getLogger(Entitlements.class);
+
+ // ------------------- individual permissions
+
+ public static EntitlementClass<String> SEE_CATALOG_ITEM = new BasicEntitlementClassDefinition<String>("catalog.see", String.class);
+ public static EntitlementClass<Object> ADD_CATALOG_ITEM = new BasicEntitlementClassDefinition<Object>("catalog.add", Object.class);
+ public static EntitlementClass<StringAndArgument> MODIFY_CATALOG_ITEM = new BasicEntitlementClassDefinition<StringAndArgument>("catalog.modify", StringAndArgument.class);
+
+ public static EntitlementClass<Entity> SEE_ENTITY = new BasicEntitlementClassDefinition<Entity>("entity.see", Entity.class);
+ public static EntitlementClass<EntityAndItem<String>> SEE_SENSOR = new BasicEntitlementClassDefinition<EntityAndItem<String>>("sensor.see", EntityAndItem. typeToken(String.class));
+ // string is effector name; argument may be a map or a list, depending how the args were supplied
+ public static EntitlementClass<EntityAndItem<StringAndArgument>> INVOKE_EFFECTOR = new BasicEntitlementClassDefinition<EntityAndItem<StringAndArgument>>("effector.invoke", EntityAndItem.typeToken(StringAndArgument.class));
+ public static EntitlementClass<Entity> MODIFY_ENTITY = new BasicEntitlementClassDefinition<Entity>("entity.modify", Entity.class);
+
+ /** the permission to deploy an application, where parameter is some representation of the app to be deployed (spec instance or yaml plan) */
+ public static EntitlementClass<Object> DEPLOY_APPLICATION = new BasicEntitlementClassDefinition<Object>("app.deploy", Object.class);
+
+ /** catch-all for catalog, locations, scripting, usage, etc - exporting persistence, shutting down, etc;
+ * this is significantly more powerful than {@link #SERVER_STATUS}.
+ * NB: this may be refactored and deprecated in future */
+ public static EntitlementClass<Void> SEE_ALL_SERVER_INFO = new BasicEntitlementClassDefinition<Void>("server.info.all.see", Void.class);
+
+ /** permission to see general server status info: basically HA status; not nearly as much as {@link #SEE_ALL_SERVER_INFO} */
+ public static EntitlementClass<Void> SERVER_STATUS = new BasicEntitlementClassDefinition<Void>("server.status", Void.class);
+
+ /** permission to run untrusted code or embedded scripts at the server;
+ * secondary check required for any operation which could potentially grant root-level access */
+ public static EntitlementClass<Void> ROOT = new BasicEntitlementClassDefinition<Void>("root", Void.class);
+
+ @SuppressWarnings("unchecked")
+ public static enum EntitlementClassesEnum {
+ ENTITLEMENT_SEE_CATALOG_ITEM(SEE_CATALOG_ITEM) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeCatalogItem((String)argument); } },
+ ENTITLEMENT_ADD_CATALOG_ITEM(ADD_CATALOG_ITEM) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleAddCatalogItem(argument); } },
+ ENTITLEMENT_MODIFY_CATALOG_ITEM(MODIFY_CATALOG_ITEM) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleModifyCatalogItem((StringAndArgument)argument); } },
+
+ ENTITLEMENT_SEE_ENTITY(SEE_ENTITY) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeEntity((Entity)argument); } },
+ ENTITLEMENT_SEE_SENSOR(SEE_SENSOR) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeSensor((EntityAndItem<String>)argument); } },
+ ENTITLEMENT_INVOKE_EFFECTOR(INVOKE_EFFECTOR) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleInvokeEffector((EntityAndItem<StringAndArgument>)argument); } },
+ ENTITLEMENT_MODIFY_ENTITY(MODIFY_ENTITY) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleModifyEntity((Entity)argument); } },
+
+ ENTITLEMENT_DEPLOY_APPLICATION(DEPLOY_APPLICATION) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleDeployApplication(argument); } },
+
+ ENTITLEMENT_SEE_ALL_SERVER_INFO(SEE_ALL_SERVER_INFO) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeAllServerInfo(); } },
+ ENTITLEMENT_SERVER_STATUS(SERVER_STATUS) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeServerStatus(); } },
+ ENTITLEMENT_ROOT(ROOT) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleRoot(); } },
+ ;
+
+ private EntitlementClass<?> entitlementClass;
+
+ private EntitlementClassesEnum(EntitlementClass<?> specificClass) {
+ this.entitlementClass = specificClass;
+ }
+ public EntitlementClass<?> getEntitlementClass() {
+ return entitlementClass;
+ }
+
+ public abstract <T> T handle(EntitlementClassesHandler<T> handler, Object argument);
+
+ public static EntitlementClassesEnum of(EntitlementClass<?> entitlementClass) {
+ for (EntitlementClassesEnum x: values()) {
+ if (entitlementClass.equals(x.getEntitlementClass())) return x;
+ }
+ return null;
+ }
+ }
+
+ public interface EntitlementClassesHandler<T> {
+ public T handleSeeCatalogItem(String catalogItemId);
+ public T handleSeeServerStatus();
+ public T handleAddCatalogItem(Object catalogItemBeingAdded);
+ public T handleModifyCatalogItem(StringAndArgument catalogItemIdAndModification);
+ public T handleSeeEntity(Entity entity);
+ public T handleSeeSensor(EntityAndItem<String> sensorInfo);
+ public T handleInvokeEffector(EntityAndItem<StringAndArgument> effectorInfo);
+ public T handleModifyEntity(Entity entity);
+ public T handleDeployApplication(Object app);
+ public T handleSeeAllServerInfo();
+ public T handleRoot();
+ }
+
+ protected static class Pair<T1,T2> {
+ protected final T1 p1;
+ protected final T2 p2;
+ protected Pair(T1 p1, T2 p2) { this.p1 = p1; this.p2 = p2; }
+ }
+ public static class EntityAndItem<T> extends Pair<Entity,T> {
+ public static <TT> TypeToken<EntityAndItem<TT>> typeToken(Class<TT> type) {
+ return new TypeToken<Entitlements.EntityAndItem<TT>>() {
+ private static final long serialVersionUID = -738154831809025407L;
+ };
+ }
+ public EntityAndItem(Entity entity, T item) { super (entity, item); }
+ public Entity getEntity() { return p1; }
+ public T getItem() { return p2; }
+ public static <T> EntityAndItem<T> of(Entity entity, T item) {
+ return new EntityAndItem<T>(entity, item);
+ }
+ }
+
+ public static class StringAndArgument extends Pair<String,Object> {
+ public StringAndArgument(String string, Object argument) { super(string, argument); }
+ public String getString() { return p1; }
+ public Object getArgument() { return p2; }
+ public static StringAndArgument of(String string, Object argument) {
+ return new StringAndArgument(string, argument);
+ }
+ }
+
+ /**
+ * These lifecycle operations are currently treated as effectors. This may change in the future.
+ * @since 0.7.0 */
+ @Beta
+ public static class LifecycleEffectors {
+ public static final String DELETE = "delete";
+ }
+
+ // ------------- permission sets -------------
+
+ /** always ALLOW access to everything */
+ public static EntitlementManager root() {
+ return new EntitlementManager() {
+ @Override
+ public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
+ return true;
+ }
+ @Override
+ public String toString() {
+ return "Entitlements.root";
+ }
+ };
+ }
+
+ /** always DENY access to anything which requires entitlements */
+ public static EntitlementManager minimal() {
+ return new EntitlementManager() {
+ @Override
+ public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
+ return false;
+ }
+ @Override
+ public String toString() {
+ return "Entitlements.minimal";
+ }
+ };
+ }
+
+ public static class FineGrainedEntitlements {
+
+ private static final Joiner COMMA_JOINER = Joiner.on(',');
+
+ public static EntitlementManager anyOf(final EntitlementManager... checkers) {
+ return anyOf(Arrays.asList(checkers));
+ }
+
+ public static EntitlementManager anyOf(final Iterable<? extends EntitlementManager> checkers) {
+ return new EntitlementManager() {
+ @Override
+ public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
+ for (EntitlementManager checker: checkers)
+ if (checker.isEntitled(context, permission, typeArgument))
+ return true;
+ return false;
+ }
+ @Override
+ public String toString() {
+ return "Entitlements.anyOf(" + COMMA_JOINER.join(checkers) + ")";
+ }
+ };
+ }
+
+ public static EntitlementManager allOf(final EntitlementManager... checkers) {
+ return allOf(Arrays.asList(checkers));
+ }
+
+ public static EntitlementManager allOf(final Iterable<? extends EntitlementManager> checkers) {
+ return new EntitlementManager() {
+ @Override
+ public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
+ for (EntitlementManager checker: checkers)
+ if (checker.isEntitled(context, permission, typeArgument))
+ return true;
+ return false;
+ }
+ @Override
+ public String toString() {
+ return "Entitlements.allOf(" + COMMA_JOINER.join(checkers) + ")";
+ }
+ };
+ }
+
+ public static <U> EntitlementManager allowing(EntitlementClass<U> permission, Predicate<U> test) {
+ return new SinglePermissionEntitlementChecker<U>(permission, test);
+ }
+
+ public static <U> EntitlementManager allowing(EntitlementClass<U> permission) {
+ return new SinglePermissionEntitlementChecker<U>(permission, Predicates.<U>alwaysTrue());
+ }
+
+ public static class SinglePermissionEntitlementChecker<U> implements EntitlementManager {
+ final EntitlementClass<U> permission;
+ final Predicate<U> test;
+
+ protected SinglePermissionEntitlementChecker(EntitlementClass<U> permission, Predicate<U> test) {
+ this.permission = permission;
+ this.test = test;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
+ if (!Objects.equal(this.permission, permission)) return false;
+ return test.apply((U)typeArgument);
+ }
+ @Override
+ public String toString() {
+ return "Entitlements.allowing(" + permission + " -> " + test + ")";
+ }
+ }
+ public static EntitlementManager seeNonSecretSensors() {
+ return allowing(SEE_SENSOR, new Predicate<EntityAndItem<String>>() {
+ @Override
+ public boolean apply(EntityAndItem<String> input) {
+ if (input == null) return false;
+ return !Entities.isSecret(input.getItem());
+ }
+ @Override
+ public String toString() {
+ return "Predicates.nonSecret";
+ }
+ });
+ }
+
+ }
+
+ /** allow read-only */
+ public static EntitlementManager readOnly() {
+ return FineGrainedEntitlements.anyOf(
+ FineGrainedEntitlements.allowing(SEE_ENTITY),
+ FineGrainedEntitlements.seeNonSecretSensors()
+ );
+ }
+
+ /** allow healthcheck */
+ public static EntitlementManager serverStatusOnly() {
+ return FineGrainedEntitlements.allowing(SERVER_STATUS);
+ }
+
+ // ------------- lookup conveniences -------------
+
+ private static class PerThreadEntitlementContextHolder {
+ public static final ThreadLocal<EntitlementContext> perThreadEntitlementsContextHolder = new ThreadLocal<EntitlementContext>();
+ }
+
+ /**
+ * Finds the currently applicable {@link EntitlementContext} by examining the current thread
+ * then by investigating the current task, its submitter, etc. */
+ // NOTE: entitlements are propagated to tasks whenever they are created, as tags
+ // (see BrooklynTaskTags.tagForEntitlement and BasicExecutionContext.submitInternal).
+ // It might be cheaper to only do this lookup, not to propagate as tags, and to ensure
+ // all entitlement operations are wrapped in a task at source; but currently we do not
+ // do that so we need at least to set entitlement on the outermost task.
+ // Setting it on tasks submitted by a task is not strictly necessary (i.e. in BasicExecutionContext)
+ // but seems cheap enough, and means checking entitlements is fast, if we choose to do that more often.
+ public static EntitlementContext getEntitlementContext() {
+ EntitlementContext context;
+ context = PerThreadEntitlementContextHolder.perThreadEntitlementsContextHolder.get();
+ if (context!=null) return context;
+
+ Task<?> task = Tasks.current();
+ while (task!=null) {
+ context = BrooklynTaskTags.getEntitlement(task);
+ if (context!=null) return context;
+ task = task.getSubmittedByTask();
+ }
+
+ // no entitlements set -- assume entitlements not used, or system internal
+ return null;
+ }
+
+ public static void setEntitlementContext(EntitlementContext context) {
+ EntitlementContext oldContext = PerThreadEntitlementContextHolder.perThreadEntitlementsContextHolder.get();
+ if (oldContext!=null && context!=null) {
+ log.warn("Changing entitlement context from "+oldContext+" to "+context+"; context should have been reset or extended, not replaced");
+ log.debug("Trace for entitlement context duplicate overwrite", new Throwable("Trace for entitlement context overwrite"));
+ }
+ PerThreadEntitlementContextHolder.perThreadEntitlementsContextHolder.set(context);
+ }
+
+ public static void clearEntitlementContext() {
+ PerThreadEntitlementContextHolder.perThreadEntitlementsContextHolder.set(null);
+ }
+
+ public static <T> boolean isEntitled(EntitlementManager checker, EntitlementClass<T> permission, T typeArgument) {
+ return checker.isEntitled(getEntitlementContext(), permission, typeArgument);
+ }
+
+ /** throws {@link NotEntitledException} if entitlement not available for current {@link #getEntitlementContext()} */
+ public static <T> void checkEntitled(EntitlementManager checker, EntitlementClass<T> permission, T typeArgument) {
+ if (!isEntitled(checker, permission, typeArgument)) {
+ throw new NotEntitledException(getEntitlementContext(), permission, typeArgument);
+ }
+ }
+ /** throws {@link NotEntitledException} if entitlement not available for current {@link #getEntitlementContext()}
+ * @since 0.7.0
+ * @deprecated since 0.7.0, use {@link #checkEntitled(EntitlementManager, EntitlementClass, Object)};
+ * kept briefly because there is some downstream usage*/
+ public static <T> void requireEntitled(EntitlementManager checker, EntitlementClass<T> permission, T typeArgument) {
+ checkEntitled(checker, permission, typeArgument);
+ }
+
+ // ----------------- initialization ----------------
+
+ public final static String ENTITLEMENTS_CONFIG_PREFIX = "brooklyn.entitlements";
+
+ public static ConfigKey<String> GLOBAL_ENTITLEMENT_MANAGER = ConfigKeys.newStringConfigKey(ENTITLEMENTS_CONFIG_PREFIX+".global",
+ "Class for entitlements in effect globally; "
+ + "short names 'minimal', 'readonly', or 'root' are permitted here, with the default 'root' giving full access to all declared users; "
+ + "or supply the name of an "+EntitlementManager.class+" class to instantiate, taking a 1-arg BrooklynProperties constructor or a 0-arg constructor",
+ "root");
+
+ public static EntitlementManager newManager(ManagementContext mgmt, BrooklynProperties brooklynProperties) {
+ return newGlobalManager(mgmt, brooklynProperties);
+ }
+ private static EntitlementManager newGlobalManager(ManagementContext mgmt, BrooklynProperties brooklynProperties) {
+ return load(mgmt, brooklynProperties, brooklynProperties.getConfig(GLOBAL_ENTITLEMENT_MANAGER));
+ }
+
+ public static EntitlementManager load(@Nullable ManagementContext mgmt, BrooklynProperties brooklynProperties, String type) {
+ if ("root".equalsIgnoreCase(type)) return root();
+ if ("readonly".equalsIgnoreCase(type) || "read_only".equalsIgnoreCase(type)) return readOnly();
+ if ("minimal".equalsIgnoreCase(type)) return minimal();
+ if (Strings.isNonBlank(type)) {
+ try {
+ ClassLoader cl = mgmt==null ? null : ((ManagementContextInternal)mgmt).getCatalogClassLoader();
+ if (cl==null) cl = Entitlements.class.getClassLoader();
+ Class<?> clazz = cl.loadClass(type);
+ return (EntitlementManager) instantiate(clazz, ImmutableList.of(
+ new Object[] {mgmt, brooklynProperties},
+ new Object[] {mgmt},
+ new Object[] {brooklynProperties},
+ new Object[0]));
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+ throw new IllegalStateException("Invalid entitlement manager specified: '"+type+"'");
+ }
+
+ private static Object instantiate(Class<?> clazz, List<Object[]> constructorArgOptions) {
+ try {
+ for (Object[] constructorArgOption : constructorArgOptions) {
+ Optional<?> result = Reflections.invokeConstructorWithArgs(clazz, constructorArgOption);
+ if (result.isPresent()) return result.get();
+ }
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ throw new IllegalStateException("No matching constructor to instantiate "+clazz);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/entitlement/NotEntitledException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/NotEntitledException.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/NotEntitledException.java
new file mode 100644
index 0000000..aab7c0d
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/NotEntitledException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+
+
+public class NotEntitledException extends RuntimeException {
+
+ private static final long serialVersionUID = -4001882260980589181L;
+
+ EntitlementContext entitlementContext;
+ EntitlementClass<?> permission;
+ Object typeArgument;
+
+ public <T> NotEntitledException(EntitlementContext entitlementContext, EntitlementClass<T> permission, T typeArgument) {
+ this.entitlementContext = entitlementContext;
+ this.permission = permission;
+ this.typeArgument = typeArgument;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"["+entitlementContext+":"+permission+(typeArgument!=null ? "("+typeArgument+")" : "")+"]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManager.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManager.java
new file mode 100644
index 0000000..c5914e8
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManager.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigPredicates;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Preconditions;
+
+public class PerUserEntitlementManager implements EntitlementManager {
+
+ private static final Logger log = LoggerFactory.getLogger(PerUserEntitlementManager.class);
+
+ public final static String PER_USER_ENTITLEMENTS_CONFIG_PREFIX = Entitlements.ENTITLEMENTS_CONFIG_PREFIX+".perUser";
+
+ public final static ConfigKey<String> DEFAULT_MANAGER = ConfigKeys.newStringConfigKey(PER_USER_ENTITLEMENTS_CONFIG_PREFIX+
+ ".default", "Default entitlements manager for users without further specification", "minimal");
+
+ protected final EntitlementManager defaultManager;
+ protected final Map<String,EntitlementManager> perUserManagers = MutableMap.of();
+
+ private final static ThreadLocal<Boolean> ACTIVE = new ThreadLocal<Boolean>();
+
+ private static EntitlementManager load(BrooklynProperties properties, String type) {
+ if (Boolean.TRUE.equals(ACTIVE.get())) {
+ // prevent infinite loop
+ throw new IllegalStateException("Cannot set "+PerUserEntitlementManager.class.getName()+" within config for itself");
+ }
+ try {
+ ACTIVE.set(true);
+ return Entitlements.load(null, properties, type);
+ } finally {
+ ACTIVE.remove();
+ }
+ }
+
+ public PerUserEntitlementManager(BrooklynProperties properties) {
+ this(load(properties, properties.getConfig(DEFAULT_MANAGER)));
+
+ BrooklynProperties users = properties.submap(ConfigPredicates.startingWith(PER_USER_ENTITLEMENTS_CONFIG_PREFIX+"."));
+ for (Map.Entry<ConfigKey<?>,?> key: users.getAllConfig().entrySet()) {
+ if (key.getKey().getName().equals(DEFAULT_MANAGER.getName())) continue;
+ String user = Strings.removeFromStart(key.getKey().getName(), PER_USER_ENTITLEMENTS_CONFIG_PREFIX+".");
+ addUser(user, load(properties, Strings.toString(key.getValue())));
+ }
+
+ log.info(getClass().getSimpleName()+" created with "+perUserManagers.size()+" user"+Strings.s(perUserManagers)+" and "
+ + "default "+defaultManager+" (users: "+perUserManagers+")");
+ }
+
+ public PerUserEntitlementManager(EntitlementManager defaultManager) {
+ this.defaultManager = Preconditions.checkNotNull(defaultManager);
+ }
+
+ public void addUser(String user, EntitlementManager managerForThisUser) {
+ perUserManagers.put(Preconditions.checkNotNull(user, "user"), Preconditions.checkNotNull(managerForThisUser, "managerForThisUser"));
+ }
+
+ @Override
+ public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
+ EntitlementManager entitlementInEffect = null;
+ if (context==null || context.user()==null) {
+ // no user means it is running as an internal process, always has root
+ entitlementInEffect = Entitlements.root();
+ } else {
+ if (context!=null) entitlementInEffect = perUserManagers.get(context.user());
+ if (entitlementInEffect==null) entitlementInEffect = defaultManager;
+ }
+ return entitlementInEffect.isEntitled(context, entitlementClass, entitlementClassArgument);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManagerWithDefault.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManagerWithDefault.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManagerWithDefault.java
new file mode 100644
index 0000000..b4c7e38
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManagerWithDefault.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+
+@Deprecated
+/** @deprecated since 0.7.0 use {@link PerUserEntitlementManager} */
+public class PerUserEntitlementManagerWithDefault extends PerUserEntitlementManager {
+
+ public PerUserEntitlementManagerWithDefault(EntitlementManager defaultManager) {
+ super(defaultManager);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/entitlement/WebEntitlementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/entitlement/WebEntitlementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/WebEntitlementContext.java
new file mode 100644
index 0000000..2efed42
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/entitlement/WebEntitlementContext.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+
+import brooklyn.util.javalang.JavaClassNames;
+
+/**
+ * Indicates an authenticated web request as the entitlements context;
+ * note user may still be null if no authentication was requested
+ */
+public class WebEntitlementContext implements EntitlementContext {
+
+ final String user;
+ final String sourceIp;
+ final String requestUri;
+
+ /**
+ * A mostly-unique identifier for the inbound request, to distinguish
+ * between duplicate requests and for cross-referencing with URIs
+ */
+ final String requestUniqueIdentifier;
+
+ public WebEntitlementContext(String user, String sourceIp, String requestUri, String requestUniqueIdentifier) {
+ this.user = user;
+ this.sourceIp = sourceIp;
+ this.requestUri = requestUri;
+ this.requestUniqueIdentifier = requestUniqueIdentifier;
+ }
+
+ @Override public String user() { return user; }
+ public String sourceIp() { return sourceIp; }
+ public String requestUri() { return requestUri; }
+ public String requestUniqueIdentifier() { return requestUniqueIdentifier; }
+
+ @Override
+ public String toString() {
+ return JavaClassNames.simpleClassName(getClass())+"["+user+"@"+sourceIp+":"+requestUniqueIdentifier+"]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/ha/BasicMasterChooser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/BasicMasterChooser.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/BasicMasterChooser.java
new file mode 100644
index 0000000..034a6bd
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/BasicMasterChooser.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.brooklyn.api.entity.trait.Identifiable;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.text.NaturalOrderComparator;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Ordering;
+
+/**
+ * @since 0.7.0
+ *
+ * @author aled
+ */
+@Beta
+public abstract class BasicMasterChooser implements MasterChooser {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BasicMasterChooser.class);
+
+ protected static class ScoredRecord<T extends Comparable<T>> implements Identifiable, Comparable<ScoredRecord<T>> {
+ String id;
+ ManagementNodeSyncRecord record;
+ T score;
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public int compareTo(ScoredRecord<T> o) {
+ return score.compareTo(o.score);
+ }
+ }
+
+ public ManagementNodeSyncRecord choose(ManagementPlaneSyncRecord memento, Duration heartbeatTimeout, String ownNodeId) {
+ if (LOG.isDebugEnabled()) LOG.debug("Choosing new master from "+memento.getManagementNodes());
+ ManagementNodeSyncRecord me = memento.getManagementNodes().get(ownNodeId);
+ if (me==null) {
+ LOG.warn("Management node details not known when choosing new master: "+memento+" / "+ownNodeId);
+ return null;
+ }
+ Long nowIsh = me.getRemoteTimestamp();
+ if (nowIsh==null) {
+ LOG.warn("Management node for self missing timestamp when choosing new master: "+memento);
+ return null;
+ }
+
+ List<ScoredRecord<?>> contenders = filterHealthy(memento, heartbeatTimeout, nowIsh);
+
+ if (!contenders.isEmpty()) {
+ return pick(contenders);
+ } else {
+ LOG.info("No valid management node found for choosing new master: contender="+memento.getManagementNodes());
+ return null;
+ }
+ }
+
+ /** pick the best contender; argument guaranteed to be non-null and non-empty,
+ * filtered for health reasons */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected ManagementNodeSyncRecord pick(List<ScoredRecord<?>> contenders) {
+ ScoredRecord min = null;
+ for (ScoredRecord x: contenders) {
+ if (min==null || x.score.compareTo(min.score)<0) min = x;
+ }
+ return min.record;
+ }
+
+ public static class AlphabeticChooserScore implements Comparable<AlphabeticChooserScore> {
+ long priority;
+ int versionBias;
+ String brooklynVersion;
+ int statePriority;
+ String nodeId;
+
+ @Override
+ public int compareTo(AlphabeticChooserScore o) {
+ if (o==null) return -1;
+ return ComparisonChain.start()
+ // invert the order where we prefer higher values
+ .compare(o.priority, this.priority)
+ .compare(o.versionBias, this.versionBias)
+ .compare(o.brooklynVersion, this.brooklynVersion,
+ Ordering.from(NaturalOrderComparator.INSTANCE).nullsFirst())
+ .compare(o.statePriority, this.statePriority)
+ .compare(this.nodeId, o.nodeId, Ordering.usingToString().nullsLast())
+ .result();
+ }
+ }
+
+ /** comparator which prefers, in order:
+ * <li> higher explicit priority
+ * <li> non-snapshot Brooklyn version, then any Brooklyn version, and lastly null version
+ * (using {@link NaturalOrderComparator} so e.g. v10 > v3.20 > v3.9 )
+ * <li> higher version (null last)
+ * <li> node which reports it's master, hot standby, then standby
+ * <li> finally (common case): lower (alphabetically) node id
+ */
+ public static class AlphabeticMasterChooser extends BasicMasterChooser {
+ final boolean preferHotStandby;
+ public AlphabeticMasterChooser(boolean preferHotStandby) { this.preferHotStandby = preferHotStandby; }
+ public AlphabeticMasterChooser() { this.preferHotStandby = true; }
+ @Override
+ protected AlphabeticChooserScore score(ManagementNodeSyncRecord contender) {
+ AlphabeticChooserScore score = new AlphabeticChooserScore();
+ score.priority = contender.getPriority()!=null ? contender.getPriority() : 0;
+ score.brooklynVersion = contender.getBrooklynVersion();
+ score.versionBias = contender.getBrooklynVersion()==null ? -2 :
+ contender.getBrooklynVersion().toLowerCase().indexOf("snapshot")>=0 ? -1 :
+ 0;
+ if (preferHotStandby) {
+ // other master should be preferred before we get invoked, but including for good measure
+ score.statePriority = contender.getStatus()==ManagementNodeState.MASTER ? 3 :
+ contender.getStatus()==ManagementNodeState.HOT_STANDBY ? 2 :
+ contender.getStatus()==ManagementNodeState.STANDBY ? 1 : -1;
+ } else {
+ score.statePriority = 0;
+ }
+ score.nodeId = contender.getNodeId();
+ return score;
+ }
+ }
+
+ /**
+ * Filters the {@link ManagementPlaneSyncRecord#getManagementNodes()} to only those in an appropriate state,
+ * and with heartbeats that have not timed out.
+ */
+ protected List<ScoredRecord<?>> filterHealthy(ManagementPlaneSyncRecord memento, Duration heartbeatTimeout, long nowIsh) {
+ long oldestAcceptableTimestamp = nowIsh - heartbeatTimeout.toMilliseconds();
+ List<ScoredRecord<?>> contenders = MutableList.of();
+ for (ManagementNodeSyncRecord contender : memento.getManagementNodes().values()) {
+ boolean statusOk = (contender.getStatus() == ManagementNodeState.STANDBY || contender.getStatus() == ManagementNodeState.HOT_STANDBY || contender.getStatus() == ManagementNodeState.MASTER);
+ Long remoteTimestamp = contender.getRemoteTimestamp();
+ boolean heartbeatOk;
+ if (remoteTimestamp==null) {
+ throw new IllegalStateException("Missing remote timestamp when performing master election: "+this+" / "+contender);
+ // if the above exception happens in some contexts we could either fallback to local, or fail:
+// remoteTimestamp = contender.getLocalTimestamp();
+ // or
+// heartbeatOk=false;
+ } else {
+ heartbeatOk = remoteTimestamp >= oldestAcceptableTimestamp;
+ }
+ if (statusOk && heartbeatOk) {
+ contenders.add(newScoredRecord(contender));
+ }
+ if (LOG.isTraceEnabled()) LOG.trace("Filtering choices of new master: contender="+contender+"; statusOk="+statusOk+"; heartbeatOk="+heartbeatOk);
+ }
+ return contenders;
+ }
+
+ @VisibleForTesting
+ //Java 6 compiler workaround, using parameterized types fails
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected List<ScoredRecord<?>> sort(List<ScoredRecord<?>> input) {
+ ArrayList copy = new ArrayList<ScoredRecord<?>>(input);
+ Collections.sort(copy);
+ return copy;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected ScoredRecord<?> newScoredRecord(ManagementNodeSyncRecord contender) {
+ ScoredRecord r = new ScoredRecord();
+ r.id = contender.getNodeId();
+ r.record = contender;
+ r.score = score(contender);
+ return r;
+ }
+
+ protected abstract Comparable<?> score(ManagementNodeSyncRecord contender);
+
+}
[24/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
[BROOKLYN-162] Refactor package in ./core/management
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/6602f694
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/6602f694
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/6602f694
Branch: refs/heads/master
Commit: 6602f694a2ac625e895de264d83a0407bc512fbe
Parents: 083953f
Author: Hadrian Zbarcea <ha...@apache.org>
Authored: Fri Aug 14 23:35:04 2015 -0400
Committer: Hadrian Zbarcea <ha...@apache.org>
Committed: Fri Aug 14 23:35:04 2015 -0400
----------------------------------------------------------------------
.../src/main/java/brooklyn/BrooklynVersion.java | 2 +-
.../brooklyn/basic/AbstractBrooklynObject.java | 2 +-
.../brooklyn/basic/BasicConfigurableObject.java | 2 +-
.../brooklyn/catalog/CatalogPredicates.java | 2 +-
.../catalog/internal/BasicBrooklynCatalog.java | 2 +-
.../catalog/internal/CatalogClasspathDo.java | 2 +-
.../brooklyn/catalog/internal/CatalogDo.java | 2 +-
.../catalog/internal/CatalogInitialization.java | 4 +-
.../brooklyn/catalog/internal/CatalogUtils.java | 10 +-
.../brooklyn/config/BrooklynServerPaths.java | 2 +-
.../entity/basic/AbstractApplication.java | 2 +-
.../brooklyn/entity/basic/AbstractEffector.java | 2 +-
.../brooklyn/entity/basic/AbstractEntity.java | 8 +-
.../entity/basic/AbstractGroupImpl.java | 2 +-
.../entity/basic/BrooklynShutdownHooks.java | 2 +-
.../brooklyn/entity/basic/DynamicGroupImpl.java | 4 +-
.../java/brooklyn/entity/basic/Entities.java | 10 +-
.../brooklyn/entity/basic/EntityInternal.java | 2 +-
.../basic/EntityTransientCopyInternal.java | 2 +-
.../brooklyn/entity/basic/MethodEffector.java | 2 +-
.../entity/effector/AddChildrenEffector.java | 4 +-
.../brooklyn/entity/effector/EffectorTasks.java | 4 +-
.../entity/proxying/EntityProxyImpl.java | 6 +-
.../entity/proxying/InternalEntityFactory.java | 2 +-
.../entity/proxying/InternalFactory.java | 3 +-
.../proxying/InternalLocationFactory.java | 4 +-
.../entity/proxying/InternalPolicyFactory.java | 2 +-
.../rebind/InitialFullRebindIteration.java | 8 +-
.../brooklyn/entity/rebind/RebindIteration.java | 12 +-
.../entity/rebind/RebindManagerImpl.java | 4 +-
.../BrooklynMementoPersisterToObjectStore.java | 2 +-
.../persister/BrooklynPersistenceUtils.java | 6 +-
.../rebind/persister/XmlMementoSerializer.java | 6 +-
...platedStringAttributeSensorAndConfigKey.java | 2 +-
.../internal/storage/DataGridFactory.java | 4 +-
.../impl/inmemory/InMemoryDataGridFactory.java | 3 +-
.../management/ManagementContextInjectable.java | 33 -
.../AbstractBrooklynClassLoadingContext.java | 82 --
.../BrooklynClassLoadingContextSequential.java | 136 ---
...ssLoaderFromBrooklynClassLoadingContext.java | 66 --
.../JavaBrooklynClassLoadingContext.java | 123 --
.../OsgiBrooklynClassLoadingContext.java | 147 ---
.../BasicEntitlementClassDefinition.java | 56 -
.../entitlement/EntitlementManagerAdapter.java | 134 ---
.../entitlement/EntitlementPredicates.java | 40 -
.../management/entitlement/Entitlements.java | 418 -------
.../entitlement/NotEntitledException.java | 44 -
.../entitlement/PerUserEntitlementManager.java | 100 --
.../PerUserEntitlementManagerWithDefault.java | 31 -
.../entitlement/WebEntitlementContext.java | 57 -
.../management/ha/BasicMasterChooser.java | 204 ----
.../ha/HighAvailabilityManagerImpl.java | 1105 ------------------
.../ha/ManagementPlaneSyncRecordDeltaImpl.java | 122 --
...ntPlaneSyncRecordPersisterToObjectStore.java | 355 ------
.../brooklyn/management/ha/MasterChooser.java | 40 -
.../brooklyn/management/ha/OsgiManager.java | 312 -----
.../internal/AbstractManagementContext.java | 485 --------
.../internal/AbstractSubscriptionManager.java | 141 ---
.../management/internal/AccessManager.java | 41 -
.../internal/AsyncCollectionChangeAdapter.java | 83 --
.../internal/BasicSubscriptionContext.java | 180 ---
.../internal/BrooklynGarbageCollector.java | 626 ----------
.../internal/BrooklynObjectManagementMode.java | 31 -
.../internal/BrooklynObjectManagerInternal.java | 36 -
.../internal/CollectionChangeListener.java | 24 -
.../management/internal/EffectorUtils.java | 356 ------
.../internal/EntityChangeListener.java | 79 --
.../internal/EntityManagementSupport.java | 478 --------
.../internal/EntityManagementUtils.java | 326 ------
.../internal/EntityManagerInternal.java | 32 -
...PropertyChangeToCollectionChangeAdapter.java | 65 --
.../management/internal/LocalAccessManager.java | 111 --
.../management/internal/LocalEntityManager.java | 818 -------------
.../internal/LocalLocationManager.java | 463 --------
.../internal/LocalManagementContext.java | 421 -------
.../internal/LocalSubscriptionManager.java | 292 -----
.../management/internal/LocalUsageManager.java | 430 -------
.../internal/LocationManagerInternal.java | 28 -
.../internal/ManagementContextInternal.java | 122 --
.../internal/ManagementTransitionInfo.java | 48 -
.../internal/ManagementTransitionMode.java | 127 --
.../internal/NonDeploymentAccessManager.java | 98 --
.../internal/NonDeploymentEntityManager.java | 196 ----
.../internal/NonDeploymentLocationManager.java | 146 ---
.../NonDeploymentManagementContext.java | 639 ----------
.../internal/NonDeploymentUsageManager.java | 132 ---
.../internal/QueueingSubscriptionManager.java | 148 ---
.../management/internal/Subscription.java | 66 --
.../internal/SubscriptionTracker.java | 137 ---
.../management/internal/UsageListener.java | 104 --
.../management/internal/UsageManager.java | 166 ---
.../management/usage/ApplicationUsage.java | 126 --
.../management/usage/LocationUsage.java | 135 ---
.../policy/basic/AbstractEntityAdjunct.java | 2 +-
.../main/java/brooklyn/util/ResourceUtils.java | 4 +-
.../util/task/BasicExecutionContext.java | 2 +-
.../java/brooklyn/util/task/CompoundTask.java | 2 +-
.../util/task/DynamicSequentialTask.java | 2 +-
.../brooklyn/util/text/TemplateProcessor.java | 2 +-
.../management/ManagementContextInjectable.java | 33 +
.../AbstractBrooklynClassLoadingContext.java | 82 ++
.../BrooklynClassLoadingContextSequential.java | 136 +++
...ssLoaderFromBrooklynClassLoadingContext.java | 66 ++
.../JavaBrooklynClassLoadingContext.java | 123 ++
.../OsgiBrooklynClassLoadingContext.java | 147 +++
.../BasicEntitlementClassDefinition.java | 56 +
.../entitlement/EntitlementManagerAdapter.java | 133 +++
.../entitlement/EntitlementPredicates.java | 40 +
.../management/entitlement/Entitlements.java | 418 +++++++
.../entitlement/NotEntitledException.java | 44 +
.../entitlement/PerUserEntitlementManager.java | 100 ++
.../PerUserEntitlementManagerWithDefault.java | 31 +
.../entitlement/WebEntitlementContext.java | 57 +
.../core/management/ha/BasicMasterChooser.java | 204 ++++
.../ha/HighAvailabilityManagerImpl.java | 1105 ++++++++++++++++++
.../ha/ManagementPlaneSyncRecordDeltaImpl.java | 122 ++
...ntPlaneSyncRecordPersisterToObjectStore.java | 355 ++++++
.../core/management/ha/MasterChooser.java | 40 +
.../core/management/ha/OsgiManager.java | 312 +++++
.../internal/AbstractManagementContext.java | 485 ++++++++
.../internal/AbstractSubscriptionManager.java | 141 +++
.../core/management/internal/AccessManager.java | 41 +
.../internal/AsyncCollectionChangeAdapter.java | 83 ++
.../internal/BasicSubscriptionContext.java | 180 +++
.../internal/BrooklynGarbageCollector.java | 626 ++++++++++
.../internal/BrooklynObjectManagementMode.java | 31 +
.../internal/BrooklynObjectManagerInternal.java | 36 +
.../internal/CollectionChangeListener.java | 24 +
.../core/management/internal/EffectorUtils.java | 356 ++++++
.../internal/EntityChangeListener.java | 79 ++
.../internal/EntityManagementSupport.java | 478 ++++++++
.../internal/EntityManagementUtils.java | 326 ++++++
.../internal/EntityManagerInternal.java | 32 +
...PropertyChangeToCollectionChangeAdapter.java | 65 ++
.../management/internal/LocalAccessManager.java | 111 ++
.../management/internal/LocalEntityManager.java | 818 +++++++++++++
.../internal/LocalLocationManager.java | 463 ++++++++
.../internal/LocalManagementContext.java | 421 +++++++
.../internal/LocalSubscriptionManager.java | 292 +++++
.../management/internal/LocalUsageManager.java | 430 +++++++
.../internal/LocationManagerInternal.java | 28 +
.../internal/ManagementContextInternal.java | 122 ++
.../internal/ManagementTransitionInfo.java | 48 +
.../internal/ManagementTransitionMode.java | 127 ++
.../internal/NonDeploymentAccessManager.java | 98 ++
.../internal/NonDeploymentEntityManager.java | 196 ++++
.../internal/NonDeploymentLocationManager.java | 146 +++
.../NonDeploymentManagementContext.java | 639 ++++++++++
.../internal/NonDeploymentUsageManager.java | 132 +++
.../internal/QueueingSubscriptionManager.java | 148 +++
.../core/management/internal/Subscription.java | 66 ++
.../internal/SubscriptionTracker.java | 137 +++
.../core/management/internal/UsageListener.java | 103 ++
.../core/management/internal/UsageManager.java | 166 +++
.../core/management/usage/ApplicationUsage.java | 126 ++
.../core/management/usage/LocationUsage.java | 135 +++
.../location/basic/AbstractLocation.java | 4 +-
.../location/basic/BasicLocationRegistry.java | 2 +-
.../location/basic/ByonLocationResolver.java | 2 +-
.../test/java/brooklyn/BrooklynVersionTest.java | 5 +-
.../brooklyn/camp/lite/CampYamlLiteTest.java | 4 +-
.../catalog/internal/CatalogDtoTest.java | 2 +-
.../catalog/internal/CatalogScanTest.java | 2 +-
.../catalog/internal/CatalogVersioningTest.java | 2 +-
.../entity/BrooklynAppLiveTestSupport.java | 2 +-
.../entity/BrooklynAppUnitTestSupport.java | 2 +-
.../brooklyn/entity/EffectorMetadataTest.java | 2 +-
.../entity/EffectorSayHiGroovyTest.groovy | 2 +-
.../java/brooklyn/entity/EffectorSayHiTest.java | 2 +-
.../downloads/BasicDownloadsRegistryTest.java | 3 +-
.../DownloadProducerFromLocalRepoTest.java | 3 +-
.../DownloadProducerFromPropertiesTest.java | 3 +-
.../entity/effector/EffectorBasicTest.java | 4 +-
.../ApplicationBuilderOverridingTest.java | 2 +-
.../entity/proxying/EntityProxyTest.java | 2 +-
.../proxying/InternalEntityFactoryTest.java | 2 +-
.../rebind/ActivePartialRebindVersionTest.java | 4 +-
.../entity/rebind/RebindCatalogEntityTest.java | 2 +-
.../entity/rebind/RebindCatalogItemTest.java | 4 +-
...talogWhenCatalogPersistenceDisabledTest.java | 2 +-
.../entity/rebind/RebindEntityTest.java | 2 +-
.../entity/rebind/RebindFailuresTest.java | 2 +-
.../brooklyn/entity/rebind/RebindFeedTest.java | 2 +-
.../entity/rebind/RebindFeedWithHaTest.java | 2 +-
.../entity/rebind/RebindTestFixture.java | 4 +-
.../brooklyn/entity/rebind/RebindTestUtils.java | 6 +-
.../persister/XmlMementoSerializerTest.java | 5 +-
.../transformer/CompoundTransformerTest.java | 2 +-
.../event/feed/ConfigToAttributesTest.java | 4 +-
.../entitlement/AcmeEntitlementManager.java | 50 -
.../entitlement/AcmeEntitlementManagerTest.java | 59 -
.../AcmeEntitlementManagerTestFixture.java | 155 ---
.../entitlement/EntitlementsTest.java | 207 ----
.../entitlement/EntityEntitlementTest.java | 183 ---
...PerUserEntitlementManagerPropertiesTest.java | 52 -
.../HighAvailabilityManagerFileBasedTest.java | 47 -
...ilabilityManagerInMemoryIntegrationTest.java | 96 --
.../ha/HighAvailabilityManagerInMemoryTest.java | 144 ---
.../HighAvailabilityManagerSplitBrainTest.java | 472 --------
.../ha/HighAvailabilityManagerTestFixture.java | 284 -----
.../brooklyn/management/ha/HotStandbyTest.java | 665 -----------
.../ha/ImmutableManagementPlaneSyncRecord.java | 57 -
...agementPlaneSyncRecordPersisterInMemory.java | 99 --
.../management/ha/MasterChooserTest.java | 146 ---
.../ha/MutableManagementPlaneSyncRecord.java | 62 -
.../management/ha/TestEntityFailingRebind.java | 55 -
.../brooklyn/management/ha/WarmStandbyTest.java | 153 ---
.../management/internal/AccessManagerTest.java | 145 ---
.../internal/EntityExecutionManagerTest.java | 479 --------
.../LocalManagementContextInstancesTest.java | 86 --
.../internal/LocalManagementContextTest.java | 126 --
.../internal/LocalSubscriptionManagerTest.java | 181 ---
.../brooklyn/management/osgi/OsgiPathTest.java | 105 --
.../management/osgi/OsgiStandaloneTest.java | 259 ----
.../management/osgi/OsgiTestResources.java | 74 --
.../osgi/OsgiVersionMoreEntityTest.java | 459 --------
.../EntityCleanupLongevityTestFixture.java | 8 +-
.../brooklyn/util/task/ssh/SshTasksTest.java | 2 +-
.../util/task/system/SystemTasksTest.java | 2 +-
.../util/text/TemplateProcessorTest.java | 2 +-
.../entitlement/AcmeEntitlementManager.java | 52 +
.../entitlement/AcmeEntitlementManagerTest.java | 60 +
.../AcmeEntitlementManagerTestFixture.java | 158 +++
.../entitlement/EntitlementsTest.java | 208 ++++
.../entitlement/EntityEntitlementTest.java | 185 +++
...PerUserEntitlementManagerPropertiesTest.java | 52 +
.../HighAvailabilityManagerFileBasedTest.java | 47 +
...ilabilityManagerInMemoryIntegrationTest.java | 96 ++
.../ha/HighAvailabilityManagerInMemoryTest.java | 145 +++
.../HighAvailabilityManagerSplitBrainTest.java | 474 ++++++++
.../ha/HighAvailabilityManagerTestFixture.java | 287 +++++
.../core/management/ha/HotStandbyTest.java | 667 +++++++++++
.../ha/ImmutableManagementPlaneSyncRecord.java | 57 +
...agementPlaneSyncRecordPersisterInMemory.java | 100 ++
.../core/management/ha/MasterChooserTest.java | 146 +++
.../ha/MutableManagementPlaneSyncRecord.java | 62 +
.../management/ha/TestEntityFailingRebind.java | 55 +
.../core/management/ha/WarmStandbyTest.java | 155 +++
.../management/internal/AccessManagerTest.java | 146 +++
.../internal/EntityExecutionManagerTest.java | 478 ++++++++
.../LocalManagementContextInstancesTest.java | 87 ++
.../internal/LocalManagementContextTest.java | 127 ++
.../internal/LocalSubscriptionManagerTest.java | 181 +++
.../core/management/osgi/OsgiPathTest.java | 105 ++
.../management/osgi/OsgiStandaloneTest.java | 259 ++++
.../core/management/osgi/OsgiTestResources.java | 74 ++
.../osgi/OsgiVersionMoreEntityTest.java | 459 ++++++++
.../PortForwardManagerLocationResolverTest.java | 2 +-
...regatingMachineProvisioningLocationTest.java | 3 +-
.../basic/ByonLocationResolverTest.java | 2 +-
...ixedListMachineProvisioningLocationTest.java | 2 +-
.../basic/HostLocationResolverTest.java | 2 +-
.../basic/LocalhostLocationResolverTest.java | 2 +-
...ocalhostMachineProvisioningLocationTest.java | 2 +-
.../LocalhostProvisioningAndAccessTest.java | 2 +-
.../location/basic/LocationPredicatesTest.java | 2 +-
.../location/basic/LocationRegistryTest.java | 2 +-
.../basic/MultiLocationResolverTest.java | 2 +-
.../location/basic/MultiLocationTest.java | 2 +-
.../SingleMachineLocationResolverTest.java | 2 +-
.../SingleMachineProvisioningLocationTest.java | 3 +-
.../SshMachineLocationReuseIntegrationTest.java | 2 +-
.../entity/LocalManagementContextForTests.java | 5 +-
...nMementoPersisterJcloudsObjectStoreTest.java | 2 +-
...tyToBlobStorePersistencePerformanceTest.java | 2 +-
...ailabilityManagerJcloudsObjectStoreTest.java | 4 +-
.../JcloudsBlobStoreBasedObjectStoreTest.java | 2 +-
.../jclouds/AbstractJcloudsLiveTest.java | 4 +-
.../jclouds/BailOutJcloudsLocation.java | 2 +-
.../jclouds/BrooklynMachinePoolLiveTest.java | 3 +-
.../JcloudsByonLocationResolverAwsLiveTest.java | 4 +-
...dsByonLocationResolverSoftlayerLiveTest.java | 2 +-
.../JcloudsByonLocationResolverTest.java | 2 +-
.../jclouds/JcloudsLocationMetadataTest.java | 3 +-
.../jclouds/JcloudsLocationResolverTest.java | 2 +-
.../location/jclouds/JcloudsLocationTest.java | 2 +-
.../jclouds/RebindJcloudsLocationLiveTest.java | 2 +-
.../provider/CarrenzaLocationLiveTest.groovy | 2 +-
.../zone/AwsAvailabilityZoneExtensionTest.java | 3 +-
.../entity/brooklyn/BrooklynMetricsImpl.java | 4 +-
.../enricher/DeltaEnrichersTests.groovy | 2 +-
.../entity/AbstractGoogleComputeLiveTest.java | 2 +-
.../entity/AbstractSoftlayerLiveTest.java | 2 +-
...SoftwareProcessSshDriverIntegrationTest.java | 2 +-
.../entity/java/VanillaJavaAppRebindTest.java | 4 +-
.../pool/ServerPoolLocationResolverTest.java | 2 +-
.../entity/pool/ServerPoolRebindTest.java | 2 +-
.../entity/software/AbstractDockerLiveTest.java | 2 +-
.../usage/ApplicationUsageTrackingTest.java | 7 +-
.../usage/LocationUsageTrackingTest.java | 5 +-
.../usage/RecordingLegacyUsageListener.java | 7 +-
.../usage/RecordingUsageListener.java | 7 +-
.../management/usage/UsageListenerTest.java | 8 +-
.../basic/WinRmMachineLocationLiveTest.java | 3 +-
.../mariadb/MariaDbIntegrationTest.java | 4 +-
.../postgresql/PostgreSqlIntegrationTest.java | 3 +-
.../rubyrep/RubyRepIntegrationTest.java | 3 +-
.../storm/StormAbstractCloudLiveTest.java | 2 +-
.../nosql/couchbase/CouchbaseOfflineTest.java | 3 +-
.../entity/dns/AbstractGeoDnsServiceTest.java | 2 +-
.../brooklyn/entity/proxy/UrlMappingTest.java | 2 +-
.../nginx/NginxRebindWithHaIntegrationTest.java | 2 +-
...namicWebAppClusterRebindIntegrationTest.java | 4 +-
...namicWebAppClusterRebindIntegrationTest.java | 3 +-
.../impl/hazelcast/HazelcastDataGrid.java | 2 +-
.../hazelcast/HazelcastDataGridFactory.java | 3 +-
.../impl/hazelcast/HazelcastStorageTest.java | 4 +-
.../app/SampleLocalhostIntegrationTest.java | 2 +-
.../brooklyn/sample/app/SampleUnitTest.java | 2 +-
.../BrooklynCampPlatformLauncherAbstract.java | 2 +-
.../BrooklynAssemblyTemplateInstantiator.java | 4 +-
.../BrooklynComponentTemplateResolver.java | 6 +-
.../spi/creation/BrooklynEntityMatcher.java | 2 +-
.../brooklyn/spi/dsl/methods/DslComponent.java | 2 +-
.../camp/brooklyn/ApplicationsYamlTest.java | 2 +-
.../camp/brooklyn/AbstractYamlRebindTest.java | 2 +-
.../camp/brooklyn/AbstractYamlTest.java | 2 +-
.../BrooklynYamlTypeInstantiatorTest.java | 2 +-
.../camp/brooklyn/DslAndRebindYamlTest.java | 2 +-
.../camp/brooklyn/EntitiesYamlTest.java | 2 +-
...aWebAppWithDslYamlRebindIntegrationTest.java | 2 +-
.../brooklyn/camp/brooklyn/ObjectsYamlTest.java | 2 +-
.../camp/brooklyn/ReferencedYamlTest.java | 2 +-
.../catalog/AbstractCatalogXmlTest.java | 4 +-
.../CatalogOsgiVersionMoreEntityTest.java | 2 +-
.../brooklyn/catalog/CatalogYamlEntityTest.java | 4 +-
.../catalog/CatalogYamlLocationTest.java | 4 +-
.../brooklyn/catalog/CatalogYamlPolicyTest.java | 2 +-
.../catalog/CatalogYamlTemplateTest.java | 6 +-
.../org/apache/brooklyn/cli/CloudExplorer.java | 2 +-
.../main/java/org/apache/brooklyn/cli/Main.java | 4 +-
.../brooklyn/launcher/BrooklynLauncher.java | 10 +-
.../brooklyn/launcher/BrooklynWebServer.java | 4 +-
.../camp/BrooklynCampPlatformLauncher.java | 4 +-
.../launcher/config/BrooklynGlobalConfig.java | 4 +-
.../BrooklynLauncherHighAvailabilityTest.java | 2 +-
.../brooklyn/launcher/BrooklynLauncherTest.java | 4 +-
.../launcher/BrooklynWebServerTest.java | 4 +-
.../brooklyn/launcher/WebAppRunnerTest.java | 5 +-
.../blueprints/AbstractBlueprintTest.java | 2 +-
.../org/apache/brooklyn/qa/load/LoadTest.java | 2 +-
.../ApplicationResourceIntegrationTest.java | 4 +-
.../rest/client/BrooklynApiRestClientTest.java | 4 +-
.../BrooklynPropertiesSecurityFilter.java | 4 +-
.../resources/AbstractBrooklynRestResource.java | 2 +-
.../brooklyn/rest/resources/AccessResource.java | 4 +-
.../rest/resources/ApplicationResource.java | 12 +-
.../rest/resources/CatalogResource.java | 4 +-
.../rest/resources/EffectorResource.java | 7 +-
.../rest/resources/EntityConfigResource.java | 2 +-
.../brooklyn/rest/resources/EntityResource.java | 8 +-
.../rest/resources/PolicyConfigResource.java | 2 +-
.../brooklyn/rest/resources/SensorResource.java | 2 +-
.../brooklyn/rest/resources/ServerResource.java | 4 +-
.../brooklyn/rest/resources/UsageResource.java | 10 +-
.../rest/transform/AccessTransformer.java | 2 +-
.../rest/util/BrooklynRestResourceUtils.java | 4 +-
.../rest/util/DefaultExceptionMapper.java | 4 +-
.../util/json/BrooklynJacksonJsonProvider.java | 2 +-
.../brooklyn/rest/BrooklynRestApiLauncher.java | 4 +-
.../BrooklynRestApiLauncherTestFixture.java | 2 +-
.../apache/brooklyn/rest/HaHotCheckTest.java | 6 +-
.../rest/resources/CatalogResourceTest.java | 2 +-
.../ServerResourceIntegrationTest.java | 4 +-
.../rest/resources/ServerResourceTest.java | 2 +-
.../rest/resources/UsageResourceTest.java | 6 +-
.../rest/testing/BrooklynRestApiTest.java | 6 +-
.../util/BrooklynRestResourceUtilsTest.java | 2 +-
.../brooklyn/test/BrooklynLeakListener.java | 2 +-
369 files changed, 16794 insertions(+), 16765 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/BrooklynVersion.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/BrooklynVersion.java b/core/src/main/java/brooklyn/BrooklynVersion.java
index f147303..dbc7869 100644
--- a/core/src/main/java/brooklyn/BrooklynVersion.java
+++ b/core/src/main/java/brooklyn/BrooklynVersion.java
@@ -44,8 +44,8 @@ import com.google.common.collect.Maps;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.classloading.OsgiBrooklynClassLoadingContext;
-import brooklyn.management.classloading.OsgiBrooklynClassLoadingContext;
import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.osgi.Osgis;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
index be49f7b..c990ed9 100644
--- a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
+++ b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
@@ -24,13 +24,13 @@ import java.util.Set;
import org.apache.brooklyn.api.basic.internal.ApiObjectsFactory;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.proxying.InternalFactory;
import brooklyn.entity.rebind.RebindManagerImpl;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.Identifiers;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java b/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java
index 06cdd40..d02f1bd 100644
--- a/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java
+++ b/core/src/main/java/brooklyn/basic/BasicConfigurableObject.java
@@ -22,12 +22,12 @@ import org.apache.brooklyn.api.entity.trait.Configurable;
import org.apache.brooklyn.api.entity.trait.Identifiable;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.config.ConfigMap;
-import brooklyn.management.ManagementContextInjectable;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.text.Identifiers;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
index a873726..07dcbe0 100644
--- a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
+++ b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
@@ -30,9 +30,9 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.management.entitlement.Entitlements;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index f129f4c..88474e7 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -52,6 +52,7 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.catalog.CatalogPredicates;
import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
@@ -59,7 +60,6 @@ import brooklyn.config.BrooklynServerConfig;
import org.apache.brooklyn.location.basic.BasicLocationRegistry;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
index 3acd165..b81b439 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
@@ -38,9 +38,9 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.javalang.AggregateClassLoader;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index b6c62a7..25fabff 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -25,11 +25,11 @@ import java.util.List;
import java.util.Map;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableList;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.javalang.AggregateClassLoader;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java b/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
index 42d8688..07eac9b 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
@@ -27,10 +27,10 @@ import org.slf4j.LoggerFactory;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.config.BrooklynServerConfig;
-import brooklyn.management.ManagementContextInjectable;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
index e8cd0d3..302e17c 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
@@ -34,16 +34,16 @@ import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.classloading.BrooklynClassLoadingContextSequential;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.classloading.OsgiBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.ha.OsgiManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
import brooklyn.config.BrooklynLogging;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
-import brooklyn.management.classloading.BrooklynClassLoadingContextSequential;
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
-import brooklyn.management.classloading.OsgiBrooklynClassLoadingContext;
-import brooklyn.management.ha.OsgiManager;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.guava.Maybe;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/config/BrooklynServerPaths.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/config/BrooklynServerPaths.java b/core/src/main/java/brooklyn/config/BrooklynServerPaths.java
index f082496..a865d5b 100644
--- a/core/src/main/java/brooklyn/config/BrooklynServerPaths.java
+++ b/core/src/main/java/brooklyn/config/BrooklynServerPaths.java
@@ -24,11 +24,11 @@ import java.util.Map;
import javax.annotation.Nullable;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java b/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
index 65ef309..79c2ef1 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractApplication.java
@@ -24,13 +24,13 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ServiceStateLogic.ServiceProblemsLogic;
import brooklyn.entity.trait.StartableMethods;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeInterruptedException;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java b/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java
index 26ced4a..bf29732 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEffector.java
@@ -26,13 +26,13 @@ import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.effector.EffectorBase;
import brooklyn.entity.effector.EffectorTasks.EffectorTaskFactory;
import brooklyn.entity.effector.EffectorWithBody;
-import brooklyn.management.internal.EffectorUtils;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.task.DynamicSequentialTask;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index 89a691e..dc005d8 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -53,6 +53,10 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.EntityAdjunct;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.management.internal.EffectorUtils;
+import org.apache.brooklyn.core.management.internal.EntityManagementSupport;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.SubscriptionTracker;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -80,10 +84,6 @@ import brooklyn.internal.storage.impl.BasicReference;
import org.apache.brooklyn.location.basic.Locations;
-import brooklyn.management.internal.EffectorUtils;
-import brooklyn.management.internal.EntityManagementSupport;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.SubscriptionTracker;
import brooklyn.policy.basic.AbstractEntityAdjunct;
import brooklyn.policy.basic.AbstractEntityAdjunct.AdjunctTagSupport;
import brooklyn.policy.basic.AbstractPolicy;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java b/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java
index 07287dc..79abdb0 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java
@@ -28,11 +28,11 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.internal.BrooklynFeatureEnablement;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.SetFromLiveMap;
import com.google.common.base.Optional;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java b/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
index b614e0f..6032fff 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java
@@ -26,11 +26,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.trait.Startable;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java b/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java
index 2fe8d46..7ffe8a0 100644
--- a/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java
+++ b/core/src/main/java/brooklyn/entity/basic/DynamicGroupImpl.java
@@ -28,13 +28,13 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.CollectionChangeListener;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.BrooklynLogging;
import brooklyn.config.BrooklynLogging.LoggingLevel;
-import brooklyn.management.internal.CollectionChangeListener;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.GroovyJavaMethods;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.task.Tasks;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/Entities.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/Entities.java b/core/src/main/java/brooklyn/entity/basic/Entities.java
index 1f09903..c768726 100644
--- a/core/src/main/java/brooklyn/entity/basic/Entities.java
+++ b/core/src/main/java/brooklyn/entity/basic/Entities.java
@@ -59,6 +59,11 @@ import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.TaskFactory;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.internal.EffectorUtils;
+import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.NonDeploymentManagementContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -75,11 +80,6 @@ import brooklyn.event.basic.DependentConfiguration;
import org.apache.brooklyn.location.basic.LocationInternal;
import org.apache.brooklyn.location.basic.Locations;
-import brooklyn.management.internal.EffectorUtils;
-import brooklyn.management.internal.EntityManagerInternal;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.NonDeploymentManagementContext;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.config.ConfigBag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/EntityInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityInternal.java b/core/src/main/java/brooklyn/entity/basic/EntityInternal.java
index a735750..085079f 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityInternal.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityInternal.java
@@ -32,10 +32,10 @@ import org.apache.brooklyn.api.management.ExecutionContext;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.SubscriptionContext;
import org.apache.brooklyn.api.mementos.EntityMemento;
+import org.apache.brooklyn.core.management.internal.EntityManagementSupport;
import brooklyn.basic.BrooklynObjectInternal;
import brooklyn.config.ConfigKey;
-import brooklyn.management.internal.EntityManagementSupport;
import brooklyn.util.config.ConfigBag;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java b/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
index a25d17e..63b49b5 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
@@ -37,12 +37,12 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.mementos.EntityMemento;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.internal.EntityManagementSupport;
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.entity.basic.EntityInternal.FeedSupport;
import brooklyn.entity.proxying.EntityProxyImpl;
-import brooklyn.management.internal.EntityManagementSupport;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.guava.Maybe;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/basic/MethodEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/MethodEffector.java b/core/src/main/java/brooklyn/entity/basic/MethodEffector.java
index 4d07344..121f70f 100644
--- a/core/src/main/java/brooklyn/entity/basic/MethodEffector.java
+++ b/core/src/main/java/brooklyn/entity/basic/MethodEffector.java
@@ -27,12 +27,12 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ParameterType;
+import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.codehaus.groovy.runtime.MethodClosure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.annotation.EffectorParam;
-import brooklyn.management.internal.EffectorUtils;
import brooklyn.util.GroovyJavaMethods;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.flags.TypeCoercions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java b/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
index b7ce04f..eef3cf9 100644
--- a/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
+++ b/core/src/main/java/brooklyn/entity/effector/AddChildrenEffector.java
@@ -23,14 +23,14 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.effector.Effectors.EffectorBuilder;
-import brooklyn.management.internal.EntityManagementUtils;
-import brooklyn.management.internal.EntityManagementUtils.CreationResult;
import brooklyn.util.config.ConfigBag;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java b/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java
index e7657ea..6094686 100644
--- a/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java
+++ b/core/src/main/java/brooklyn/entity/effector/EffectorTasks.java
@@ -27,16 +27,18 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.ConfigKeys;
+
import org.apache.brooklyn.location.basic.Machines;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.apache.brooklyn.location.basic.WinRmMachineLocation;
-import brooklyn.management.internal.EffectorUtils;
+
import brooklyn.util.config.ConfigBag;
import brooklyn.util.javalang.Reflections;
import brooklyn.util.task.DynamicSequentialTask;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java b/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
index 1eccb92..647ad76 100644
--- a/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
+++ b/core/src/main/java/brooklyn/entity/proxying/EntityProxyImpl.java
@@ -33,6 +33,9 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.management.internal.EffectorUtils;
+import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
+import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,9 +45,6 @@ import brooklyn.entity.basic.EntityTransientCopyInternal;
import brooklyn.entity.basic.EntityTransientCopyInternal.SpecialEntityTransientCopyInternal;
import brooklyn.entity.effector.EffectorWithBody;
import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
-import brooklyn.management.internal.EffectorUtils;
-import brooklyn.management.internal.EntityManagerInternal;
-import brooklyn.management.internal.ManagementTransitionMode;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.task.DynamicTasks;
import brooklyn.util.task.TaskTags;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
index 42c532f..c2a4bfd 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
@@ -36,6 +36,7 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,7 +46,6 @@ import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/proxying/InternalFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalFactory.java
index 3b77526..8517664 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalFactory.java
@@ -23,7 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
-import brooklyn.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.javalang.Reflections;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
index 58c7dfc..10338b8 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
@@ -25,14 +25,14 @@ import java.util.Map.Entry;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalLocationManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.config.ConfigKey;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.basic.LocationInternal;
-import brooklyn.management.internal.LocalLocationManager;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.flags.FlagUtils;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
index 52fd7ba..aeb371c 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
@@ -26,11 +26,11 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.config.ConfigBag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
index f9e42b3..8c5eed2 100644
--- a/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/InitialFullRebindIteration.java
@@ -26,16 +26,16 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.rebind.RebindExceptionHandler;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
+import org.apache.brooklyn.core.management.internal.BrooklynObjectManagementMode;
+import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
+import org.apache.brooklyn.core.management.internal.LocationManagerInternal;
+import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.BrooklynLogging;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
-import brooklyn.management.internal.BrooklynObjectManagementMode;
-import brooklyn.management.internal.EntityManagerInternal;
-import brooklyn.management.internal.LocationManagerInternal;
-import brooklyn.management.internal.ManagementTransitionMode;
import brooklyn.util.text.Strings;
import com.google.common.base.Preconditions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 9051242..30803e2 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -64,6 +64,12 @@ import org.apache.brooklyn.api.mementos.TreeNode;
import org.apache.brooklyn.api.mementos.BrooklynMementoManifest.EntityMementoManifest;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.internal.BrooklynObjectManagementMode;
+import org.apache.brooklyn.core.management.internal.BrooklynObjectManagerInternal;
+import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
+import org.apache.brooklyn.core.management.internal.LocationManagerInternal;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
import brooklyn.catalog.internal.CatalogInitialization;
import brooklyn.catalog.internal.CatalogUtils;
@@ -85,12 +91,6 @@ import brooklyn.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.basic.LocationInternal;
-import brooklyn.management.internal.BrooklynObjectManagementMode;
-import brooklyn.management.internal.BrooklynObjectManagerInternal;
-import brooklyn.management.internal.EntityManagerInternal;
-import brooklyn.management.internal.LocationManagerInternal;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.ManagementTransitionMode;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 25a396b..8221472 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -43,6 +43,8 @@ import org.apache.brooklyn.api.management.ha.MementoCopyMode;
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
import org.apache.brooklyn.api.mementos.TreeNode;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,8 +59,6 @@ import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils.CreateBackupMod
import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
import brooklyn.entity.rebind.transformer.CompoundTransformer;
import brooklyn.internal.BrooklynFeatureEnablement;
-import brooklyn.management.ha.HighAvailabilityManagerImpl;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.QuorumCheck;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index 9495988..be51b44 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -48,6 +48,7 @@ import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
import org.apache.brooklyn.api.mementos.CatalogItemMemento;
import org.apache.brooklyn.api.mementos.Memento;
+import org.apache.brooklyn.core.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.ConfigKey;
@@ -59,7 +60,6 @@ import brooklyn.entity.rebind.dto.BrooklynMementoImpl;
import brooklyn.entity.rebind.dto.BrooklynMementoManifestImpl;
import brooklyn.entity.rebind.persister.PersistenceObjectStore.StoreObjectAccessor;
import brooklyn.entity.rebind.persister.PersistenceObjectStore.StoreObjectAccessorWithLock;
-import brooklyn.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.CompoundRuntimeException;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
index a171d18..68074e9 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
@@ -42,6 +42,9 @@ import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
import org.apache.brooklyn.api.mementos.Memento;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import org.apache.brooklyn.core.management.internal.LocalLocationManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.BrooklynServerPaths;
@@ -53,9 +56,6 @@ import brooklyn.entity.rebind.transformer.CompoundTransformerLoader;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
-import brooklyn.management.internal.LocalLocationManager;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
index 82c9c7a..fe5a677 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
@@ -42,6 +42,9 @@ import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingConte
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister.LookupContext;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.classloading.BrooklynClassLoadingContextSequential;
+import org.apache.brooklyn.core.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import brooklyn.catalog.internal.CatalogBundleDto;
import brooklyn.catalog.internal.CatalogUtils;
@@ -58,9 +61,6 @@ import brooklyn.entity.rebind.dto.BasicPolicyMemento;
import brooklyn.entity.rebind.dto.MutableBrooklynMemento;
import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.management.classloading.BrooklynClassLoadingContextSequential;
-import brooklyn.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.text.Strings;
import brooklyn.util.xstream.XmlSerializer;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java b/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java
index d5e46cf..0a57b62 100644
--- a/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java
+++ b/core/src/main/java/brooklyn/event/basic/TemplatedStringAttributeSensorAndConfigKey.java
@@ -20,12 +20,12 @@ package brooklyn.event.basic;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.text.TemplateProcessor;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/internal/storage/DataGridFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/internal/storage/DataGridFactory.java b/core/src/main/java/brooklyn/internal/storage/DataGridFactory.java
index 8513ebb..d5264c1 100644
--- a/core/src/main/java/brooklyn/internal/storage/DataGridFactory.java
+++ b/core/src/main/java/brooklyn/internal/storage/DataGridFactory.java
@@ -18,13 +18,13 @@
*/
package brooklyn.internal.storage;
-import brooklyn.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
/**
* A factory for creating a {@link DataGrid}.
*
* Implementations of this interface should have a public no arg constructor; this constructor will be
- * called through reflection in the {@link brooklyn.management.internal.LocalManagementContext}.
+ * called through reflection in the {@link org.apache.brooklyn.core.management.internal.LocalManagementContext}.
*/
public interface DataGridFactory {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/internal/storage/impl/inmemory/InMemoryDataGridFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/internal/storage/impl/inmemory/InMemoryDataGridFactory.java b/core/src/main/java/brooklyn/internal/storage/impl/inmemory/InMemoryDataGridFactory.java
index 9be9134..4f0fbac 100644
--- a/core/src/main/java/brooklyn/internal/storage/impl/inmemory/InMemoryDataGridFactory.java
+++ b/core/src/main/java/brooklyn/internal/storage/impl/inmemory/InMemoryDataGridFactory.java
@@ -18,9 +18,10 @@
*/
package brooklyn.internal.storage.impl.inmemory;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
import brooklyn.internal.storage.DataGrid;
import brooklyn.internal.storage.DataGridFactory;
-import brooklyn.management.internal.ManagementContextInternal;
public class InMemoryDataGridFactory implements DataGridFactory {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/ManagementContextInjectable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ManagementContextInjectable.java b/core/src/main/java/brooklyn/management/ManagementContextInjectable.java
deleted file mode 100644
index 772dee3..0000000
--- a/core/src/main/java/brooklyn/management/ManagementContextInjectable.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-
-/**
- * Provides a way for the {@link ManagementContext} to be injected directly.
- */
-public interface ManagementContextInjectable {
-
- /**
- * Sets the {@link ManagementContext} reference.
- */
- public void injectManagementContext(ManagementContext managementContext);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/classloading/AbstractBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/AbstractBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/AbstractBrooklynClassLoadingContext.java
deleted file mode 100644
index fc975eb..0000000
--- a/core/src/main/java/brooklyn/management/classloading/AbstractBrooklynClassLoadingContext.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package brooklyn.management.classloading;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-
-import brooklyn.util.guava.Maybe;
-
-import com.google.common.base.Objects;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-public abstract class AbstractBrooklynClassLoadingContext implements BrooklynClassLoadingContext {
-
- protected final ManagementContext mgmt;
-
- public AbstractBrooklynClassLoadingContext(ManagementContext mgmt) {
- this.mgmt = mgmt;
- }
-
- @Override
- public ManagementContext getManagementContext() {
- return mgmt;
- }
-
- @Override
- public Class<?> loadClass(String className) {
- return tryLoadClass(className).get();
- }
-
- @Override
- // this is the only one left for subclasses
- public abstract Maybe<Class<?>> tryLoadClass(String className);
-
- @Override
- public <T> Class<? extends T> loadClass(String className, @Nullable Class<T> supertype) {
- return tryLoadClass(className, supertype).get();
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public <T> Maybe<Class<? extends T>> tryLoadClass(String className, @Nullable Class<T> supertype) {
- Maybe<Class<?>> result = tryLoadClass(className);
- if (result.isAbsent()) return (Maybe)result;
- Class<?> clazz = result.get();
- if (supertype==null || supertype.isAssignableFrom(clazz)) return (Maybe)result;
- throw new ClassCastException(className+" is not an instance of "+supertype);
- }
-
- @Override
- public abstract String toString();
-
- @Override
- public int hashCode() {
- return Objects.hashCode(mgmt);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof BrooklynClassLoadingContext)) return false;
- if (!Objects.equal(mgmt, ((BrooklynClassLoadingContext)obj).getManagementContext())) return false;
- return true;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java b/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
deleted file mode 100644
index a1270bc..0000000
--- a/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.classloading;
-
-import java.net.URL;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
-public final class BrooklynClassLoadingContextSequential extends AbstractBrooklynClassLoadingContext {
-
- private static final Logger log = LoggerFactory.getLogger(BrooklynClassLoadingContextSequential.class);
-
- private final List<BrooklynClassLoadingContext> primaries = MutableList.<BrooklynClassLoadingContext>of();
- // secondaries used to put java classloader last
- private final Set<BrooklynClassLoadingContext> secondaries = MutableSet.<BrooklynClassLoadingContext>of();
-
- public BrooklynClassLoadingContextSequential(ManagementContext mgmt, BrooklynClassLoadingContext ...targets) {
- super(mgmt);
- for (BrooklynClassLoadingContext target: targets)
- add(target);
- }
-
- public void add(BrooklynClassLoadingContext target) {
- if (target instanceof BrooklynClassLoadingContextSequential) {
- for (BrooklynClassLoadingContext targetN: ((BrooklynClassLoadingContextSequential)target).primaries )
- add(targetN);
- for (BrooklynClassLoadingContext targetN: ((BrooklynClassLoadingContextSequential)target).secondaries )
- addSecondary(targetN);
- } else {
- this.primaries.add( target );
- }
- }
-
- public void addSecondary(BrooklynClassLoadingContext target) {
- if (!(target instanceof JavaBrooklynClassLoadingContext)) {
- // support for legacy catalog classloader only
- log.warn("Only Java classloaders should be secondary");
- }
- this.secondaries.add( target );
- }
-
- public Maybe<Class<?>> tryLoadClass(String className) {
- List<Throwable> errors = MutableList.of();
- for (BrooklynClassLoadingContext target: primaries) {
- Maybe<Class<?>> clazz = target.tryLoadClass(className);
- if (clazz.isPresent())
- return clazz;
- errors.add( ((Maybe.Absent<?>)clazz).getException() );
- }
- boolean noPrimaryErrors = errors.isEmpty();
- for (BrooklynClassLoadingContext target: secondaries) {
- Maybe<Class<?>> clazz = target.tryLoadClass(className);
- if (clazz.isPresent())
- return clazz;
- if (noPrimaryErrors)
- errors.add( ((Maybe.Absent<?>)clazz).getException() );
- }
-
- return Maybe.absent(Exceptions.create("Unable to load "+className+" from "+primaries, errors));
- }
-
- @Override
- public URL getResource(String resourceInThatDir) {
- for (BrooklynClassLoadingContext target: primaries) {
- URL result = target.getResource(resourceInThatDir);
- if (result!=null) return result;
- }
- for (BrooklynClassLoadingContext target: secondaries) {
- URL result = target.getResource(resourceInThatDir);
- if (result!=null) return result;
- }
- return null;
- }
-
- @Override
- public Iterable<URL> getResources(String name) {
- List<Iterable<URL>> resources = Lists.newArrayList();
- for (BrooklynClassLoadingContext target : primaries) {
- resources.add(target.getResources(name));
- }
- for (BrooklynClassLoadingContext target : secondaries) {
- resources.add(target.getResources(name));
- }
- return Iterables.concat(resources);
- }
-
- @Override
- public String toString() {
- return "classload:"+primaries+";"+secondaries;
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(super.hashCode(), primaries, secondaries);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!super.equals(obj)) return false;
- if (!(obj instanceof BrooklynClassLoadingContextSequential)) return false;
- if (!Objects.equal(primaries, ((BrooklynClassLoadingContextSequential)obj).primaries)) return false;
- if (!Objects.equal(secondaries, ((BrooklynClassLoadingContextSequential)obj).secondaries)) return false;
- return true;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/ClassLoaderFromBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
deleted file mode 100644
index 104b3a1..0000000
--- a/core/src/main/java/brooklyn/management/classloading/ClassLoaderFromBrooklynClassLoadingContext.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.classloading;
-
-import java.net.URL;
-
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-
-public class ClassLoaderFromBrooklynClassLoadingContext extends ClassLoader {
-
- /** Constructs a {@link ClassLoader} which delegates to the given {@link BrooklynClassLoadingContext} */
- public static ClassLoader of(BrooklynClassLoadingContext clc) {
- return new ClassLoaderFromBrooklynClassLoadingContext(clc);
- }
-
- protected final BrooklynClassLoadingContext clc;
-
- protected ClassLoaderFromBrooklynClassLoadingContext(BrooklynClassLoadingContext clc) {
- this.clc = clc;
- }
-
- @Override
- public Class<?> findClass(String className) throws ClassNotFoundException {
- Class<?> result = clc.loadClass(className);
- if (result!=null) return result;
-
- // last resort. see comment in XStream CompositeClassLoader
- ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
- if (contextClassLoader != null) {
- result = contextClassLoader.loadClass(className);
- if (result!=null) return result;
- }
- return null;
- }
-
- @Override
- protected URL findResource(String name) {
- URL result = clc.getResource(name);
- if (result!=null) return result;
-
- // last resort. see comment in XStream CompositeClassLoader
- ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
- if (contextClassLoader != null) {
- result = contextClassLoader.getResource(name);
- if (result!=null) return result;
- }
- return null;
- }
-
-}
[12/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java
new file mode 100644
index 0000000..53d31eb
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalEntityManager.java
@@ -0,0 +1,818 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import groovy.util.ObservableList;
+
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.entity.proxying.EntityTypeRegistry;
+import org.apache.brooklyn.api.management.AccessController;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.policy.Enricher;
+import org.apache.brooklyn.api.policy.EnricherSpec;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.BrooklynLogging;
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.EntityPredicates;
+import brooklyn.entity.proxying.BasicEntityTypeRegistry;
+import brooklyn.entity.proxying.EntityProxy;
+import brooklyn.entity.proxying.EntityProxyImpl;
+import brooklyn.entity.proxying.InternalEntityFactory;
+import brooklyn.entity.proxying.InternalPolicyFactory;
+import brooklyn.entity.trait.Startable;
+import brooklyn.internal.storage.BrooklynStorage;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.collections.SetFromLiveMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.time.CountdownTimer;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class LocalEntityManager implements EntityManagerInternal {
+
+ private static final Logger log = LoggerFactory.getLogger(LocalEntityManager.class);
+
+ private final LocalManagementContext managementContext;
+ private final BasicEntityTypeRegistry entityTypeRegistry;
+ private final InternalEntityFactory entityFactory;
+ private final InternalPolicyFactory policyFactory;
+
+ /** Entities that have been created, but have not yet begun to be managed */
+ protected final Map<String,Entity> preRegisteredEntitiesById = Collections.synchronizedMap(new WeakHashMap<String, Entity>());
+
+ /** Entities that are in the process of being managed, but where management is not yet complete */
+ protected final Map<String,Entity> preManagedEntitiesById = Collections.synchronizedMap(new WeakHashMap<String, Entity>());
+
+ /** Proxies of the managed entities */
+ protected final ConcurrentMap<String,Entity> entityProxiesById = Maps.newConcurrentMap();
+
+ /** Real managed entities */
+ protected final Map<String,Entity> entitiesById = Maps.newLinkedHashMap();
+
+ /** Management mode for each entity */
+ protected final Map<String,ManagementTransitionMode> entityModesById = Collections.synchronizedMap(Maps.<String,ManagementTransitionMode>newLinkedHashMap());
+
+ /** Proxies of the managed entities */
+ protected final ObservableList entities = new ObservableList();
+
+ /** Proxies of the managed entities that are applications */
+ protected final Set<Application> applications = Sets.newConcurrentHashSet();
+
+ private final BrooklynStorage storage;
+ private final Map<String,String> entityTypes;
+ private final Set<String> applicationIds;
+
+ public LocalEntityManager(LocalManagementContext managementContext) {
+ this.managementContext = checkNotNull(managementContext, "managementContext");
+ this.storage = managementContext.getStorage();
+ this.entityTypeRegistry = new BasicEntityTypeRegistry();
+ this.policyFactory = new InternalPolicyFactory(managementContext);
+ this.entityFactory = new InternalEntityFactory(managementContext, entityTypeRegistry, policyFactory);
+
+ entityTypes = storage.getMap("entities");
+ applicationIds = SetFromLiveMap.create(storage.<String,Boolean>getMap("applications"));
+ }
+
+ public InternalEntityFactory getEntityFactory() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+ return entityFactory;
+ }
+
+ public InternalPolicyFactory getPolicyFactory() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+ return policyFactory;
+ }
+
+ @Override
+ public EntityTypeRegistry getEntityTypeRegistry() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+ return entityTypeRegistry;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Entity> T createEntity(EntitySpec<T> spec) {
+ try {
+ T entity = entityFactory.createEntity(spec);
+ Entity proxy = ((AbstractEntity)entity).getProxy();
+ return (T) checkNotNull(proxy, "proxy for entity %s, spec %s", entity, spec);
+ } catch (Throwable e) {
+ log.warn("Failed to create entity using spec "+spec+" (rethrowing)", e);
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public <T extends Entity> T createEntity(Map<?,?> config, Class<T> type) {
+ return createEntity(EntitySpec.create(config, type));
+ }
+
+ @Override
+ public <T extends Policy> T createPolicy(PolicySpec<T> spec) {
+ try {
+ return policyFactory.createPolicy(spec);
+ } catch (Throwable e) {
+ log.warn("Failed to create policy using spec "+spec+" (rethrowing)", e);
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public <T extends Enricher> T createEnricher(EnricherSpec<T> spec) {
+ try {
+ return policyFactory.createEnricher(spec);
+ } catch (Throwable e) {
+ log.warn("Failed to create enricher using spec "+spec+" (rethrowing)", e);
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public Collection<Entity> getEntities() {
+ return ImmutableList.copyOf(entityProxiesById.values());
+ }
+
+ @Override
+ public Collection<String> getEntityIds() {
+ return ImmutableList.copyOf(entityProxiesById.keySet());
+ }
+
+ @Override
+ public Collection<Entity> getEntitiesInApplication(Application application) {
+ Predicate<Entity> predicate = EntityPredicates.applicationIdEqualTo(application.getId());
+ return ImmutableList.copyOf(Iterables.filter(entityProxiesById.values(), predicate));
+ }
+
+ @Override
+ public Collection<Entity> findEntities(Predicate<? super Entity> filter) {
+ return ImmutableList.copyOf(Iterables.filter(entityProxiesById.values(), filter));
+ }
+
+ @Override
+ public Collection<Entity> findEntitiesInApplication(Application application, Predicate<? super Entity> filter) {
+ Predicate<Entity> predicate = Predicates.and(EntityPredicates.applicationIdEqualTo(application.getId()), filter);
+ return ImmutableList.copyOf(Iterables.filter(entityProxiesById.values(), predicate));
+ }
+
+ @Override
+ public Iterable<Entity> getAllEntitiesInApplication(Application application) {
+ Predicate<Entity> predicate = EntityPredicates.applicationIdEqualTo(application.getId());
+ Iterable<Entity> allentities = Iterables.concat(preRegisteredEntitiesById.values(), preManagedEntitiesById.values(), entityProxiesById.values());
+ Iterable<Entity> result = Iterables.filter(allentities, predicate);
+ return ImmutableSet.copyOf(Iterables.transform(result, new Function<Entity, Entity>() {
+ @Override public Entity apply(Entity input) {
+ return Entities.proxy(input);
+ }}));
+ }
+
+ @Override
+ public Entity getEntity(String id) {
+ return entityProxiesById.get(id);
+ }
+
+ Collection<Application> getApplications() {
+ return ImmutableList.copyOf(applications);
+ }
+
+ @Override
+ public boolean isManaged(Entity e) {
+ return (isRunning() && getEntity(e.getId()) != null);
+ }
+
+ boolean isPreRegistered(Entity e) {
+ return preRegisteredEntitiesById.containsKey(e.getId());
+ }
+
+ void prePreManage(Entity entity) {
+ if (isPreRegistered(entity)) {
+ log.warn(""+this+" redundant call to pre-pre-manage entity "+entity+"; skipping",
+ new Exception("source of duplicate pre-pre-manage of "+entity));
+ return;
+ }
+ preRegisteredEntitiesById.put(entity.getId(), entity);
+ }
+
+ @Override
+ public ManagementTransitionMode getLastManagementTransitionMode(String itemId) {
+ return entityModesById.get(itemId);
+ }
+
+ @Override
+ public void setManagementTransitionMode(Entity item, ManagementTransitionMode mode) {
+ entityModesById.put(item.getId(), mode);
+ }
+
+ // TODO synchronization issues here. We guard with isManaged(), but if another thread executing
+ // concurrently then the managed'ness could be set after our check but before we do
+ // onManagementStarting etc. However, we can't just synchronize because we're calling alien code
+ // (the user might override entity.onManagementStarting etc).
+ //
+ // TODO We need to do some check about isPreManaged - i.e. is there another thread (or is this a
+ // re-entrant call) where the entity is not yet full managed (i.e. isManaged==false) but we're in
+ // the middle of managing it.
+ //
+ // TODO Also see LocalLocationManager.manage(Entity), if fixing things here
+ @Override
+ public void manage(Entity e) {
+ if (isManaged(e)) {
+ log.warn(""+this+" redundant call to start management of entity (and descendants of) "+e+"; skipping",
+ new Exception("source of duplicate management of "+e));
+ return;
+ }
+ manageRecursive(e, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.NONEXISTENT, BrooklynObjectManagementMode.MANAGED_PRIMARY));
+ }
+
+ @Override
+ public void manageRebindedRoot(Entity item) {
+ ManagementTransitionMode mode = getLastManagementTransitionMode(item.getId());
+ Preconditions.checkNotNull(mode, "Mode not set for rebinding %s", item);
+ manageRecursive(item, mode);
+ }
+
+ protected void checkManagementAllowed(Entity item) {
+ AccessController.Response access = managementContext.getAccessController().canManageEntity(item);
+ if (!access.isAllowed()) {
+ throw new IllegalStateException("Access controller forbids management of "+item+": "+access.getMsg());
+ }
+ }
+
+ /* TODO we sloppily use "recursive" to ensure ordering of parent-first in many places
+ * (which may not be necessary but seems like a good idea),
+ * and also to collect many entities when doing a big rebind,
+ * ensuring all have #manageNonRecursive called before calling #onManagementStarted.
+ *
+ * it would be better to have a manageAll(Map<Entity,ManagementTransitionMode> items)
+ * method which did that in two phases, allowing us to selectively rebind,
+ * esp when we come to want supporting different modes and different brooklyn nodes.
+ *
+ * the impl of manageAll could sort them with parents before children,
+ * (and manageRecursive could simply populate a map and delegate to manageAll).
+ *
+ * manageRebindRoot would then go, and the (few) callers would construct the map.
+ *
+ * similarly we might want an unmanageAll(),
+ * although possibly all unmanagement should be recursive, if we assume an entity's ancestors are always at least proxied
+ * (and the non-recursive RO path here could maybe be dropped)
+ */
+
+ /** Applies management lifecycle callbacks (onManagementStarting, for all beforehand, then onManagementStopped, for all after) */
+ protected void manageRecursive(Entity e, final ManagementTransitionMode initialMode) {
+ checkManagementAllowed(e);
+
+ final List<EntityInternal> allEntities = Lists.newArrayList();
+ Predicate<EntityInternal> manageEntity = new Predicate<EntityInternal>() { public boolean apply(EntityInternal it) {
+ ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
+ if (mode==null) {
+ setManagementTransitionMode(it, mode = initialMode);
+ }
+
+ Boolean isReadOnlyFromEntity = it.getManagementSupport().isReadOnlyRaw();
+ if (isReadOnlyFromEntity==null) {
+ if (mode.isReadOnly()) {
+ // should have been marked by rebinder
+ log.warn("Read-only entity "+it+" not marked as such on call to manage; marking and continuing");
+ }
+ it.getManagementSupport().setReadOnly(mode.isReadOnly());
+ } else {
+ if (!isReadOnlyFromEntity.equals(mode.isReadOnly())) {
+ log.warn("Read-only status at entity "+it+" ("+isReadOnlyFromEntity+") not consistent with management mode "+mode);
+ }
+ }
+
+ if (it.getManagementSupport().isDeployed()) {
+ if (mode.wasNotLoaded()) {
+ // silently bail out
+ return false;
+ } else {
+ if (mode.wasPrimary() && mode.isPrimary()) {
+ // active partial rebind; continue
+ } else if (mode.wasReadOnly() && mode.isReadOnly()) {
+ // reload in RO mode
+ } else {
+ // on initial non-RO rebind, should not have any deployed instances
+ log.warn("Already deployed "+it+" when managing "+mode+"/"+initialMode+"; ignoring this and all descendants");
+ return false;
+ }
+ }
+ }
+
+ // check RO status is consistent
+ boolean isNowReadOnly = Boolean.TRUE.equals( ((EntityInternal)it).getManagementSupport().isReadOnly() );
+ if (mode.isReadOnly()!=isNowReadOnly) {
+ throw new IllegalStateException("Read-only status mismatch for "+it+": "+mode+" / RO="+isNowReadOnly);
+ }
+
+ allEntities.add(it);
+ preManageNonRecursive(it, mode);
+ it.getManagementSupport().onManagementStarting( new ManagementTransitionInfo(managementContext, mode) );
+ return manageNonRecursive(it, mode);
+ } };
+ boolean isRecursive = true;
+ if (initialMode.wasPrimary() && initialMode.isPrimary()) {
+ // already managed, so this shouldn't be recursive
+ // (in ActivePartialRebind we cheat, calling in to this method then skipping recursion).
+ // it also falls through to here when doing a redundant promotion,
+ // in that case we *should* be recursive; determine by checking whether a child exists and is preregistered.
+ // the TODO above removing manageRebindRoot in favour of explicit mgmt list would clean this up a lot!
+ Entity aChild = Iterables.getFirst(e.getChildren(), null);
+ if (aChild!=null && isPreRegistered(aChild)) {
+ log.debug("Managing "+e+" in mode "+initialMode+", doing this recursively because a child is preregistered");
+ } else {
+ log.debug("Managing "+e+" but skipping recursion, as mode is "+initialMode);
+ isRecursive = false;
+ }
+ }
+ if (!isRecursive) {
+ manageEntity.apply( (EntityInternal)e );
+ } else {
+ recursively(e, manageEntity);
+ }
+
+ for (EntityInternal it : allEntities) {
+ if (!it.getManagementSupport().isFullyManaged()) {
+ ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
+ ManagementTransitionInfo info = new ManagementTransitionInfo(managementContext, mode);
+
+ it.getManagementSupport().onManagementStarted(info);
+ managementContext.getRebindManager().getChangeListener().onManaged(it);
+ }
+ }
+ }
+
+ @Override
+ public void unmanage(final Entity e) {
+ unmanage(e, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT));
+ }
+
+ public void unmanage(final Entity e, final ManagementTransitionMode mode) {
+ unmanage(e, mode, false);
+ }
+
+ private void unmanage(final Entity e, ManagementTransitionMode mode, boolean hasBeenReplaced) {
+ if (shouldSkipUnmanagement(e)) return;
+ final ManagementTransitionInfo info = new ManagementTransitionInfo(managementContext, mode);
+
+ if (hasBeenReplaced) {
+ // we are unmanaging an old instance after having replaced it
+ // don't unmanage or even clear its fields, because there might be references to it
+
+ if (mode.wasReadOnly()) {
+ // if coming *from* read only; nothing needed
+ } else {
+ if (!mode.wasPrimary()) {
+ log.warn("Unexpected mode "+mode+" for unmanage-replace "+e+" (applying anyway)");
+ }
+ // migrating away or in-place active partial rebind:
+ ((EntityInternal)e).getManagementSupport().onManagementStopping(info);
+ stopTasks(e);
+ ((EntityInternal)e).getManagementSupport().onManagementStopped(info);
+ }
+ // do not remove from maps below, bail out now
+ return;
+
+ } else if (mode.wasReadOnly() && mode.isNoLongerLoaded()) {
+ // we are unmanaging an instance (secondary); either stopping here or primary destroyed elsewhere
+ ((EntityInternal)e).getManagementSupport().onManagementStopping(info);
+ unmanageNonRecursive(e);
+ stopTasks(e);
+ ((EntityInternal)e).getManagementSupport().onManagementStopped(info);
+ managementContext.getRebindManager().getChangeListener().onUnmanaged(e);
+ if (managementContext.getGarbageCollector() != null) managementContext.getGarbageCollector().onUnmanaged(e);
+
+ } else if (mode.wasPrimary() && mode.isNoLongerLoaded()) {
+ // unmanaging a primary; currently this is done recursively
+
+ /* TODO tidy up when it is recursive and when it isn't; if something is being unloaded or destroyed,
+ * that probably *is* recursive, but the old mode might be different if in some cases things are read-only.
+ * or maybe nothing needs to be recursive, we just make sure the callers (e.g. HighAvailabilityModeImpl.clearManagedItems)
+ * call in a good order
+ *
+ * see notes above about recursive/manage/All/unmanageAll
+ */
+
+ // Need to store all child entities as onManagementStopping removes a child from the parent entity
+ final List<EntityInternal> allEntities = Lists.newArrayList();
+ recursively(e, new Predicate<EntityInternal>() { public boolean apply(EntityInternal it) {
+ if (shouldSkipUnmanagement(it)) return false;
+ allEntities.add(it);
+ it.getManagementSupport().onManagementStopping(info);
+ return true;
+ } });
+
+ for (EntityInternal it : allEntities) {
+ if (shouldSkipUnmanagement(it)) continue;
+ unmanageNonRecursive(it);
+ stopTasks(it);
+ }
+ for (EntityInternal it : allEntities) {
+ it.getManagementSupport().onManagementStopped(info);
+ managementContext.getRebindManager().getChangeListener().onUnmanaged(it);
+ if (managementContext.getGarbageCollector() != null) managementContext.getGarbageCollector().onUnmanaged(e);
+ }
+
+ } else {
+ log.warn("Invalid mode for unmanage: "+mode+" on "+e+" (ignoring)");
+ }
+
+ preRegisteredEntitiesById.remove(e.getId());
+ preManagedEntitiesById.remove(e.getId());
+ entityProxiesById.remove(e.getId());
+ entitiesById.remove(e.getId());
+ entityModesById.remove(e.getId());
+ }
+
+ private void stopTasks(Entity entity) {
+ stopTasks(entity, null);
+ }
+
+ /** stops all tasks (apart from any current one or its descendants) on this entity,
+ * optionally -- if a timeout is given -- waiting for completion and warning on incomplete tasks */
+ @Beta
+ public void stopTasks(Entity entity, @Nullable Duration timeout) {
+ CountdownTimer timeleft = timeout==null ? null : timeout.countdownTimer();
+ // try forcibly interrupting tasks on managed entities
+ Collection<Exception> exceptions = MutableSet.of();
+ try {
+ Set<Task<?>> tasksCancelled = MutableSet.of();
+ for (Task<?> t: managementContext.getExecutionContext(entity).getTasks()) {
+ if (entity.equals(BrooklynTaskTags.getContextEntity(Tasks.current())) && hasTaskAsAncestor(t, Tasks.current())) {
+ // don't cancel if we are running inside a task on the target entity and
+ // the task being considered is one we have submitted -- e.g. on "stop" don't cancel ourselves!
+ // but if our current task is from another entity we probably do want to cancel them (we are probably invoking unmanage)
+ continue;
+ }
+
+ if (!t.isDone()) {
+ try {
+ log.debug("Cancelling "+t+" on "+entity);
+ tasksCancelled.add(t);
+ t.cancel(true);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ log.debug("Error cancelling "+t+" on "+entity+" (will warn when all tasks are cancelled): "+e, e);
+ exceptions.add(e);
+ }
+ }
+ }
+
+ if (timeleft!=null) {
+ Set<Task<?>> tasksIncomplete = MutableSet.of();
+ // go through all tasks, not just cancelled ones, in case there are previously cancelled ones which are not complete
+ for (Task<?> t: managementContext.getExecutionContext(entity).getTasks()) {
+ if (hasTaskAsAncestor(t, Tasks.current()))
+ continue;
+ if (!Tasks.blockUntilInternalTasksEnded(t, timeleft.getDurationRemaining())) {
+ tasksIncomplete.add(t);
+ }
+ }
+ if (!tasksIncomplete.isEmpty()) {
+ log.warn("Incomplete tasks when stopping "+entity+": "+tasksIncomplete);
+ }
+ if (log.isTraceEnabled())
+ log.trace("Cancelled "+tasksCancelled+" tasks for "+entity+", with "+
+ timeleft.getDurationRemaining()+" remaining (of "+timeout+"): "+tasksCancelled);
+ } else {
+ if (log.isTraceEnabled())
+ log.trace("Cancelled "+tasksCancelled+" tasks for "+entity+": "+tasksCancelled);
+ }
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ log.warn("Error inspecting tasks to cancel on unmanagement: "+e, e);
+ }
+ if (!exceptions.isEmpty())
+ log.warn("Error when cancelling tasks for "+entity+" on unmanagement: "+Exceptions.create(exceptions));
+ }
+
+ private boolean hasTaskAsAncestor(Task<?> t, Task<?> potentialAncestor) {
+ if (t==null || potentialAncestor==null) return false;
+ if (t.equals(potentialAncestor)) return true;
+ return hasTaskAsAncestor(t.getSubmittedByTask(), potentialAncestor);
+ }
+
+ /**
+ * activates management when effector invoked, warning unless context is acceptable
+ * (currently only acceptable context is "start")
+ */
+ void manageIfNecessary(Entity entity, Object context) {
+ if (!isRunning()) {
+ return; // TODO Still a race for terminate being called, and then isManaged below returning false
+ } else if (((EntityInternal)entity).getManagementSupport().wasDeployed()) {
+ return;
+ } else if (isManaged(entity)) {
+ return;
+ } else if (isPreManaged(entity)) {
+ return;
+ } else if (Boolean.TRUE.equals(((EntityInternal)entity).getManagementSupport().isReadOnly())) {
+ return;
+ } else {
+ Entity rootUnmanaged = entity;
+ while (true) {
+ Entity candidateUnmanagedParent = rootUnmanaged.getParent();
+ if (candidateUnmanagedParent == null || isManaged(candidateUnmanagedParent) || isPreManaged(candidateUnmanagedParent))
+ break;
+ rootUnmanaged = candidateUnmanagedParent;
+ }
+ if (context == Startable.START.getName())
+ log.info("Activating local management for {} on start", rootUnmanaged);
+ else
+ log.warn("Activating local management for {} due to effector invocation on {}: {}", new Object[]{rootUnmanaged, entity, context});
+ manage(rootUnmanaged);
+ }
+ }
+
+ private void recursively(Entity e, Predicate<EntityInternal> action) {
+ Entity otherPreregistered = preRegisteredEntitiesById.get(e.getId());
+ if (otherPreregistered!=null) {
+ // if something has been pre-registered, prefer it
+ // (e.g. if we recursing through children, we might have a proxy from previous iteration;
+ // the most recent will have been pre-registered)
+ e = otherPreregistered;
+ }
+
+ boolean success = action.apply( (EntityInternal)e );
+ if (!success) {
+ return; // Don't manage children if action false/unnecessary for parent
+ }
+ for (Entity child : e.getChildren()) {
+ recursively(child, action);
+ }
+ }
+
+ /**
+ * Whether the entity is in the process of being managed.
+ */
+ private synchronized boolean isPreManaged(Entity e) {
+ return preManagedEntitiesById.containsKey(e.getId());
+ }
+
+ /**
+ * Should ensure that the entity is now known about, but should not be accessible from other entities yet.
+ *
+ * Records that the given entity is about to be managed (used for answering {@link isPreManaged(Entity)}.
+ * Note that refs to the given entity are stored in a a weak hashmap so if the subsequent management
+ * attempt fails then this reference to the entity will eventually be discarded (if no-one else holds
+ * a reference).
+ */
+ private synchronized boolean preManageNonRecursive(Entity e, ManagementTransitionMode mode) {
+ Entity realE = toRealEntity(e);
+
+ Object old = preManagedEntitiesById.put(e.getId(), realE);
+ preRegisteredEntitiesById.remove(e.getId());
+
+ if (old!=null && mode.wasNotLoaded()) {
+ if (old.equals(e)) {
+ log.warn("{} redundant call to pre-start management of entity {}, mode {}; ignoring", new Object[] { this, e, mode });
+ } else {
+ throw new IllegalStateException("call to pre-manage entity "+e+" ("+mode+") but different entity "+old+" already known under that id at "+this);
+ }
+ return false;
+ } else {
+ if (log.isTraceEnabled()) log.trace("{} pre-start management of entity {}, mode {}",
+ new Object[] { this, e, mode });
+ return true;
+ }
+ }
+
+ /**
+ * Should ensure that the entity is now managed somewhere, and known about in all the lists.
+ * Returns true if the entity has now become managed; false if it was already managed (anything else throws exception)
+ * @param isOrWasReadOnly
+ */
+ private synchronized boolean manageNonRecursive(Entity e, ManagementTransitionMode mode) {
+ Entity old = entitiesById.get(e.getId());
+
+ if (old!=null && mode.wasNotLoaded()) {
+ if (old.equals(e)) {
+ log.warn("{} redundant call to start management of entity {}; ignoring", this, e);
+ } else {
+ throw new IllegalStateException("call to manage entity "+e+" ("+mode+") but different entity "+old+" already known under that id at "+this);
+ }
+ return false;
+ }
+
+ BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(e),
+ "{} starting management of entity {}", this, e);
+ Entity realE = toRealEntity(e);
+
+ Entity oldProxy = entityProxiesById.get(e.getId());
+ Entity proxyE;
+ if (oldProxy!=null) {
+ if (mode.wasNotLoaded()) {
+ throw new IllegalStateException("call to manage entity "+e+" from unloaded state ("+mode+") but already had proxy "+oldProxy+" already known under that id at "+this);
+ }
+ // make the old proxy point at this new delegate
+ // (some other tricks done in the call below)
+ ((EntityProxyImpl)(Proxy.getInvocationHandler(oldProxy))).resetDelegate(oldProxy, oldProxy, realE);
+ proxyE = oldProxy;
+ } else {
+ proxyE = toProxyEntityIfAvailable(e);
+ }
+ entityProxiesById.put(e.getId(), proxyE);
+ entityTypes.put(e.getId(), realE.getClass().getName());
+ entitiesById.put(e.getId(), realE);
+
+ preManagedEntitiesById.remove(e.getId());
+ if ((e instanceof Application) && (e.getParent()==null)) {
+ applications.add((Application)proxyE);
+ applicationIds.add(e.getId());
+ }
+ if (!entities.contains(proxyE))
+ entities.add(proxyE);
+
+ if (old!=null && old!=e) {
+ // passing the transition info will ensure the right shutdown steps invoked for old instance
+ unmanage(old, mode, true);
+ }
+
+ return true;
+ }
+
+ /**
+ * Should ensure that the entity is no longer managed anywhere, remove from all lists.
+ * Returns true if the entity has been removed from management; if it was not previously managed (anything else throws exception)
+ */
+ private boolean unmanageNonRecursive(Entity e) {
+ /*
+ * When method is synchronized, hit deadlock:
+ * 1. thread called unmanage() on a member of a group, so we got the lock and called group.removeMember;
+ * this ties to synchronize on AbstractGroupImpl.members
+ * 2. another thread was doing AbstractGroupImpl.addMember, which is synchronized on AbstractGroupImpl.members;
+ * it tries to call Entities.manage(child) which calls LocalEntityManager.getEntity(), which is
+ * synchronized on this.
+ *
+ * We MUST NOT call alien code from within the management framework while holding locks.
+ * The AbstractGroup.removeMember is effectively alien because a user could override it, and because
+ * it is entity specific.
+ *
+ * TODO Does getting then removing from groups risk this entity being added to other groups while
+ * this is happening? Should abstractEntity.onManagementStopped or some such remove the entity
+ * from its groups?
+ */
+
+ if (!getLastManagementTransitionMode(e.getId()).isReadOnly()) {
+ e.clearParent();
+ Collection<Group> groups = e.getGroups();
+ for (Group group : groups) {
+ if (!Entities.isNoLongerManaged(group)) group.removeMember(e);
+ }
+ if (e instanceof Group) {
+ Collection<Entity> members = ((Group)e).getMembers();
+ for (Entity member : members) {
+ if (!Entities.isNoLongerManaged(member)) member.removeGroup((Group)e);
+ }
+ }
+ } else {
+ log.debug("No relations being updated on unmanage of read only {}", e);
+ }
+
+ synchronized (this) {
+ Entity proxyE = toProxyEntityIfAvailable(e);
+ if (e instanceof Application) {
+ applications.remove(proxyE);
+ applicationIds.remove(e.getId());
+ }
+
+ entities.remove(proxyE);
+ entityProxiesById.remove(e.getId());
+ entityModesById.remove(e.getId());
+ Object old = entitiesById.remove(e.getId());
+
+ entityTypes.remove(e.getId());
+ if (old==null) {
+ log.warn("{} call to stop management of unknown entity (already unmanaged?) {}; ignoring", this, e);
+ return false;
+ } else if (!old.equals(e)) {
+ // shouldn't happen...
+ log.error("{} call to stop management of entity {} removed different entity {}", new Object[] { this, e, old });
+ return true;
+ } else {
+ if (log.isDebugEnabled()) log.debug("{} stopped management of entity {}", this, e);
+ return true;
+ }
+ }
+ }
+
+ void addEntitySetListener(CollectionChangeListener<Entity> listener) {
+ //must notify listener in a different thread to avoid deadlock (issue #378)
+ AsyncCollectionChangeAdapter<Entity> wrappedListener = new AsyncCollectionChangeAdapter<Entity>(managementContext.getExecutionManager(), listener);
+ entities.addPropertyChangeListener(new GroovyObservablesPropertyChangeToCollectionChangeAdapter(wrappedListener));
+ }
+
+ void removeEntitySetListener(CollectionChangeListener<Entity> listener) {
+ AsyncCollectionChangeAdapter<Entity> wrappedListener = new AsyncCollectionChangeAdapter<Entity>(managementContext.getExecutionManager(), listener);
+ entities.removePropertyChangeListener(new GroovyObservablesPropertyChangeToCollectionChangeAdapter(wrappedListener));
+ }
+
+ private boolean shouldSkipUnmanagement(Entity e) {
+ if (e==null) {
+ log.warn(""+this+" call to unmanage null entity; skipping",
+ new IllegalStateException("source of null unmanagement call to "+this));
+ return true;
+ }
+ if (!isManaged(e)) {
+ log.warn("{} call to stop management of unknown entity (already unmanaged?) {}; skipping, and all descendants", this, e);
+ return true;
+ }
+ return false;
+ }
+
+ private Entity toProxyEntityIfAvailable(Entity e) {
+ checkNotNull(e, "entity");
+
+ if (e instanceof EntityProxy) {
+ return e;
+ } else if (e instanceof AbstractEntity) {
+ Entity result = ((AbstractEntity)e).getProxy();
+ return (result == null) ? e : result;
+ } else {
+ // If we don't already know about the proxy, then use the real thing; presumably it's
+ // the legacy way of creating the entity so didn't get a preManage() call
+
+ return e;
+ }
+ }
+
+ private Entity toRealEntity(Entity e) {
+ checkNotNull(e, "entity");
+
+ if (e instanceof AbstractEntity) {
+ return e;
+ } else {
+ Entity result = toRealEntityOrNull(e.getId());
+ if (result == null) {
+ throw new IllegalStateException("No concrete entity known for entity "+e+" ("+e.getId()+", "+e.getEntityType().getName()+")");
+ }
+ return result;
+ }
+ }
+
+ public boolean isKnownEntityId(String id) {
+ return entitiesById.containsKey(id) || preManagedEntitiesById.containsKey(id) || preRegisteredEntitiesById.containsKey(id);
+ }
+
+ private Entity toRealEntityOrNull(String id) {
+ Entity result;
+ // prefer the preRegistered and preManaged entities, during hot proxying, they should be newer
+ result = preRegisteredEntitiesById.get(id);
+ if (result==null)
+ result = preManagedEntitiesById.get(id);
+ if (result==null)
+ entitiesById.get(id);
+ return result;
+ }
+
+ private boolean isRunning() {
+ return managementContext.isRunning();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java
new file mode 100644
index 0000000..54708f5
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalLocationManager.java
@@ -0,0 +1,463 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.Closeable;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.location.ProvisioningLocation;
+import org.apache.brooklyn.api.management.AccessController;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.BrooklynLogging;
+import brooklyn.config.BrooklynLogging.LoggingLevel;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.proxying.InternalLocationFactory;
+import brooklyn.internal.storage.BrooklynStorage;
+
+import org.apache.brooklyn.location.basic.AbstractLocation;
+import org.apache.brooklyn.location.basic.LocationInternal;
+
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.RuntimeInterruptedException;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.task.Tasks;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+public class LocalLocationManager implements LocationManagerInternal {
+
+ @Beta /* expect to remove when API returns LocationSpec or similar */
+ public static final ConfigKey<Boolean> CREATE_UNMANAGED = ConfigKeys.newBooleanConfigKey("brooklyn.internal.location.createUnmanaged",
+ "If set on a location or spec, causes the manager to create it in an unmanaged state (for peeking)", false);
+
+ private static final Logger log = LoggerFactory.getLogger(LocalLocationManager.class);
+
+ private final LocalManagementContext managementContext;
+ private final InternalLocationFactory locationFactory;
+
+ protected final Map<String,Location> locationsById = Maps.newLinkedHashMap();
+ private final Map<String, Location> preRegisteredLocationsById = Maps.newLinkedHashMap();
+
+ /** Management mode for each location */
+ protected final Map<String,ManagementTransitionMode> locationModesById = Maps.newLinkedHashMap();
+
+ private final BrooklynStorage storage;
+ private Map<String, String> locationTypes;
+
+ private static AtomicLong LOCATION_CNT = new AtomicLong(0);
+
+ public LocalLocationManager(LocalManagementContext managementContext) {
+ this.managementContext = checkNotNull(managementContext, "managementContext");
+ this.locationFactory = new InternalLocationFactory(managementContext);
+
+ this.storage = managementContext.getStorage();
+ locationTypes = storage.getMap("locations");
+ }
+
+ public InternalLocationFactory getLocationFactory() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+ return locationFactory;
+
+ }
+
+ @Override
+ public <T extends Location> T createLocation(LocationSpec<T> spec) {
+ try {
+ boolean createUnmanaged = ConfigBag.coerceFirstNonNullKeyValue(CREATE_UNMANAGED,
+ spec.getConfig().get(CREATE_UNMANAGED), spec.getFlags().get(CREATE_UNMANAGED.getName()));
+ if (createUnmanaged) {
+ spec.removeConfig(CREATE_UNMANAGED);
+ }
+
+ T loc = locationFactory.createLocation(spec);
+ if (!createUnmanaged) {
+ manage(loc);
+ } else {
+ // remove references
+ Location parent = loc.getParent();
+ if (parent!=null) {
+ ((AbstractLocation)parent).removeChild(loc);
+ }
+ preRegisteredLocationsById.remove(loc.getId());
+ }
+
+ return loc;
+ } catch (Throwable e) {
+ log.warn("Failed to create location using spec "+spec+" (rethrowing)", e);
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public <T extends Location> T createLocation(Map<?,?> config, Class<T> type) {
+ return createLocation(LocationSpec.create(config, type));
+ }
+
+ @Override
+ public synchronized Collection<Location> getLocations() {
+ return ImmutableList.copyOf(locationsById.values());
+ }
+
+ @Override
+ public Collection<String> getLocationIds() {
+ return ImmutableList.copyOf(locationsById.keySet());
+ }
+
+ @Override
+ public synchronized Location getLocation(String id) {
+ return locationsById.get(id);
+ }
+
+ public synchronized Location getLocationEvenIfPreManaged(String id) {
+ Location result = locationsById.get(id);
+ if (result == null) {
+ result = preRegisteredLocationsById.get(id);
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isManaged(Location loc) {
+ return (isRunning() && loc != null && getLocation(loc.getId()) != null);
+ }
+
+ synchronized boolean isPreRegistered(Location loc) {
+ return preRegisteredLocationsById.containsKey(loc.getId());
+ }
+
+ public boolean isKnownLocationId(String id) {
+ return preRegisteredLocationsById.containsKey(id) || locationsById.containsKey(id);
+ }
+
+ synchronized void prePreManage(Location loc) {
+ if (isPreRegistered(loc)) {
+ log.warn(""+this+" redundant call to pre-pre-manage location "+loc+"; skipping",
+ new Exception("source of duplicate pre-pre-manage of "+loc));
+ return;
+ }
+ preRegisteredLocationsById.put(loc.getId(), loc);
+ }
+
+ @Override
+ public ManagementTransitionMode getLastManagementTransitionMode(String itemId) {
+ return locationModesById.get(itemId);
+ }
+
+ @Override
+ public void setManagementTransitionMode(Location item, ManagementTransitionMode mode) {
+ locationModesById.put(item.getId(), mode);
+ }
+
+ // TODO synchronization issues here: see comment in LocalEntityManager.manage(Entity)
+ /** management on creation */
+ @Override
+ public Location manage(Location loc) {
+ if (isManaged(loc)) {
+ // TODO put log.warn back in if/when manage(Location) becomes private; or could even have assert.
+ // Can be stricter about contract.
+ return loc;
+ }
+
+ Location parent = loc.getParent();
+ if (parent != null && !managementContext.getLocationManager().isManaged(parent)) {
+ log.warn("Parent location "+parent+" of "+loc+" is not managed; attempting to manage it (in future this may be disallowed)");
+ return manage(parent);
+ } else {
+ return manageRecursive(loc, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.NONEXISTENT, BrooklynObjectManagementMode.MANAGED_PRIMARY));
+ }
+ }
+
+ @Override
+ public void manageRebindedRoot(Location item) {
+ ManagementTransitionMode mode = getLastManagementTransitionMode(item.getId());
+ Preconditions.checkNotNull(mode, "Mode not set for rebinding %s", item);
+ manageRecursive(item, mode);
+ }
+
+ protected void checkManagementAllowed(Location item) {
+ AccessController.Response access = managementContext.getAccessController().canManageLocation(item);
+ if (!access.isAllowed()) {
+ throw new IllegalStateException("Access controller forbids management of "+item+": "+access.getMsg());
+ }
+ }
+
+ protected Location manageRecursive(Location loc, final ManagementTransitionMode initialMode) {
+ // TODO see comments in LocalEntityManager about recursive management / manageRebindRoot v manageAll
+
+ AccessController.Response access = managementContext.getAccessController().canManageLocation(loc);
+ if (!access.isAllowed()) {
+ throw new IllegalStateException("Access controller forbids management of "+loc+": "+access.getMsg());
+ }
+
+ long count = LOCATION_CNT.incrementAndGet();
+ if (log.isDebugEnabled()) {
+ String msg = "Managing location " + loc + " ("+initialMode+"), from " + Tasks.current()+" / "+Entitlements.getEntitlementContext();
+ LoggingLevel level = (!initialMode.wasNotLoaded() || initialMode.isReadOnly() ? LoggingLevel.TRACE : LoggingLevel.DEBUG);
+ if (count % 100 == 0) {
+ // include trace periodically in case we get leaks or too much location management
+ BrooklynLogging.log(log, level,
+ msg, new Exception("Informational stack trace of call to manage location "+loc+" ("+count+" calls; "+getLocations().size()+" currently managed)"));
+ } else {
+ BrooklynLogging.log(log, level, msg);
+ }
+ }
+
+ recursively(loc, new Predicate<AbstractLocation>() { public boolean apply(AbstractLocation it) {
+ ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
+ if (mode==null) {
+ setManagementTransitionMode(it, mode = initialMode);
+ }
+
+ if (it.isManaged()) {
+ if (mode.wasNotLoaded()) {
+ // silently bail out
+ return false;
+ } else {
+ // on rebind, we just replace, fall through to below
+ }
+ }
+
+ boolean result = manageNonRecursive(it, mode);
+ if (result) {
+ it.setManagementContext(managementContext);
+ if (mode.isPrimary()) {
+ it.onManagementStarted();
+ if (mode.isCreating()) {
+ // Never record event on rebind; this isn't the location (e.g. the VM) being "created"
+ // so don't tell listeners that.
+ // TODO The location-event history should be persisted; currently it is lost on
+ // rebind, unless there is a listener that is persisting the state externally itself.
+ recordLocationEvent(it, Lifecycle.CREATED);
+ }
+ }
+ managementContext.getRebindManager().getChangeListener().onManaged(it);
+ }
+ return result;
+ } });
+ return loc;
+ }
+
+ @Override
+ public void unmanage(final Location loc) {
+ unmanage(loc, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT));
+ }
+
+ public void unmanage(final Location loc, final ManagementTransitionMode mode) {
+ unmanage(loc, mode, false);
+ }
+
+ private void unmanage(final Location loc, final ManagementTransitionMode mode, boolean hasBeenReplaced) {
+ if (shouldSkipUnmanagement(loc)) return;
+
+ if (hasBeenReplaced) {
+ // we are unmanaging an old instance after having replaced it;
+ // don't unmanage or even clear its fields, because there might be references to it
+
+ if (mode.wasReadOnly()) {
+ // if coming *from* read only; nothing needed
+ } else {
+ if (!mode.wasPrimary()) {
+ log.warn("Unexpected mode "+mode+" for unmanage-replace "+loc+" (applying anyway)");
+ }
+ // migrating away or in-place active partial rebind:
+ managementContext.getRebindManager().getChangeListener().onUnmanaged(loc);
+ if (managementContext.gc != null) managementContext.gc.onUnmanaged(loc);
+ }
+ // do not remove from maps below, bail out now
+ return;
+
+ } else if ((mode.wasPrimary() && mode.isReadOnly()) || (mode.wasReadOnly() && mode.isNoLongerLoaded())) {
+ if (mode.isReadOnly() && mode.wasPrimary()) {
+ // TODO shouldn't this fall into "hasBeenReplaced" above?
+ log.debug("Unmanaging on demotion: "+loc+" ("+mode+")");
+ }
+ // we are unmanaging an instance whose primary management is elsewhere (either we were secondary, or we are being demoted)
+ unmanageNonRecursiveRemoveFromRecords(loc, mode);
+ managementContext.getRebindManager().getChangeListener().onUnmanaged(loc);
+ if (managementContext.gc != null) managementContext.gc.onUnmanaged(loc);
+ unmanageNonRecursiveClearItsFields(loc, mode);
+
+ } else if (mode.isNoLongerLoaded()) {
+ // Need to store all child entities as onManagementStopping removes a child from the parent entity
+
+ // As above, see TODO in LocalEntityManager about recursive management / unmanagement v manageAll/unmanageAll
+ recursively(loc, new Predicate<AbstractLocation>() { public boolean apply(AbstractLocation it) {
+ if (shouldSkipUnmanagement(it)) return false;
+ boolean result = unmanageNonRecursiveRemoveFromRecords(it, mode);
+ if (result) {
+ ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
+ if (mode==null) {
+ // ad hoc creation e.g. tests
+ log.debug("Missing transition mode for "+it+" when unmanaging; assuming primary/destroying");
+ mode = ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT);
+ }
+ if (mode.wasPrimary()) it.onManagementStopped();
+ managementContext.getRebindManager().getChangeListener().onUnmanaged(it);
+ if (mode.isDestroying()) recordLocationEvent(it, Lifecycle.DESTROYED);
+ if (managementContext.gc != null) managementContext.gc.onUnmanaged(it);
+ }
+ unmanageNonRecursiveClearItsFields(loc, mode);
+ return result;
+ } });
+
+ } else {
+ log.warn("Invalid mode for unmanage: "+mode+" on "+loc+" (ignoring)");
+ }
+
+ if (loc instanceof Closeable) {
+ Streams.closeQuietly( (Closeable)loc );
+ }
+
+ locationsById.remove(loc.getId());
+ preRegisteredLocationsById.remove(loc.getId());
+ locationModesById.remove(loc.getId());
+ locationTypes.remove(loc.getId());
+ }
+
+ /**
+ * Adds this location event to the usage record for the given location (creating the usage
+ * record if one does not already exist).
+ */
+ private void recordLocationEvent(LocationInternal loc, Lifecycle state) {
+ try {
+ managementContext.getUsageManager().recordLocationEvent(loc, state);
+ } catch (RuntimeInterruptedException e) {
+ throw e;
+ } catch (RuntimeException e) {
+ log.warn("Failed to store location lifecycle event for "+loc+" (ignoring)", e);
+ }
+ }
+
+ private void recursively(Location e, Predicate<AbstractLocation> action) {
+ boolean success = action.apply( (AbstractLocation)e );
+ if (!success) {
+ return; // Don't manage children if action false/unnecessary for parent
+ }
+ for (Location child : e.getChildren()) {
+ recursively(child, action);
+ }
+ }
+
+ /**
+ * Should ensure that the location is now managed somewhere, and known about in all the lists.
+ * Returns true if the location has now become managed; false if it was already managed (anything else throws exception)
+ * @param rebindPrimary true if rebinding primary, false if rebinding as copy, null if creating (not rebinding)
+ */
+ private synchronized boolean manageNonRecursive(Location loc, ManagementTransitionMode mode) {
+ Location old = locationsById.put(loc.getId(), loc);
+ preRegisteredLocationsById.remove(loc.getId());
+
+ locationTypes.put(loc.getId(), loc.getClass().getName());
+
+ if (old!=null && mode.wasNotLoaded()) {
+ if (old.equals(loc)) {
+ log.warn("{} redundant call to start management of location {}", this, loc);
+ } else {
+ throw new IllegalStateException("call to manage location "+loc+" but different location "+old+" already known under that id at "+this);
+ }
+ return false;
+ }
+
+ if (old!=null && old!=loc) {
+ // passing the transition info will ensure the right shutdown steps invoked for old instance
+ unmanage(old, mode, true);
+ }
+
+ return true;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private synchronized void unmanageNonRecursiveClearItsFields(Location loc, ManagementTransitionMode mode) {
+ if (mode.isDestroying()) {
+ ((AbstractLocation)loc).setParent(null, true);
+
+ Location parent = ((AbstractLocation)loc).getParent();
+ if (parent instanceof ProvisioningLocation<?>) {
+ try {
+ ((ProvisioningLocation)parent).release(loc);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ log.debug("Error releasing "+loc+" in its parent "+parent+": "+e);
+ }
+ }
+ } else {
+ // if not destroying, don't change the parent's children list
+ ((AbstractLocation)loc).setParent(null, false);
+ }
+ // clear config to help with GC; i know you're not supposed to, but this seems to help, else config bag is littered with refs to entities etc
+ // FIXME relies on config().getLocalBag() returning the underlying bag!
+ ((AbstractLocation)loc).config().getLocalBag().clear();
+ }
+
+ /**
+ * Should ensure that the location is no longer managed anywhere, remove from all lists.
+ * Returns true if the location has been removed from management; if it was not previously managed (anything else throws exception)
+ */
+ private synchronized boolean unmanageNonRecursiveRemoveFromRecords(Location loc, ManagementTransitionMode mode) {
+ Object old = locationsById.remove(loc.getId());
+ locationTypes.remove(loc.getId());
+ locationModesById.remove(loc.getId());
+
+ if (old==null) {
+ log.warn("{} call to stop management of unknown location (already unmanaged?) {}; ignoring", this, loc);
+ return false;
+ } else if (!old.equals(loc)) {
+ // shouldn't happen...
+ log.error("{} call to stop management of location {} removed different location {}; ignoring", new Object[] { this, loc, old });
+ return true;
+ } else {
+ if (log.isDebugEnabled()) log.debug("{} stopped management of location {}", this, loc);
+ return true;
+ }
+ }
+
+ private boolean shouldSkipUnmanagement(Location loc) {
+ if (loc==null) {
+ log.warn(""+this+" call to unmanage null location; skipping",
+ new IllegalStateException("source of null unmanagement call to "+this));
+ return true;
+ }
+ if (!isManaged(loc)) {
+ log.warn("{} call to stop management of unknown location (already unmanaged?) {}; skipping, and all descendants", this, loc);
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isRunning() {
+ return managementContext.isRunning();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
new file mode 100644
index 0000000..306dcd8
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
@@ -0,0 +1,421 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static brooklyn.util.JavaGroovyEquivalents.elvis;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.AccessController;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.SubscriptionManager;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.ha.OsgiManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynProperties.Factory.Builder;
+import brooklyn.entity.drivers.downloads.BasicDownloadsManager;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.proxying.InternalEntityFactory;
+import brooklyn.entity.proxying.InternalLocationFactory;
+import brooklyn.entity.proxying.InternalPolicyFactory;
+import brooklyn.internal.BrooklynFeatureEnablement;
+import brooklyn.internal.storage.DataGridFactory;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.task.BasicExecutionContext;
+import brooklyn.util.task.BasicExecutionManager;
+import brooklyn.util.task.DynamicTasks;
+import brooklyn.util.task.TaskTags;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.text.Strings;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A local (single node) implementation of the {@link ManagementContext} API.
+ */
+public class LocalManagementContext extends AbstractManagementContext {
+
+ private static final Logger log = LoggerFactory.getLogger(LocalManagementContext.class);
+
+ private static final Set<LocalManagementContext> INSTANCES = Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<LocalManagementContext, Boolean>()));
+
+ private final Builder builder;
+
+ private final List<ManagementContext.PropertiesReloadListener> reloadListeners = new CopyOnWriteArrayList<ManagementContext.PropertiesReloadListener>();
+
+ @VisibleForTesting
+ static Set<LocalManagementContext> getInstances() {
+ synchronized (INSTANCES) {
+ return ImmutableSet.copyOf(INSTANCES);
+ }
+ }
+
+ // Note also called reflectively by BrooklynLeakListener
+ public static void logAll(Logger logger){
+ for (LocalManagementContext context : getInstances()) {
+ logger.warn("Management Context "+context+" running, creation stacktrace:\n" + Throwables.getStackTraceAsString(context.constructionStackTrace));
+ }
+ }
+
+ /** terminates all (best effort); returns count of sessions closed; if exceptions thrown, returns negative number.
+ * semantics might change, particular in dealing with interminable mgmt contexts. */
+ // Note also called reflectively by BrooklynLeakListener
+ @Beta
+ public static int terminateAll() {
+ int closed=0,dangling=0;
+ for (LocalManagementContext context : getInstances()) {
+ try {
+ context.terminate();
+ closed++;
+ }catch (Throwable t) {
+ Exceptions.propagateIfFatal(t);
+ log.warn("Failed to terminate management context", t);
+ dangling++;
+ }
+ }
+ if (dangling>0) return -dangling;
+ return closed;
+ }
+
+ private String managementPlaneId;
+ private String managementNodeId;
+ private BasicExecutionManager execution;
+ private SubscriptionManager subscriptions;
+ private LocalEntityManager entityManager;
+ private final LocalLocationManager locationManager;
+ private final LocalAccessManager accessManager;
+ private final LocalUsageManager usageManager;
+ private OsgiManager osgiManager;
+
+ public final Throwable constructionStackTrace = new Throwable("for construction stacktrace").fillInStackTrace();
+
+ private final Map<String, Object> brooklynAdditionalProperties;
+
+ /**
+ * Creates a LocalManagement with default BrooklynProperties.
+ */
+ public LocalManagementContext() {
+ this(BrooklynProperties.Factory.builderDefault());
+ }
+
+ public LocalManagementContext(BrooklynProperties brooklynProperties) {
+ this(brooklynProperties, (DataGridFactory)null);
+ }
+
+ /**
+ * Creates a new LocalManagementContext.
+ *
+ * @param brooklynProperties the BrooklynProperties.
+ * @param datagridFactory the DataGridFactory to use. If this instance is null, it means that the system
+ * is going to use BrooklynProperties to figure out which instance to load or otherwise
+ * use a default instance.
+ */
+ @VisibleForTesting
+ public LocalManagementContext(BrooklynProperties brooklynProperties, DataGridFactory datagridFactory) {
+ this(Builder.fromProperties(brooklynProperties), datagridFactory);
+ }
+
+ public LocalManagementContext(Builder builder) {
+ this(builder, null, null);
+ }
+
+ public LocalManagementContext(Builder builder, DataGridFactory datagridFactory) {
+ this(builder, null, datagridFactory);
+ }
+
+ public LocalManagementContext(Builder builder, Map<String, Object> brooklynAdditionalProperties) {
+ this(builder, brooklynAdditionalProperties, null);
+ }
+
+ public LocalManagementContext(BrooklynProperties brooklynProperties, Map<String, Object> brooklynAdditionalProperties) {
+ this(Builder.fromProperties(brooklynProperties), brooklynAdditionalProperties, null);
+ }
+
+ public LocalManagementContext(Builder builder, Map<String, Object> brooklynAdditionalProperties, DataGridFactory datagridFactory) {
+ super(builder.build(), datagridFactory);
+
+ checkNotNull(configMap, "brooklynProperties");
+
+ // TODO in a persisted world the planeId may be injected
+ this.managementPlaneId = Strings.makeRandomId(8);
+ this.managementNodeId = Strings.makeRandomId(8);
+ this.builder = builder;
+ this.brooklynAdditionalProperties = brooklynAdditionalProperties;
+ if (brooklynAdditionalProperties != null)
+ configMap.addFromMap(brooklynAdditionalProperties);
+
+ BrooklynFeatureEnablement.init(configMap);
+
+ this.locationManager = new LocalLocationManager(this);
+ this.accessManager = new LocalAccessManager();
+ this.usageManager = new LocalUsageManager(this);
+
+ if (configMap.getConfig(OsgiManager.USE_OSGI)) {
+ this.osgiManager = new OsgiManager(this);
+ osgiManager.start();
+ }
+
+ INSTANCES.add(this);
+ log.debug("Created management context "+this);
+ }
+
+ @Override
+ public String getManagementPlaneId() {
+ return managementPlaneId;
+ }
+
+ @Override
+ public String getManagementNodeId() {
+ return managementNodeId;
+ }
+
+ @Override
+ public void prePreManage(Entity entity) {
+ getEntityManager().prePreManage(entity);
+ }
+
+ @Override
+ public void prePreManage(Location location) {
+ getLocationManager().prePreManage(location);
+ }
+
+ @Override
+ public synchronized Collection<Application> getApplications() {
+ return getEntityManager().getApplications();
+ }
+
+ @Override
+ public void addEntitySetListener(CollectionChangeListener<Entity> listener) {
+ getEntityManager().addEntitySetListener(listener);
+ }
+
+ @Override
+ public void removeEntitySetListener(CollectionChangeListener<Entity> listener) {
+ getEntityManager().removeEntitySetListener(listener);
+ }
+
+ @Override
+ protected void manageIfNecessary(Entity entity, Object context) {
+ getEntityManager().manageIfNecessary(entity, context);
+ }
+
+ @Override
+ public synchronized LocalEntityManager getEntityManager() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+
+ if (entityManager == null) {
+ entityManager = new LocalEntityManager(this);
+ }
+ return entityManager;
+ }
+
+ @Override
+ public InternalEntityFactory getEntityFactory() {
+ return getEntityManager().getEntityFactory();
+ }
+
+ @Override
+ public InternalLocationFactory getLocationFactory() {
+ return getLocationManager().getLocationFactory();
+ }
+
+ @Override
+ public InternalPolicyFactory getPolicyFactory() {
+ return getEntityManager().getPolicyFactory();
+ }
+
+ @Override
+ public synchronized LocalLocationManager getLocationManager() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+ return locationManager;
+ }
+
+ @Override
+ public synchronized LocalAccessManager getAccessManager() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+ return accessManager;
+ }
+
+ @Override
+ public synchronized LocalUsageManager getUsageManager() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+ return usageManager;
+ }
+
+ @Override
+ public synchronized Maybe<OsgiManager> getOsgiManager() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+ if (osgiManager==null) return Maybe.absent("OSGi not available in this instance");
+ return Maybe.of(osgiManager);
+ }
+
+ @Override
+ public synchronized AccessController getAccessController() {
+ return getAccessManager().getAccessController();
+ }
+
+ @Override
+ public synchronized SubscriptionManager getSubscriptionManager() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+
+ if (subscriptions == null) {
+ subscriptions = new LocalSubscriptionManager(getExecutionManager());
+ }
+ return subscriptions;
+ }
+
+ @Override
+ public synchronized ExecutionManager getExecutionManager() {
+ if (!isRunning()) throw new IllegalStateException("Management context no longer running");
+
+ if (execution == null) {
+ execution = new BasicExecutionManager(getManagementNodeId());
+ gc = new BrooklynGarbageCollector(configMap, execution, getStorage());
+ }
+ return execution;
+ }
+
+ @Override
+ public void terminate() {
+ INSTANCES.remove(this);
+ super.terminate();
+ if (osgiManager!=null) {
+ osgiManager.stop();
+ osgiManager = null;
+ }
+ if (usageManager != null) usageManager.terminate();
+ if (execution != null) execution.shutdownNow();
+ if (gc != null) gc.shutdownNow();
+ }
+
+ @Override
+ protected void finalize() {
+ terminate();
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public <T> Task<T> runAtEntity(Map flags, Entity entity, Callable<T> c) {
+ manageIfNecessary(entity, elvis(Arrays.asList(flags.get("displayName"), flags.get("description"), flags, c)));
+ return runAtEntity(entity, Tasks.<T>builder().dynamic(true).body(c).flags(flags).build());
+ }
+
+ protected <T> Task<T> runAtEntity(Entity entity, TaskAdaptable<T> task) {
+ getExecutionContext(entity).submit(task);
+ if (DynamicTasks.getTaskQueuingContext()!=null) {
+ // put it in the queueing context so it appears in the GUI
+ // mark it inessential as this is being invoked from code,
+ // the caller will do 'get' to handle errors
+ TaskTags.markInessential(task);
+ DynamicTasks.getTaskQueuingContext().queue(task.asTask());
+ }
+ return task.asTask();
+ }
+
+ @Override
+ protected <T> Task<T> runAtEntity(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters) {
+ manageIfNecessary(entity, eff);
+ // prefer to submit this from the current execution context so it sets up correct cross-context chaining
+ ExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext();
+ if (ec == null) {
+ log.debug("Top-level effector invocation: {} on {}", eff, entity);
+ ec = getExecutionContext(entity);
+ }
+ return runAtEntity(entity, Effectors.invocation(entity, eff, parameters));
+ }
+
+ @Override
+ public boolean isManagedLocally(Entity e) {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return LocalManagementContext.class.getSimpleName()+"["+getManagementPlaneId()+"-"+getManagementNodeId()+"]";
+ }
+
+ @Override
+ public void reloadBrooklynProperties() {
+ log.info("Reloading brooklyn properties from " + builder);
+ if (builder.hasDelegateOriginalProperties())
+ log.warn("When reloading, mgmt context "+this+" properties are fixed, so reload will be of limited utility");
+
+ BrooklynProperties properties = builder.build();
+ configMap = properties;
+ if (brooklynAdditionalProperties != null) {
+ log.info("Reloading additional brooklyn properties from " + brooklynAdditionalProperties);
+ configMap.addFromMap(brooklynAdditionalProperties);
+ }
+ this.downloadsManager = BasicDownloadsManager.newDefault(configMap);
+ this.entitlementManager = Entitlements.newManager(this, configMap);
+
+ clearLocationRegistry();
+
+ BrooklynFeatureEnablement.init(configMap);
+
+ // Notify listeners that properties have been reloaded
+ for (PropertiesReloadListener listener : reloadListeners) {
+ listener.reloaded();
+ }
+ }
+
+ @VisibleForTesting
+ public void clearLocationRegistry() {
+ // Force reload of location registry
+ this.locationRegistry = null;
+ }
+
+ @Override
+ public void addPropertiesReloadListener(PropertiesReloadListener listener) {
+ reloadListeners.add(checkNotNull(listener, "listener"));
+ }
+
+ @Override
+ public void removePropertiesReloadListener(PropertiesReloadListener listener) {
+ reloadListeners.remove(listener);
+ }
+
+ public void noteStartupComplete() {
+ startupComplete = true;
+ }
+}
[03/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
new file mode 100644
index 0000000..8a555ed
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
@@ -0,0 +1,459 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.osgi;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.api.basic.BrooklynObject;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
+import brooklyn.catalog.internal.CatalogEntityItemDto;
+import brooklyn.catalog.internal.CatalogItemBuilder;
+import brooklyn.catalog.internal.CatalogItemDtoAbstract;
+import brooklyn.catalog.internal.CatalogTestUtils;
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.proxying.InternalEntityFactory;
+import brooklyn.entity.proxying.InternalPolicyFactory;
+
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.test.entity.TestApplication;
+
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.os.Os;
+import brooklyn.util.osgi.Osgis;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+
+/**
+ * Tests that OSGi entities load correctly and have the right catalog information set.
+ * Note further tests done elsewhere using CAMP YAML (referring to methods in this class).
+ */
+public class OsgiVersionMoreEntityTest {
+
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V1_PATH;
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V1_PATH;
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_PATH;
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V2_PATH;
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH;
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH;
+
+ public static final String TEST_VERSION = "0.1.0";
+
+ public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1 = "Hi BROOKLYN from V1";
+ public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2 = "HI BROOKLYN FROM V2";
+ public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN = "HO BROOKLYN FROM V2 EVIL TWIN";
+
+ protected LocalManagementContext mgmt;
+ protected TestApplication app;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).build();
+ app = TestApplication.Factory.newManagedInstanceForTests(mgmt);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws BundleException, IOException, InterruptedException {
+ Entities.destroyAll(mgmt);
+ }
+
+ /**
+ * Test fix for
+ * java.lang.NoClassDefFoundError: brooklyn.event.AttributeSensor not found by io.brooklyn.brooklyn-test-osgi-entities [41]
+ */
+ @Test
+ public void testEntityProxy() throws Exception {
+ File storageTempDir = Os.newTempDir("osgi-standalone");
+ Framework framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
+
+ try {
+ ManagementContextInternal managementContext;
+ InternalEntityFactory factory;
+
+ managementContext = new LocalManagementContextForTests();
+ InternalPolicyFactory policyFactory = new InternalPolicyFactory(managementContext);
+ factory = new InternalEntityFactory(managementContext, managementContext.getEntityManager().getEntityTypeRegistry(), policyFactory);
+
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+ Bundle bundle = Osgis.install(framework, BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+ @SuppressWarnings("unchecked")
+ Class<? extends Entity> bundleCls = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntityImpl");
+ @SuppressWarnings("unchecked")
+ Class<? extends Entity> bundleInterface = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntity");
+
+ @SuppressWarnings("unchecked")
+ EntitySpec<Entity> spec = (EntitySpec<Entity>) (((EntitySpec<Entity>)EntitySpec.create(bundleInterface))).impl(bundleCls);
+ Entity entity = bundleCls.newInstance();
+ factory.createEntityProxy(spec, entity);
+
+ if (managementContext != null) Entities.destroyAll(managementContext);
+ } finally {
+ OsgiStandaloneTest.tearDownOsgiFramework(framework, storageTempDir);
+ }
+ }
+
+ protected CatalogItem<?, ?> addCatalogItemWithTypeAsName(String type, String version, String ...libraries) {
+ return addCatalogItemWithNameAndType(type, version, type, libraries);
+ }
+ protected CatalogItem<?, ?> addCatalogItemWithNameAndType(String symName, String version, String type, String ...libraries) {
+ return addCatalogItemWithNameAndType(mgmt, symName, version, type, libraries);
+ }
+
+ @SuppressWarnings("deprecation")
+ static CatalogItem<?, ?> addCatalogItemWithNameAndType(ManagementContext mgmt, String symName, String version, String type, String ...libraries) {
+ CatalogEntityItemDto c1 = newCatalogItemWithNameAndType(symName, version, type, libraries);
+ mgmt.getCatalog().addItem(c1);
+ CatalogItem<?, ?> c2 = mgmt.getCatalog().getCatalogItem(symName, version);
+ Preconditions.checkNotNull(c2, "Item "+type+":"+version+" was not found after adding it");
+ return c2;
+ }
+
+ static CatalogEntityItemDto newCatalogItemWithTypeAsName(String type, String version, String ...libraries) {
+ return newCatalogItemWithNameAndType(type, version, type, libraries);
+ }
+ static CatalogEntityItemDto newCatalogItemWithNameAndType(String symName, String version, String type, String ...libraries) {
+ @SuppressWarnings("deprecation")
+ CatalogEntityItemDto c1 = CatalogItemBuilder.newEntity(symName, version)
+ .javaType(type)
+ .libraries(CatalogItemDtoAbstract.parseLibraries(Arrays.asList(libraries)))
+ .build();
+ return c1;
+ }
+
+ protected Entity addItemFromCatalog(CatalogItem<?, ?> c2) {
+ return addItemFromCatalog(mgmt, app, c2);
+ }
+
+ public static Entity addItemFromCatalog(ManagementContext mgmt, TestApplication parent, CatalogItem<?, ?> c2) {
+ return parent.createAndManageChild( CatalogTestUtils.createEssentialEntitySpec(mgmt, c2) );
+ }
+
+ public static void assertV1MethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1);
+ }
+ public static void assertV2MethodCall(BrooklynObject me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2);
+ }
+ public static void assertV2EvilTwinMethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN);
+ }
+
+ public static Object doMethodCallBrooklyn(BrooklynObject me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ return me.getClass().getMethod("sayHI", String.class).invoke(me, "Brooklyn");
+ }
+
+ public static void assertV1EffectorCall(Entity me) {
+ Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1);
+ }
+ public static void assertV2EffectorCall(Entity me) {
+ Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2);
+ }
+ public static void assertV2EvilTwinEffectorCall(Entity me) {
+ Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN);
+ }
+
+ public static String doEffectorCallBrooklyn(Entity me) {
+ return me.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), ImmutableMap.of("name", "brooklyn")).getUnchecked();
+ }
+
+ public static CatalogItem<?, ?> addMoreEntityV1(ManagementContext mgmt, String versionToRegister) {
+ TestResourceUnavailableException.throwIfResourceUnavailable(OsgiVersionMoreEntityTest.class, BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
+ return addCatalogItemWithNameAndType(mgmt,
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ versionToRegister,
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+ }
+ public static CatalogItem<?, ?> addMoreEntityV2(ManagementContext mgmt, String versionToRegister) {
+ TestResourceUnavailableException.throwIfResourceUnavailable(OsgiVersionMoreEntityTest.class, BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
+ return addCatalogItemWithNameAndType(mgmt,
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ versionToRegister,
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ BROOKLYN_TEST_MORE_ENTITIES_V2_URL,
+ BROOKLYN_TEST_OSGI_ENTITIES_URL);
+ }
+
+ @Test
+ public void testMoreEntitiesV1() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
+
+ CatalogItem<?, ?> c2 = addMoreEntityV1(mgmt, TEST_VERSION);
+
+ // test load and instantiate
+ Entity me = addItemFromCatalog(c2);
+ Assert.assertEquals(me.getCatalogItemId(), CatalogUtils.getVersionedId(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION));
+
+ assertV1MethodCall(me);
+ assertV1EffectorCall(me);
+
+ // test adding a child gets the right type; this time by entity parent hierarchy
+ BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, c2);
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Entity me2 = me.addChild(EntitySpec.create( (Class)loader.loadClass(c2.getJavaType()) ));
+ Assert.assertEquals(me2.getCatalogItemId(), CatalogUtils.getVersionedId(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION));
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected PolicySpec<?> getPolicySpec(CatalogItem<?, ?> cp) {
+ BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, cp);
+ PolicySpec spec = PolicySpec.create( (Class)loader.loadClass(cp.getJavaType()) );
+ spec.catalogItemId(cp.getId());
+ return spec;
+ }
+
+ @Test
+ public void testMoreEntitiesV1Policy() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+
+ CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ TEST_VERSION,
+ BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+
+ // test load and instantiate
+ Entity me = addItemFromCatalog(c2);
+
+ CatalogItem<?, ?> cp = addCatalogItemWithTypeAsName(
+ OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY,
+ TEST_VERSION,
+ BROOKLYN_TEST_OSGI_ENTITIES_URL);
+ me.addPolicy(getPolicySpec(cp));
+
+ Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
+
+ String catalogItemId = Iterables.getOnlyElement( me.getPolicies() ).getCatalogItemId();
+ Assert.assertNotNull(catalogItemId);
+ // must be the actual source bundle
+ Assert.assertFalse(catalogItemId.equals(me.getCatalogItemId()), "catalog item id is: "+catalogItemId);
+ Assert.assertTrue(catalogItemId.equals(CatalogUtils.getVersionedId(OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY, TEST_VERSION)), "catalog item id is: "+catalogItemId);
+ }
+
+ @Test
+ public void testMoreEntitiesV2FailsWithoutBasicTestOsgiEntitiesBundle() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
+
+ CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ TEST_VERSION,
+ BROOKLYN_TEST_MORE_ENTITIES_V2_URL);
+
+ // test load and instantiate
+ try {
+ Entity me = addItemFromCatalog(c2);
+ Assert.fail("Should have failed, with unresolved dependency; instead got "+me);
+ } catch (Exception e) {
+ Assert.assertTrue(e.toString().toLowerCase().contains("unresolved constraint"), "Missing expected text in error: "+e);
+ Assert.assertTrue(e.toString().toLowerCase().contains("wiring.package"), "Missing expected text in error: "+e);
+ Assert.assertTrue(e.toString().toLowerCase().contains("brooklyn.osgi.tests"), "Missing expected text in error: "+e);
+ }
+ }
+
+ // V2 works with dependency declared, and can load
+ // and has policy, with policy item catalog ID is reasonable
+ @Test
+ public void testMoreEntitiesV2() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
+
+ CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ TEST_VERSION,
+ BROOKLYN_TEST_MORE_ENTITIES_V2_URL,
+ BROOKLYN_TEST_OSGI_ENTITIES_URL);
+
+ // test load and instantiate
+ Entity me = addItemFromCatalog(c2);
+ Assert.assertEquals(me.getCatalogItemId(), CatalogUtils.getVersionedId(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION));
+
+ assertV2MethodCall(me);
+ assertV2EffectorCall(me);
+ Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
+
+ String catalogItemId = Iterables.getOnlyElement( me.getPolicies() ).getCatalogItemId();
+ Assert.assertNotNull(catalogItemId);
+ // allow either me's bundle (more) or the actual source bundle
+ Assert.assertTrue(catalogItemId.equals(me.getCatalogItemId()) || catalogItemId.startsWith("brooklyn-test-osgi-entities"));
+ }
+
+ @Test
+ public void testMoreEntitiesV1ThenV2GivesV2() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
+
+ addCatalogItemWithTypeAsName(
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ TEST_VERSION,
+ BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+ addCatalogItemWithTypeAsName(
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ TEST_VERSION,
+ BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+
+ // test load and instantiate
+ Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION) );
+
+ assertV2MethodCall(me);
+ assertV2EffectorCall(me);
+ Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
+ }
+
+ @Test
+ public void testMoreEntitiesV2ThenV1GivesV1() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
+
+ addCatalogItemWithTypeAsName(
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ TEST_VERSION,
+ BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+ addCatalogItemWithTypeAsName(
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ TEST_VERSION,
+ BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+
+ // test load and instantiate
+ Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION) );
+ /*
+ * WARNING - Weird maven-bundle-plugin and OSGi behaviour. Some caveats:
+ * <p>
+ * (1) When "import-package" declares a version, that is the *minimum* version;
+ * it may be that semantic versioning is applied, so 1.3.1 = [1.3.1,4.0.0);
+ * or it may be just a minimum 1.3.1 = [1.3.1,) ... i can't find good docs
+ * [but see http://www.christianposta.com/blog/?p=241]
+ * <p>
+ * (2) Different versions of maven-bundle-plugin do wildly different things.
+ * * v1.4.0 attaches the version to import-package (so you get the minimum
+ * which can cause this test to fail);
+ * * v2.x does not seem to declare the exported package at all in import-package
+ * (violating the so-called best practice, see
+ * http://blog.osgi.org/2007/04/importance-of-exporting-nd-importing.html )
+ * * v2.4.0 gives a huge list in import/export package, with semver ranges;
+ * but the other versions seem not to list much and they do NOT have versions
+ * <p>
+ * The tests are all working with 2.5.3 but if version dependencies become any
+ * more intertwined maven-bundle-plugin will almost certainly NOT do the wrong
+ * thing because packages do not have versions. (Ironically, 1.4.0 seems the
+ * best behaved, but for the minimum/semver package version behaviour, and
+ * even that wouldn't be so bad if you're doing semver, or if you figure out
+ * how to override with a _versionpolicy tag!)
+ */
+ assertV1MethodCall(me);
+ assertV1EffectorCall(me);
+ Assert.assertEquals(me.getPolicies().size(), 0, "Wrong number of policies: "+me.getPolicies());
+ }
+
+ @Test
+ public void testUnfazedByMoreEntitiesV1AndV2AndV2EvilTwin() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH);
+
+ addCatalogItemWithNameAndType("v1",
+ TEST_VERSION,
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+ addCatalogItemWithNameAndType("v2",
+ TEST_VERSION,
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+ addCatalogItemWithNameAndType("v2-evil",
+ TEST_VERSION,
+ OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
+ BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+
+ // test osgi finding
+
+ List<Bundle> bundles = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
+ .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL).findAll();
+ Assert.assertEquals(bundles.size(), 3, "Wrong list of bundles: "+bundles);
+
+ Maybe<Bundle> preferredVersion = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
+ .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL).find();
+ Assert.assertTrue(preferredVersion.isPresent());
+ Assert.assertEquals(preferredVersion.get().getVersion().toString(), "0.2.0");
+
+ Maybe<Bundle> evilVersion = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework()).
+ preferringFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL).find();
+ Assert.assertTrue(evilVersion.isPresent());
+ Assert.assertEquals(evilVersion.get().getVersion().toString(), "0.2.0");
+
+ // test preferredUrl vs requiredUrl
+
+ Maybe<Bundle> versionIgnoresInvalidPreferredUrl = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
+ .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL)
+ .version(TEST_VERSION)
+ .preferringFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL).find();
+ Assert.assertTrue(versionIgnoresInvalidPreferredUrl.isPresent());
+ Assert.assertEquals(versionIgnoresInvalidPreferredUrl.get().getVersion().toString(), TEST_VERSION);
+
+ Maybe<Bundle> versionRespectsInvalidRequiredUrl = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
+ .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL)
+ .version(TEST_VERSION)
+ .requiringFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL).find();
+ Assert.assertFalse(versionRespectsInvalidRequiredUrl.isPresent());
+
+ // test entity resolution
+
+ Entity v2 = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v2", TEST_VERSION) );
+ assertV2MethodCall(v2);
+ assertV2EffectorCall(v2);
+ Assert.assertEquals(v2.getPolicies().size(), 1, "Wrong number of policies: "+v2.getPolicies());
+
+ Entity v2_evil = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v2-evil", TEST_VERSION) );
+ assertV2EvilTwinMethodCall(v2_evil);
+ assertV2EvilTwinEffectorCall(v2_evil);
+ Assert.assertEquals(v2_evil.getPolicies().size(), 1, "Wrong number of policies: "+v2_evil.getPolicies());
+
+ Entity v1 = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v1", TEST_VERSION) );
+ assertV1MethodCall(v1);
+ assertV1EffectorCall(v1);
+ Assert.assertEquals(v1.getPolicies().size(), 0, "Wrong number of policies: "+v1.getPolicies());
+ }
+
+ // TODO versioning (WIP until #92), install both V1 and V2 with version number, and test that both work
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolverTest.java
index 541585f..dfda31e 100644
--- a/core/src/test/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolverTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/access/PortForwardManagerLocationResolverTest.java
@@ -19,6 +19,7 @@
package org.apache.brooklyn.location.access;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
@@ -26,7 +27,6 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
public class PortForwardManagerLocationResolverTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocationTest.java
index 3cb5ab9..f30665c 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/AggregatingMachineProvisioningLocationTest.java
@@ -27,6 +27,7 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -36,8 +37,6 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation.LocalhostMachine;
-import brooklyn.management.internal.LocalManagementContext;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/ByonLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/ByonLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/ByonLocationResolverTest.java
index 09eb142..c282fa2 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/ByonLocationResolverTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/ByonLocationResolverTest.java
@@ -33,6 +33,7 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,7 +45,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Networking;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
index 73ca57a..9ddc3bf 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
@@ -31,6 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -49,7 +50,6 @@ import com.google.common.collect.Lists;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Networking;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/HostLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/HostLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/HostLocationResolverTest.java
index 2ef938d..fff482c 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/HostLocationResolverTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/HostLocationResolverTest.java
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.NoSuchElementException;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -33,7 +34,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java
index 704f5ac..f04e6cd 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostLocationResolverTest.java
@@ -28,6 +28,7 @@ import java.util.NoSuchElementException;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
@@ -36,7 +37,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.text.StringEscapes.JavaStringEscapes;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java
index 2bd0d28..cd1df7a 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostMachineProvisioningLocationTest.java
@@ -39,9 +39,9 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
import org.apache.brooklyn.api.location.PortRange;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.geo.HostGeoInfo;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Networking;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java
index e1dff5e..52aa281 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocalhostProvisioningAndAccessTest.java
@@ -24,13 +24,13 @@ import static org.testng.Assert.assertTrue;
import java.util.Arrays;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
public class LocalhostProvisioningAndAccessTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java
index 219acd2..cfbc5ee 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationPredicatesTest.java
@@ -23,6 +23,7 @@ import static org.testng.Assert.assertTrue;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.annotations.AfterMethod;
@@ -30,7 +31,6 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
public class LocationPredicatesTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java
index b1e01ca..c887761 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/LocationRegistryTest.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.location.basic;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,7 +30,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
public class LocationRegistryTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java
index 8953397..8ccf2e4 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationResolverTest.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.Assert;
@@ -44,7 +45,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java
index 26423f5..314c81b 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/MultiLocationTest.java
@@ -32,9 +32,9 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.cloud.AvailabilityZoneExtension;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.net.Networking;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.java
index a9da0dd..2639db9 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineLocationResolverTest.java
@@ -25,6 +25,7 @@ import java.net.InetAddress;
import java.util.Map;
import java.util.NoSuchElementException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -32,7 +33,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java
index 7d42e88..7c1e951 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/SingleMachineProvisioningLocationTest.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.location.basic;
import static org.testng.Assert.assertNotNull;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -27,8 +28,6 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.management.internal.LocalManagementContext;
-
public class SingleMachineProvisioningLocationTest {
private static final Logger log = LoggerFactory.getLogger(SingleMachineProvisioningLocation.class);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java
index 1fef80b..6ba27e7 100644
--- a/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/basic/SshMachineLocationReuseIntegrationTest.java
@@ -34,8 +34,8 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.internal.ssh.SshTool;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/test/entity/LocalManagementContextForTests.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/test/entity/LocalManagementContextForTests.java b/core/src/test/java/org/apache/brooklyn/test/entity/LocalManagementContextForTests.java
index 775f1a3..808a054 100644
--- a/core/src/test/java/org/apache/brooklyn/test/entity/LocalManagementContextForTests.java
+++ b/core/src/test/java/org/apache/brooklyn/test/entity/LocalManagementContextForTests.java
@@ -18,11 +18,12 @@
*/
package org.apache.brooklyn.test.entity;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.ConfigKey;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
/** management context which allows disabling common time-consuming tasks.
* most instances have:
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BrooklynMementoPersisterJcloudsObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BrooklynMementoPersisterJcloudsObjectStoreTest.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BrooklynMementoPersisterJcloudsObjectStoreTest.java
index c720b41..0bf3330 100644
--- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BrooklynMementoPersisterJcloudsObjectStoreTest.java
+++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BrooklynMementoPersisterJcloudsObjectStoreTest.java
@@ -19,13 +19,13 @@
package brooklyn.entity.rebind.persister.jclouds;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.rebind.RebindTestUtils;
import brooklyn.entity.rebind.persister.BrooklynMementoPersisterTestFixture;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.text.Identifiers;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/EntityToBlobStorePersistencePerformanceTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/EntityToBlobStorePersistencePerformanceTest.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/EntityToBlobStorePersistencePerformanceTest.java
index 78c4545..1085b8b 100644
--- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/EntityToBlobStorePersistencePerformanceTest.java
+++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/EntityToBlobStorePersistencePerformanceTest.java
@@ -18,11 +18,11 @@
*/
package brooklyn.entity.rebind.persister.jclouds;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.qa.performance.EntityPersistencePerformanceTest;
public class EntityToBlobStorePersistencePerformanceTest extends EntityPersistencePerformanceTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/HighAvailabilityManagerJcloudsObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/HighAvailabilityManagerJcloudsObjectStoreTest.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/HighAvailabilityManagerJcloudsObjectStoreTest.java
index 92b7a44..3ac15df 100644
--- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/HighAvailabilityManagerJcloudsObjectStoreTest.java
+++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/HighAvailabilityManagerJcloudsObjectStoreTest.java
@@ -18,14 +18,14 @@
*/
package brooklyn.entity.rebind.persister.jclouds;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerTestFixture;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.management.ha.HighAvailabilityManagerTestFixture;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.text.Identifiers;
@Test(groups={"Live", "Live-sanity"})
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStoreTest.java b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStoreTest.java
index 647e514..0e0aa6c 100644
--- a/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStoreTest.java
+++ b/locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/JcloudsBlobStoreBasedObjectStoreTest.java
@@ -21,6 +21,7 @@ package brooklyn.entity.rebind.persister.jclouds;
import java.util.List;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
import brooklyn.entity.rebind.persister.PersistenceObjectStore;
import brooklyn.entity.rebind.persister.PersistenceObjectStore.StoreObjectAccessor;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableList;
import brooklyn.util.text.Identifiers;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java
index b5f4dab..92d5f18 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsLiveTest.java
@@ -33,8 +33,10 @@ import org.testng.annotations.BeforeMethod;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
+
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.management.internal.LocalManagementContext;
+
import brooklyn.util.exceptions.CompoundRuntimeException;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java
index 7892c8e..c323b7f 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BailOutJcloudsLocation.java
@@ -26,6 +26,7 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Template;
@@ -39,7 +40,6 @@ import com.google.common.reflect.TypeToken;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.CompoundRuntimeException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java
index 3fda145..e4286bc 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/BrooklynMachinePoolLiveTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.brooklyn.location.jclouds;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.jclouds.pool.MachineSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,11 +26,9 @@ import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-
import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.apache.brooklyn.location.jclouds.pool.MachinePoolPredicates;
import org.apache.brooklyn.location.jclouds.pool.ReusableMachineTemplate;
-import brooklyn.management.internal.LocalManagementContext;
public class BrooklynMachinePoolLiveTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java
index 2f708f3..4112f61 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverAwsLiveTest.java
@@ -28,9 +28,9 @@ import java.util.Set;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.basic.FixedListMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
+
import brooklyn.util.collections.MutableMap;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java
index 31831a8..1accbad 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverSoftlayerLiveTest.java
@@ -23,12 +23,12 @@ import static org.testng.Assert.assertTrue;
import java.util.Set;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.basic.FixedListMachineProvisioningLocation;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableMap;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java
index 3f7c837..0b5d1c6 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsByonLocationResolverTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.fail;
import java.util.NoSuchElementException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.basic.FixedListMachineProvisioningLocation;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.annotations.AfterMethod;
@@ -29,7 +30,6 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
public class JcloudsByonLocationResolverTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.java
index 3c3d4a5..186fa33 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationMetadataTest.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.location.jclouds;
import static org.testng.Assert.assertEquals;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -31,8 +32,6 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.basic.LocationConfigKeys;
-import brooklyn.management.internal.LocalManagementContext;
-
import com.google.common.collect.ImmutableSet;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolverTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolverTest.java
index 8cd20b9..02537fe 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolverTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolverTest.java
@@ -25,6 +25,7 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.basic.LocationInternal;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
@@ -38,7 +39,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.event.basic.MapConfigKey;
import brooklyn.event.basic.SetConfigKey;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java
index 100f98a..83ffb78 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsLocationTest.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
import org.apache.brooklyn.api.location.MachineLocationCustomizer;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.cloud.names.CustomMachineNamer;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.jclouds.scriptbuilder.domain.OsFamily;
@@ -58,7 +59,6 @@ import org.apache.brooklyn.location.basic.LocationConfigKeys;
import org.apache.brooklyn.location.geo.HostGeoInfo;
import org.apache.brooklyn.location.jclouds.JcloudsLocation.UserCreation;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.config.ConfigBag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java
index e3b749d..6043a09 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/RebindJcloudsLocationLiveTest.java
@@ -26,6 +26,7 @@ import java.io.File;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -34,7 +35,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.config.ConfigBag;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/provider/CarrenzaLocationLiveTest.groovy
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/provider/CarrenzaLocationLiveTest.groovy b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/provider/CarrenzaLocationLiveTest.groovy
index 3c23328..9e1e1e9 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/provider/CarrenzaLocationLiveTest.groovy
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/provider/CarrenzaLocationLiveTest.groovy
@@ -30,7 +30,7 @@ import brooklyn.config.BrooklynProperties
import org.apache.brooklyn.location.basic.SshMachineLocation
import org.apache.brooklyn.location.jclouds.JcloudsLocation
import org.apache.brooklyn.location.jclouds.JcloudsSshMachineLocation
-import brooklyn.management.internal.LocalManagementContext
+import org.apache.brooklyn.core.management.internal.LocalManagementContext
import brooklyn.util.collections.MutableMap
import com.google.common.collect.ImmutableList
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtensionTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtensionTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtensionTest.java
index 84c90ab..cf372d0 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtensionTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/zone/AwsAvailabilityZoneExtensionTest.java
@@ -24,6 +24,7 @@ import static org.testng.Assert.assertTrue;
import java.util.List;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.jclouds.AbstractJcloudsLiveTest;
import org.apache.brooklyn.location.jclouds.JcloudsLocation;
import org.jclouds.domain.LocationScope;
@@ -35,8 +36,6 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.jclouds.JcloudsSshMachineLocation;
-import brooklyn.management.internal.LocalManagementContext;
-
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java
----------------------------------------------------------------------
diff --git a/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java b/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java
index f3de4dd..93ece4a 100644
--- a/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java
+++ b/policy/src/main/java/brooklyn/entity/brooklyn/BrooklynMetricsImpl.java
@@ -24,10 +24,10 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalSubscriptionManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.management.internal.LocalSubscriptionManager;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.task.BasicExecutionManager;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/policy/src/test/java/brooklyn/enricher/DeltaEnrichersTests.groovy
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/enricher/DeltaEnrichersTests.groovy b/policy/src/test/java/brooklyn/enricher/DeltaEnrichersTests.groovy
index 406fc27..e0419f7 100644
--- a/policy/src/test/java/brooklyn/enricher/DeltaEnrichersTests.groovy
+++ b/policy/src/test/java/brooklyn/enricher/DeltaEnrichersTests.groovy
@@ -31,7 +31,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal
import org.apache.brooklyn.api.event.Sensor
import brooklyn.event.basic.BasicAttributeSensor
import org.apache.brooklyn.api.management.SubscriptionContext
-import brooklyn.management.internal.LocalManagementContext
+import org.apache.brooklyn.core.management.internal.LocalManagementContext
class DeltaEnrichersTests {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/entity/AbstractGoogleComputeLiveTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/AbstractGoogleComputeLiveTest.java b/software/base/src/test/java/brooklyn/entity/AbstractGoogleComputeLiveTest.java
index ecc4adc..b3d9c10 100644
--- a/software/base/src/test/java/brooklyn/entity/AbstractGoogleComputeLiveTest.java
+++ b/software/base/src/test/java/brooklyn/entity/AbstractGoogleComputeLiveTest.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -31,7 +32,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableMap;
import com.google.common.base.CaseFormat;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/entity/AbstractSoftlayerLiveTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/AbstractSoftlayerLiveTest.java b/software/base/src/test/java/brooklyn/entity/AbstractSoftlayerLiveTest.java
index a8f15f5..46f0d6a 100644
--- a/software/base/src/test/java/brooklyn/entity/AbstractSoftlayerLiveTest.java
+++ b/software/base/src/test/java/brooklyn/entity/AbstractSoftlayerLiveTest.java
@@ -23,6 +23,7 @@ import java.util.Map;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -35,7 +36,6 @@ import com.google.common.collect.ImmutableMap;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.text.StringShortener;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java
index 485b287..f528f7c 100644
--- a/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java
+++ b/software/base/src/test/java/brooklyn/entity/basic/SoftwareProcessSshDriverIntegrationTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
@@ -44,7 +45,6 @@ import brooklyn.entity.trait.Startable;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.BrooklynNetworkUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java b/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java
index 41ec5c5..dd2b9b0 100644
--- a/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java
+++ b/software/base/src/test/java/brooklyn/entity/java/VanillaJavaAppRebindTest.java
@@ -24,6 +24,7 @@ import java.io.File;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
@@ -38,8 +39,9 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.java.JavaOptsTest.TestingJavaOptsVanillaJavaAppImpl;
import brooklyn.entity.rebind.RebindTestUtils;
import brooklyn.event.basic.Sensors;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
+
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/entity/pool/ServerPoolLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/pool/ServerPoolLocationResolverTest.java b/software/base/src/test/java/brooklyn/entity/pool/ServerPoolLocationResolverTest.java
index e6c3ab6..55b1df7 100644
--- a/software/base/src/test/java/brooklyn/entity/pool/ServerPoolLocationResolverTest.java
+++ b/software/base/src/test/java/brooklyn/entity/pool/ServerPoolLocationResolverTest.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.Assert;
@@ -43,7 +44,6 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.dynamic.DynamicLocation;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableMap;
public class ServerPoolLocationResolverTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/entity/pool/ServerPoolRebindTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/pool/ServerPoolRebindTest.java b/software/base/src/test/java/brooklyn/entity/pool/ServerPoolRebindTest.java
index f24ae5f..d47a5bb 100644
--- a/software/base/src/test/java/brooklyn/entity/pool/ServerPoolRebindTest.java
+++ b/software/base/src/test/java/brooklyn/entity/pool/ServerPoolRebindTest.java
@@ -27,6 +27,7 @@ import java.util.Collection;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,7 +37,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.rebind.RebindOptions;
import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.management.internal.LocalManagementContext;
import com.google.common.base.Optional;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/entity/software/AbstractDockerLiveTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/entity/software/AbstractDockerLiveTest.java b/software/base/src/test/java/brooklyn/entity/software/AbstractDockerLiveTest.java
index c0bf566..654597b 100644
--- a/software/base/src/test/java/brooklyn/entity/software/AbstractDockerLiveTest.java
+++ b/software/base/src/test/java/brooklyn/entity/software/AbstractDockerLiveTest.java
@@ -21,7 +21,6 @@ package brooklyn.entity.software;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableMap;
import com.google.common.base.CaseFormat;
@@ -30,6 +29,7 @@ import com.google.common.collect.ImmutableMap;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/management/usage/ApplicationUsageTrackingTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/management/usage/ApplicationUsageTrackingTest.java b/software/base/src/test/java/brooklyn/management/usage/ApplicationUsageTrackingTest.java
index 4d032df..6fbbb98 100644
--- a/software/base/src/test/java/brooklyn/management/usage/ApplicationUsageTrackingTest.java
+++ b/software/base/src/test/java/brooklyn/management/usage/ApplicationUsageTrackingTest.java
@@ -30,6 +30,10 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.UsageListener.ApplicationMetadata;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage.ApplicationEvent;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
@@ -41,9 +45,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.proxying.EntityProxy;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.UsageListener.ApplicationMetadata;
-import brooklyn.management.usage.ApplicationUsage.ApplicationEvent;
import brooklyn.test.Asserts;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/management/usage/LocationUsageTrackingTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/management/usage/LocationUsageTrackingTest.java b/software/base/src/test/java/brooklyn/management/usage/LocationUsageTrackingTest.java
index 61032c4..82ff588 100644
--- a/software/base/src/test/java/brooklyn/management/usage/LocationUsageTrackingTest.java
+++ b/software/base/src/test/java/brooklyn/management/usage/LocationUsageTrackingTest.java
@@ -31,6 +31,9 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.core.management.internal.UsageListener.LocationMetadata;
+import org.apache.brooklyn.core.management.usage.LocationUsage;
+import org.apache.brooklyn.core.management.usage.LocationUsage.LocationEvent;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -41,8 +44,6 @@ import brooklyn.entity.basic.SoftwareProcessEntityTest;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.management.internal.UsageListener.LocationMetadata;
-import brooklyn.management.usage.LocationUsage.LocationEvent;
import brooklyn.test.Asserts;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/management/usage/RecordingLegacyUsageListener.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/management/usage/RecordingLegacyUsageListener.java b/software/base/src/test/java/brooklyn/management/usage/RecordingLegacyUsageListener.java
index c270ac5..4ac1631 100644
--- a/software/base/src/test/java/brooklyn/management/usage/RecordingLegacyUsageListener.java
+++ b/software/base/src/test/java/brooklyn/management/usage/RecordingLegacyUsageListener.java
@@ -21,15 +21,16 @@ package brooklyn.management.usage;
import java.util.List;
import java.util.Map;
-import brooklyn.management.usage.ApplicationUsage.ApplicationEvent;
-import brooklyn.management.usage.LocationUsage.LocationEvent;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage.ApplicationEvent;
+import org.apache.brooklyn.core.management.usage.LocationUsage.LocationEvent;
+
import brooklyn.util.collections.MutableList;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@Deprecated
-public class RecordingLegacyUsageListener implements brooklyn.management.internal.UsageManager.UsageListener {
+public class RecordingLegacyUsageListener implements org.apache.brooklyn.core.management.internal.UsageManager.UsageListener {
private final List<List<?>> events = Lists.newCopyOnWriteArrayList();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/management/usage/RecordingUsageListener.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/management/usage/RecordingUsageListener.java b/software/base/src/test/java/brooklyn/management/usage/RecordingUsageListener.java
index bf26c5c..e5868a8 100644
--- a/software/base/src/test/java/brooklyn/management/usage/RecordingUsageListener.java
+++ b/software/base/src/test/java/brooklyn/management/usage/RecordingUsageListener.java
@@ -20,14 +20,15 @@ package brooklyn.management.usage;
import java.util.List;
-import brooklyn.management.usage.ApplicationUsage.ApplicationEvent;
-import brooklyn.management.usage.LocationUsage.LocationEvent;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage.ApplicationEvent;
+import org.apache.brooklyn.core.management.usage.LocationUsage.LocationEvent;
+
import brooklyn.util.collections.MutableList;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
-public class RecordingUsageListener implements brooklyn.management.internal.UsageListener {
+public class RecordingUsageListener implements org.apache.brooklyn.core.management.internal.UsageListener {
private final List<List<?>> events = Lists.newCopyOnWriteArrayList();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.java b/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.java
index 863f587..a143558 100644
--- a/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.java
+++ b/software/base/src/test/java/brooklyn/management/usage/UsageListenerTest.java
@@ -34,9 +34,9 @@ import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.UsageManager;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.UsageManager;
import brooklyn.test.Asserts;
import com.google.common.collect.ImmutableList;
@@ -107,7 +107,7 @@ public class UsageListenerTest {
}});
}
- public static class RecordingStaticLegacyUsageListener extends RecordingLegacyUsageListener implements brooklyn.management.internal.UsageManager.UsageListener {
+ public static class RecordingStaticLegacyUsageListener extends RecordingLegacyUsageListener implements org.apache.brooklyn.core.management.internal.UsageManager.UsageListener {
private static final List<RecordingStaticLegacyUsageListener> STATIC_INSTANCES = Lists.newCopyOnWriteArrayList();
public static RecordingStaticLegacyUsageListener getInstance() {
@@ -125,7 +125,7 @@ public class UsageListenerTest {
}
}
- public static class RecordingStaticUsageListener extends RecordingUsageListener implements brooklyn.management.internal.UsageListener {
+ public static class RecordingStaticUsageListener extends RecordingUsageListener implements org.apache.brooklyn.core.management.internal.UsageListener {
private static final List<RecordingStaticUsageListener> STATIC_INSTANCES = Lists.newCopyOnWriteArrayList();
public static RecordingStaticUsageListener getInstance() {
[07/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/WarmStandbyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/WarmStandbyTest.java b/core/src/test/java/brooklyn/management/ha/WarmStandbyTest.java
deleted file mode 100644
index 54f4b8b..0000000
--- a/core/src/test/java/brooklyn/management/ha/WarmStandbyTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
-import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
-import brooklyn.entity.rebind.persister.InMemoryObjectStore;
-import brooklyn.entity.rebind.persister.ListeningObjectStore;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.time.Duration;
-
-@Test
-public class WarmStandbyTest {
-
- private static final Logger log = LoggerFactory.getLogger(WarmStandbyTest.class);
-
- private List<HaMgmtNode> nodes = new MutableList<WarmStandbyTest.HaMgmtNode>();
- Map<String,String> sharedBackingStore = MutableMap.of();
- Map<String,Date> sharedBackingStoreDates = MutableMap.of();
- private ClassLoader classLoader = getClass().getClassLoader();
-
- public class HaMgmtNode {
- // TODO share with HotStandbyTest and SplitBrainTest and a few others (minor differences but worth it ultimately)
-
- private ManagementContextInternal mgmt;
- private String ownNodeId;
- private String nodeName;
- private ListeningObjectStore objectStore;
- private ManagementPlaneSyncRecordPersister persister;
- private HighAvailabilityManagerImpl ha;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- nodeName = "node "+nodes.size();
- mgmt = newLocalManagementContext();
- ownNodeId = mgmt.getManagementNodeId();
- objectStore = new ListeningObjectStore(newPersistenceObjectStore());
- objectStore.injectManagementContext(mgmt);
- objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
- persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
- ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
- BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
- mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
- ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())
- .setPollPeriod(Duration.PRACTICALLY_FOREVER)
- .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
- .setPersister(persister);
- log.info("Created "+nodeName+" "+ownNodeId);
- }
-
- public void tearDown() throws Exception {
- if (ha != null) ha.stop();
- if (mgmt != null) Entities.destroyAll(mgmt);
- if (objectStore != null) objectStore.deleteCompletely();
- }
-
- @Override
- public String toString() {
- return nodeName+" "+ownNodeId;
- }
- }
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- nodes.clear();
- sharedBackingStore.clear();
- }
-
- public HaMgmtNode newNode() throws Exception {
- HaMgmtNode node = new HaMgmtNode();
- node.setUp();
- nodes.add(node);
- return node;
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- for (HaMgmtNode n: nodes)
- n.tearDown();
- }
-
- protected ManagementContextInternal newLocalManagementContext() {
- return new LocalManagementContextForTests();
- }
-
- protected PersistenceObjectStore newPersistenceObjectStore() {
- return new InMemoryObjectStore(sharedBackingStore, sharedBackingStoreDates);
- }
-
- // TODO refactor above -- routines above this line are shared among HotStandbyTest and SplitBrainTest
-
- @Test
- public void testWarmStandby() throws Exception {
- HaMgmtNode n1 = newNode();
- n1.ha.start(HighAvailabilityMode.AUTO);
- assertEquals(n1.ha.getNodeState(), ManagementNodeState.MASTER);
-
- TestApplication app = TestApplication.Factory.newManagedInstanceForTests(n1.mgmt);
- app.start(MutableList.<Location>of());
-
- n1.mgmt.getRebindManager().forcePersistNow(false, null);
-
- HaMgmtNode n2 = newNode();
- n2.ha.start(HighAvailabilityMode.STANDBY);
- assertEquals(n2.ha.getNodeState(), ManagementNodeState.STANDBY);
-
- assertEquals(n2.mgmt.getApplications().size(), 0);
- }
-
- // TODO support forcible demotion, and check that a master forcibly demoted
- // to warm standby clears its apps, policies, and locations
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/internal/AccessManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/internal/AccessManagerTest.java b/core/src/test/java/brooklyn/management/internal/AccessManagerTest.java
deleted file mode 100644
index 34f733c..0000000
--- a/core/src/test/java/brooklyn/management/internal/AccessManagerTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.apache.brooklyn.test.entity.TestEntity;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.Entities;
-
-import org.apache.brooklyn.location.basic.SimulatedLocation;
-
-import brooklyn.util.exceptions.Exceptions;
-
-import com.google.common.collect.ImmutableSet;
-
-public class AccessManagerTest {
-
- private LocalManagementContext managementContext;
- private TestApplication app;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- managementContext = new LocalManagementContextForTests();
- app = ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (managementContext != null) Entities.destroyAll(managementContext);
- app = null;
- }
-
- @Test
- public void testEntityManagementAllowed() throws Exception {
- // default is allowed
- TestEntity e1 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- // when forbidden, should give error trying to create+manage new entity
- managementContext.getAccessManager().setEntityManagementAllowed(false);
- try {
- app.createAndManageChild(EntitySpec.create(TestEntity.class));
- fail();
- } catch (Exception e) {
- // expect it to be forbidden
- if (Exceptions.getFirstThrowableOfType(e, IllegalStateException.class) == null) {
- throw e;
- }
- }
-
- // when forbidden, should refuse to create new app
- try {
- ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
- fail();
- } catch (Exception e) {
- // expect it to be forbidden
- if (Exceptions.getFirstThrowableOfType(e, IllegalStateException.class) == null) {
- throw e;
- }
- }
-
- // but when forbidden, still allowed to create locations
- managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
-
- // when re-enabled, can create entities again
- managementContext.getAccessManager().setEntityManagementAllowed(true);
- TestEntity e3 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- assertEquals(ImmutableSet.copyOf(managementContext.getEntityManager().getEntities()), ImmutableSet.of(app, e1, e3));
- }
-
- @Test
- public void testLocationManagementAllowed() throws Exception {
- // default is allowed
- Location loc1 = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
-
- // when forbidden, should give error
- managementContext.getAccessManager().setLocationManagementAllowed(false);
- try {
- managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
- fail();
- } catch (Exception e) {
- // expect it to be forbidden
- if (Exceptions.getFirstThrowableOfType(e, IllegalStateException.class) == null) {
- throw e;
- }
- }
-
- // but when forbidden, still allowed to create entity
- ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
-
- // when re-enabled, can create entities again
- managementContext.getAccessManager().setLocationManagementAllowed(true);
- Location loc3 = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
-
- assertEquals(ImmutableSet.copyOf(managementContext.getLocationManager().getLocations()), ImmutableSet.of(loc1, loc3));
- }
-
- @Test
- public void testLocationProvisioningAllowed() throws Exception {
- SimulatedLocation loc = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
-
- // default is allowed
- assertTrue(managementContext.getAccessController().canProvisionLocation(loc).isAllowed());
-
- // when forbidden, should say so
- managementContext.getAccessManager().setLocationProvisioningAllowed(false);
- assertFalse(managementContext.getAccessController().canProvisionLocation(loc).isAllowed());
-
- // but when forbidden, still allowed to create locations
- managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
-
- // when re-enabled, can create entities again
- managementContext.getAccessManager().setLocationProvisioningAllowed(true);
- assertTrue(managementContext.getAccessController().canProvisionLocation(loc).isAllowed());
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/internal/EntityExecutionManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/internal/EntityExecutionManagerTest.java b/core/src/test/java/brooklyn/management/internal/EntityExecutionManagerTest.java
deleted file mode 100644
index d8cb07a..0000000
--- a/core/src/test/java/brooklyn/management/internal/EntityExecutionManagerTest.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Semaphore;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.apache.brooklyn.test.entity.TestEntity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.BrooklynTaskTags.WrappedEntity;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.event.basic.BasicAttributeSensor;
-import brooklyn.test.Asserts;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.repeat.Repeater;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.ExecutionListener;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.Callables;
-
-/** Includes many tests for {@link BrooklynGarbageCollector} */
-public class EntityExecutionManagerTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(EntityExecutionManagerTest.class);
-
- private static final Duration TIMEOUT_MS = Duration.TEN_SECONDS;
-
- private ManagementContextInternal mgmt;
- private TestApplication app;
- private TestEntity e;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (app != null) Entities.destroyAll(app.getManagementContext());
- app = null;
- if (mgmt != null) Entities.destroyAll(mgmt);
- }
-
- @Test
- public void testOnDoneCallback() throws InterruptedException {
- mgmt = LocalManagementContextForTests.newInstance();
- ExecutionManager em = mgmt.getExecutionManager();
- BasicExecutionManager bem = (BasicExecutionManager)em;
- final Map<Task<?>,Duration> completedTasks = MutableMap.of();
- final Semaphore sema4 = new Semaphore(-1);
- bem.addListener(new ExecutionListener() {
- @Override
- public void onTaskDone(Task<?> task) {
- Assert.assertTrue(task.isDone());
- Assert.assertEquals(task.getUnchecked(), "foo");
- completedTasks.put(task, Duration.sinceUtc(task.getEndTimeUtc()));
- sema4.release();
- }
- });
- Task<String> t1 = em.submit( Tasks.<String>builder().name("t1").dynamic(false).body(Callables.returning("foo")).build() );
- t1.getUnchecked();
- Task<String> t2 = em.submit( Tasks.<String>builder().name("t2").dynamic(false).body(Callables.returning("foo")).build() );
- sema4.acquire();
- Assert.assertEquals(completedTasks.size(), 2, "completed tasks are: "+completedTasks);
- completedTasks.get(t1).isShorterThan(Duration.TEN_SECONDS);
- completedTasks.get(t2).isShorterThan(Duration.TEN_SECONDS);
- }
-
- protected void forceGc() {
- ((LocalManagementContext)app.getManagementContext()).getGarbageCollector().gcIteration();
- }
-
- protected static Task<?> runEmptyTaskWithNameAndTags(Entity target, String name, Object ...tags) {
- TaskBuilder<Object> tb = newEmptyTask(name);
- for (Object tag: tags) tb.tag(tag);
- Task<?> task = ((EntityInternal)target).getExecutionContext().submit(tb.build());
- task.getUnchecked();
- return task;
- }
-
- protected static TaskBuilder<Object> newEmptyTask(String name) {
- return Tasks.builder().name(name).dynamic(false).body(Callables.returning(null));
- }
-
- protected void assertTaskCountForEntitySoon(final Entity entity, final int expectedCount) {
- // Dead task (and initialization task) should have been GC'd on completion.
- // However, the GC'ing happens in a listener, executed in a different thread - the task.get()
- // doesn't block for it. Therefore can't always guarantee it will be GC'ed by now.
- Repeater.create().backoff(Duration.millis(10), 2, Duration.millis(500)).limitTimeTo(Duration.TEN_SECONDS).until(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- forceGc();
- Collection<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(((EntityInternal)entity).getManagementContext().getExecutionManager(), entity);
- Assert.assertEquals(tasks.size(), expectedCount, "Tasks were "+tasks);
- return true;
- }
- }).runRequiringTrue();
- }
-
- @Test
- public void testGetTasksAndGcBoringTags() throws Exception {
- app = TestApplication.Factory.newManagedInstanceForTests();
- e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- final Task<?> task = runEmptyTaskWithNameAndTags(e, "should-be-kept", ManagementContextInternal.NON_TRANSIENT_TASK_TAG);
- runEmptyTaskWithNameAndTags(e, "should-be-gcd", ManagementContextInternal.TRANSIENT_TASK_TAG);
-
- assertTaskCountForEntitySoon(e, 1);
- Collection<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(app.getManagementContext().getExecutionManager(), e);
- assertEquals(tasks, ImmutableList.of(task), "Mismatched tasks, got: "+tasks);
- }
-
- @Test
- public void testGcTaskAtNormalTagLimit() throws Exception {
- app = TestApplication.Factory.newManagedInstanceForTests();
- e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- ((BrooklynProperties)app.getManagementContext().getConfig()).put(
- BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
-
- for (int count=0; count<5; count++)
- runEmptyTaskWithNameAndTags(e, "task"+count, ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
-
- assertTaskCountForEntitySoon(e, 2);
- }
-
- @Test
- public void testGcTaskAtEntityLimit() throws Exception {
- app = TestApplication.Factory.newManagedInstanceForTests();
- e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- ((BrooklynProperties)app.getManagementContext().getConfig()).put(
- BrooklynGarbageCollector.MAX_TASKS_PER_ENTITY, 2);
-
- for (int count=0; count<5; count++)
- runEmptyTaskWithNameAndTags(e, "task-e-"+count, ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
- for (int count=0; count<5; count++)
- runEmptyTaskWithNameAndTags(app, "task-app-"+count, ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
-
- assertTaskCountForEntitySoon(app, 2);
- assertTaskCountForEntitySoon(e, 2);
- }
-
- @Test
- public void testGcTaskWithTagAndEntityLimit() throws Exception {
- app = TestApplication.Factory.newManagedInstanceForTests();
- e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- ((BrooklynProperties)app.getManagementContext().getConfig()).put(
- BrooklynGarbageCollector.MAX_TASKS_PER_ENTITY, 6);
- ((BrooklynProperties)app.getManagementContext().getConfig()).put(
- BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
-
- int count=0;
-
- runEmptyTaskWithNameAndTags(app, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
- runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
- Time.sleep(Duration.ONE_MILLISECOND);
- // should keep the 2 below, because all the other borings get grace, but delete the ones above
- runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
- runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
-
- runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag", "another-tag-e");
- runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag", "another-tag-e");
- // should keep both the above
-
- runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag");
- runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag");
- Time.sleep(Duration.ONE_MILLISECOND);
- runEmptyTaskWithNameAndTags(app, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag");
- // should keep the below since they have unique tags, but remove one of the e tasks above
- runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag", "and-another-tag");
- runEmptyTaskWithNameAndTags(app, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag-app", "another-tag");
- runEmptyTaskWithNameAndTags(app, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag-app", "another-tag");
-
- assertTaskCountForEntitySoon(e, 6);
- assertTaskCountForEntitySoon(app, 3);
-
- // now with a lowered limit, we should remove one more e
- ((BrooklynProperties)app.getManagementContext().getConfig()).put(
- BrooklynGarbageCollector.MAX_TASKS_PER_ENTITY, 5);
- assertTaskCountForEntitySoon(e, 5);
- }
-
- @Test
- public void testGcDynamicTaskAtNormalTagLimit() throws Exception {
- app = TestApplication.Factory.newManagedInstanceForTests();
- e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- ((BrooklynProperties)app.getManagementContext().getConfig()).put(
- BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
-
- for (int count=0; count<5; count++) {
- TaskBuilder<Object> tb = Tasks.builder().name("task-"+count).dynamic(true).body(new Runnable() { @Override public void run() {}})
- .tag(ManagementContextInternal.NON_TRANSIENT_TASK_TAG).tag("foo");
- ((EntityInternal)e).getExecutionContext().submit(tb.build()).getUnchecked();
- }
-
- // might need an eventually here, if the internal job completion and GC is done in the background
- // (if there are no test failures for a few months, since Sept 2014, then we can remove this comment)
- assertTaskCountForEntitySoon(e, 2);
- }
-
- @Test
- public void testUnmanagedEntityCanBeGcedEvenIfPreviouslyTagged() throws Exception {
- app = TestApplication.Factory.newManagedInstanceForTests();
- e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- String eId = e.getId();
-
- e.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of()).get();
- Set<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(app.getManagementContext().getExecutionManager(), e);
- Task<?> task = Iterables.get(tasks, 0);
- assertTrue(task.getTags().contains(BrooklynTaskTags.tagForContextEntity(e)));
-
- Set<Object> tags = app.getManagementContext().getExecutionManager().getTaskTags();
- assertTrue(tags.contains(BrooklynTaskTags.tagForContextEntity(e)), "tags="+tags);
-
- Entities.destroy(e);
- forceGc();
-
- Set<Object> tags2 = app.getManagementContext().getExecutionManager().getTaskTags();
- for (Object tag : tags2) {
- if (tag instanceof Entity && ((Entity)tag).getId().equals(eId)) {
- fail("tags contains unmanaged entity "+tag);
- }
- if ((tag instanceof WrappedEntity) && ((WrappedEntity)tag).entity.getId().equals(eId)
- && ((WrappedEntity)tag).wrappingType.equals(BrooklynTaskTags.CONTEXT_ENTITY)) {
- fail("tags contains unmanaged entity (wrapped) "+tag);
- }
- }
- return;
- }
-
- @Test(groups="Integration")
- public void testSubscriptionAndEffectorTasksGced() throws Exception {
- app = TestApplication.Factory.newManagedInstanceForTests();
- BasicExecutionManager em = (BasicExecutionManager) app.getManagementContext().getExecutionManager();
- // allow background enrichers to complete
- Time.sleep(Duration.ONE_SECOND);
- forceGc();
- List<Task<?>> t1 = em.getAllTasks();
-
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- entity.setAttribute(TestEntity.NAME, "bob");
- entity.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of()).get();
- Entities.destroy(entity);
- Time.sleep(Duration.ONE_SECOND);
- forceGc();
- List<Task<?>> t2 = em.getAllTasks();
-
- Assert.assertEquals(t1.size(), t2.size(), "lists are different:\n"+t1+"\n"+t2+"\n");
- }
-
- /**
- * Invoke effector many times, where each would claim 10MB because it stores the return value.
- * If it didn't gc the tasks promptly, it would consume 10GB ram (so would OOME before that).
- */
- @Test(groups="Integration")
- public void testEffectorTasksGcedSoNoOome() throws Exception {
-
- BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
- brooklynProperties.put(BrooklynGarbageCollector.GC_PERIOD, Duration.ONE_MILLISECOND);
- brooklynProperties.put(BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
-
- app = ApplicationBuilder.newManagedApp(TestApplication.class, LocalManagementContextForTests.newInstance(brooklynProperties));
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- for (int i = 0; i < 1000; i++) {
- if (i%100==0) LOG.info(JavaClassNames.niceClassAndMethod()+": iteration "+i);
- try {
- LOG.debug("testEffectorTasksGced: iteration="+i);
- entity.invoke(TestEntity.IDENTITY_EFFECTOR, ImmutableMap.of("arg", new BigObject(10*1000*1000))).get();
-
- Time.sleep(Duration.ONE_MILLISECOND); // Give GC thread a chance to run
- forceGc();
- } catch (OutOfMemoryError e) {
- LOG.warn(JavaClassNames.niceClassAndMethod()+": OOME at iteration="+i);
- throw e;
- }
- }
- }
-
- @Test(groups="Integration")
- public void testUnmanagedEntityGcedOnUnmanageEvenIfEffectorInvoked() throws Exception {
- app = TestApplication.Factory.newManagedInstanceForTests();
-
- BasicAttributeSensor<Object> byteArrayAttrib = new BasicAttributeSensor<Object>(Object.class, "test.byteArray", "");
-
- for (int i = 0; i < 1000; i++) {
- if (i<100 && i%10==0 || i%100==0) LOG.info(JavaClassNames.niceClassAndMethod()+": iteration "+i);
- try {
- LOG.debug(JavaClassNames.niceClassAndMethod()+": iteration="+i);
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- entity.setAttribute(byteArrayAttrib, new BigObject(10*1000*1000));
- entity.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of()).get();
-
- // we get exceptions because tasks are still trying to publish after deployment;
- // this should prevent them
-// ((LocalEntityManager)app.getManagementContext().getEntityManager()).stopTasks(entity, Duration.ONE_SECOND);
-// Entities.destroy(entity);
-
- // alternatively if we 'unmanage' instead of destroy, there are usually not errors
- // (the errors come from the node transitioning to a 'stopping' state on destroy,
- // and publishing lots of info then)
- Entities.unmanage(entity);
-
- forceGc();
- // previously we did an extra GC but it was crazy slow, shouldn't be needed
-// System.gc(); System.gc();
- } catch (OutOfMemoryError e) {
- LOG.warn(JavaClassNames.niceClassAndMethod()+": OOME at iteration="+i);
- ExecutionManager em = app.getManagementContext().getExecutionManager();
- Collection<Task<?>> tasks = ((BasicExecutionManager)em).getAllTasks();
- LOG.info("TASKS count "+tasks.size()+": "+tasks);
- throw e;
- }
- }
- }
-
- @Test(groups={"Integration"})
- public void testEffectorTasksGcedForMaxPerTag() throws Exception {
- int maxNumTasks = 2;
- BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
- brooklynProperties.put(BrooklynGarbageCollector.GC_PERIOD, Duration.ONE_SECOND);
- brooklynProperties.put(BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
-
- app = ApplicationBuilder.newManagedApp(TestApplication.class, LocalManagementContextForTests.newInstance(brooklynProperties));
- final TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- List<Task<?>> tasks = Lists.newArrayList();
-
- for (int i = 0; i < (maxNumTasks+1); i++) {
- Task<?> task = entity.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of());
- task.get();
- tasks.add(task);
-
- // TASKS_OLDEST_FIRST_COMPARATOR is based on comparing EndTimeUtc; but two tasks executed in
- // rapid succession could finish in same millisecond
- // (especially when using System.currentTimeMillis, which can return the same time for several millisconds).
- Thread.sleep(10);
- }
-
- // Should initially have all tasks
- Set<Task<?>> storedTasks = app.getManagementContext().getExecutionManager().getTasksWithAllTags(
- ImmutableList.of(BrooklynTaskTags.tagForContextEntity(entity), ManagementContextInternal.EFFECTOR_TAG));
- assertEquals(storedTasks, ImmutableSet.copyOf(tasks), "storedTasks="+storedTasks+"; expected="+tasks);
-
- // Then oldest should be GC'ed to leave only maxNumTasks
- final List<Task<?>> recentTasks = tasks.subList(tasks.size()-maxNumTasks, tasks.size());
- Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new Runnable() {
- @Override public void run() {
- Set<Task<?>> storedTasks2 = app.getManagementContext().getExecutionManager().getTasksWithAllTags(
- ImmutableList.of(BrooklynTaskTags.tagForContextEntity(entity), ManagementContextInternal.EFFECTOR_TAG));
- List<String> storedTasks2Str = FluentIterable
- .from(storedTasks2)
- .transform(new Function<Task<?>, String>() {
- @Override public String apply(Task<?> input) {
- return taskToVerboseString(input);
- }})
- .toList();
- assertEquals(storedTasks2, ImmutableSet.copyOf(recentTasks), "storedTasks="+storedTasks2Str+"; expected="+recentTasks);
- }});
- }
-
- private String taskToVerboseString(Task t) {
- return Objects.toStringHelper(t)
- .add("id", t.getId())
- .add("displayName", t.getDisplayName())
- .add("submitTime", t.getSubmitTimeUtc())
- .add("startTime", t.getStartTimeUtc())
- .add("endTime", t.getEndTimeUtc())
- .add("status", t.getStatusSummary())
- .add("tags", t.getTags())
- .toString();
- }
- //2014-10-22 17:48:32,359 INFO TESTNG FAILED: "Surefire test" - brooklyn.management.internal.EntityExecutionManagerTest.testEffectorTasksGcedForMaxPerTag() finished in 10020 ms
- //java.lang.AssertionError: storedTasks=[Task[myEffector:dmCJkiM9], Task[myEffector:R2hPTpNL]]; expected=[Task[myEffector:Z9wTQ8We], Task[myEffector:R2hPTpNL]]
- // expected [[Task[myEffector:Z9wTQ8We], Task[myEffector:R2hPTpNL]]]
- // but found [[Task[myEffector:dmCJkiM9], Task[myEffector:R2hPTpNL]]]
-
- @Test(groups="Integration")
- public void testEffectorTasksGcedForAge() throws Exception {
- Duration maxTaskAge = Duration.millis(100);
- Duration maxOverhead = Duration.millis(250);
- Duration earlyReturnGrace = Duration.millis(10);
- BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
- brooklynProperties.put(BrooklynGarbageCollector.GC_PERIOD, Duration.ONE_MILLISECOND);
- brooklynProperties.put(BrooklynGarbageCollector.MAX_TASK_AGE, maxTaskAge);
-
- app = ApplicationBuilder.newManagedApp(TestApplication.class, LocalManagementContextForTests.newInstance(brooklynProperties));
- final TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- Stopwatch stopwatch = Stopwatch.createStarted();
- Task<?> oldTask = entity.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of());
- oldTask.get();
-
- Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new Runnable() {
- @Override public void run() {
- Set<Task<?>> storedTasks = app.getManagementContext().getExecutionManager().getTasksWithAllTags(ImmutableList.of(
- BrooklynTaskTags.tagForTargetEntity(entity),
- ManagementContextInternal.EFFECTOR_TAG));
- assertEquals(storedTasks, ImmutableSet.of(), "storedTasks="+storedTasks);
- }});
-
- Duration timeToGc = Duration.of(stopwatch);
- assertTrue(timeToGc.isLongerThan(maxTaskAge.subtract(earlyReturnGrace)), "timeToGc="+timeToGc+"; maxTaskAge="+maxTaskAge);
- assertTrue(timeToGc.isShorterThan(maxTaskAge.add(maxOverhead)), "timeToGc="+timeToGc+"; maxTaskAge="+maxTaskAge);
- }
-
- private static class BigObject implements Serializable {
- private static final long serialVersionUID = -4021304829674972215L;
- private final int sizeBytes;
- private final byte[] data;
-
- BigObject(int sizeBytes) {
- this.sizeBytes = sizeBytes;
- this.data = new byte[sizeBytes];
- }
-
- @Override
- public String toString() {
- return "BigObject["+sizeBytes+"/"+data.length+"]";
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/internal/LocalManagementContextInstancesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/internal/LocalManagementContextInstancesTest.java b/core/src/test/java/brooklyn/management/internal/LocalManagementContextInstancesTest.java
deleted file mode 100644
index 0e07b94..0000000
--- a/core/src/test/java/brooklyn/management/internal/LocalManagementContextInstancesTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Tests the {@link LocalManagementContext#terminateAll()} and {@link LocalManagementContext#getInstances()} behaviour.
- * Note this test must NEVER be run in parallel with other tests, as it will terminate the ManagementContext of those
- * other tests.
- *
- * @author pveentjer
- */
-public class LocalManagementContextInstancesTest {
-
- @AfterMethod(alwaysRun = true)
- public void tearDown(){
- LocalManagementContext.terminateAll();
- }
-
- /** WIP group because other threads may be running in background,
- * creating management contexts at the same time as us (slim chance, but observed once);
- * they shouldn't be, but cleaning that up is another matter! */
- @Test(groups="WIP")
- public void testGetInstances(){
- LocalManagementContext.terminateAll();
- LocalManagementContext context1 = new LocalManagementContext();
- LocalManagementContext context2 = new LocalManagementContext();
- LocalManagementContext context3 = new LocalManagementContext();
-
- assertEquals(LocalManagementContext.getInstances(), ImmutableSet.of(context1, context2, context3));
- }
-
- /** WIP group because other threads may be running in background;
- * they shouldn't be, but cleaning that up is another matter! */
- @Test
- public void terminateAll(){
- LocalManagementContext.terminateAll();
-
- LocalManagementContext context1 = new LocalManagementContext();
- LocalManagementContext context2 = new LocalManagementContext();
-
- LocalManagementContext.terminateAll();
-
- assertTrue(LocalManagementContext.getInstances().isEmpty());
- assertFalse(context1.isRunning());
- assertFalse(context2.isRunning());
- }
-
- @Test
- public void terminateExplicitContext(){
- LocalManagementContext context1 = new LocalManagementContext();
- LocalManagementContext context2 = new LocalManagementContext();
- LocalManagementContext context3 = new LocalManagementContext();
-
- context2.terminate();
-
- Assert.assertFalse(LocalManagementContext.getInstances().contains(context2));
- Assert.assertTrue(LocalManagementContext.getInstances().contains(context1));
- Assert.assertTrue(LocalManagementContext.getInstances().contains(context3));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/internal/LocalManagementContextTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/internal/LocalManagementContextTest.java b/core/src/test/java/brooklyn/management/internal/LocalManagementContextTest.java
deleted file mode 100644
index d225cd7..0000000
--- a/core/src/test/java/brooklyn/management/internal/LocalManagementContextTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotEquals;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.ManagementContext.PropertiesReloadListener;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynProperties.Factory.Builder;
-import brooklyn.util.os.Os;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.Files;
-
-public class LocalManagementContextTest {
-
- private LocalManagementContext context;
- private File globalPropertiesFile;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- context = null;
- globalPropertiesFile = Os.newTempFile(getClass(), "global.properties");
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (context!=null) context.terminate();
- if (globalPropertiesFile != null) globalPropertiesFile.delete();
- }
-
- @Test
- public void testReloadPropertiesFromBuilder() throws IOException {
- String globalPropertiesContents = "brooklyn.location.localhost.displayName=myname";
- Files.write(globalPropertiesContents, globalPropertiesFile, Charsets.UTF_8);
- Builder propsBuilder = new BrooklynProperties.Factory.Builder()
- .globalPropertiesFile(globalPropertiesFile.getAbsolutePath());
- // no builder support in LocalManagementContextForTests (we are testing that the builder's files are reloaded so we need it here)
- context = new LocalManagementContext(propsBuilder);
- Location location = context.getLocationRegistry().resolve("localhost");
- assertEquals(location.getDisplayName(), "myname");
- String newGlobalPropertiesContents = "brooklyn.location.localhost.displayName=myname2";
- Files.write(newGlobalPropertiesContents, globalPropertiesFile, Charsets.UTF_8);
- context.reloadBrooklynProperties();
- Location location2 = context.getLocationRegistry().resolve("localhost");
- assertEquals(location.getDisplayName(), "myname");
- assertEquals(location2.getDisplayName(), "myname2");
- }
-
- @Test
- public void testReloadPropertiesFromProperties() throws IOException {
- String globalPropertiesContents = "brooklyn.location.localhost.displayName=myname";
- Files.write(globalPropertiesContents, globalPropertiesFile, Charsets.UTF_8);
- BrooklynProperties brooklynProperties = new BrooklynProperties.Factory.Builder()
- .globalPropertiesFile(globalPropertiesFile.getAbsolutePath())
- .build();
- context = LocalManagementContextForTests.builder(true).useProperties(brooklynProperties).build();
- Location location = context.getLocationRegistry().resolve("localhost");
- assertEquals(location.getDisplayName(), "myname");
- String newGlobalPropertiesContents = "brooklyn.location.localhost.displayName=myname2";
- Files.write(newGlobalPropertiesContents, globalPropertiesFile, Charsets.UTF_8);
- context.reloadBrooklynProperties();
- Location location2 = context.getLocationRegistry().resolve("localhost");
- assertEquals(location.getDisplayName(), "myname");
- assertEquals(location2.getDisplayName(), "myname");
- }
-
- @Test
- public void testPropertiesModified() throws IOException {
- BrooklynProperties properties = BrooklynProperties.Factory.newEmpty();
- properties.put("myname", "myval");
- context = LocalManagementContextForTests.builder(true).useProperties(properties).build();
- assertEquals(context.getBrooklynProperties().get("myname"), "myval");
- properties.put("myname", "newval");
- assertEquals(properties.get("myname"), "newval");
- // TODO: Should changes in the 'properties' collection be reflected in context.getBrooklynProperties()?
- assertNotEquals(context.getBrooklynProperties().get("myname"), "newval");
- }
-
- @Test
- public void testAddAndRemoveReloadListener() {
- final AtomicInteger reloadedCallbackCount = new AtomicInteger(0);
- BrooklynProperties properties = BrooklynProperties.Factory.newEmpty();
- properties.put("myname", "myval");
- context = LocalManagementContextForTests.builder(true).useProperties(properties).build();
- PropertiesReloadListener listener = new PropertiesReloadListener() {
- public void reloaded() {
- reloadedCallbackCount.incrementAndGet();
- }
- };
- assertEquals(reloadedCallbackCount.get(), 0);
- context.addPropertiesReloadListener(listener);
- context.reloadBrooklynProperties();
- assertEquals(reloadedCallbackCount.get(), 1);
- context.removePropertiesReloadListener(listener);
- context.reloadBrooklynProperties();
- assertEquals(reloadedCallbackCount.get(), 1);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/internal/LocalSubscriptionManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/internal/LocalSubscriptionManagerTest.java b/core/src/test/java/brooklyn/management/internal/LocalSubscriptionManagerTest.java
deleted file mode 100644
index 7907d30..0000000
--- a/core/src/test/java/brooklyn/management/internal/LocalSubscriptionManagerTest.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
-
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.event.SensorEvent;
-import org.apache.brooklyn.api.event.SensorEventListener;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-import org.apache.brooklyn.api.management.SubscriptionManager;
-import org.apache.brooklyn.test.entity.TestEntity;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.BrooklynAppUnitTestSupport;
-import brooklyn.entity.basic.BasicGroup;
-import brooklyn.entity.basic.Entities;
-
-/**
- * testing the {@link SubscriptionManager} and associated classes.
- */
-public class LocalSubscriptionManagerTest extends BrooklynAppUnitTestSupport {
-
- private static final int TIMEOUT_MS = 5000;
-
- private TestEntity entity;
-
- @BeforeMethod(alwaysRun=true)
- @Override
- public void setUp() throws Exception {
- super.setUp();
- entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- }
-
- private void manage(Entity ...entities) {
- for (Entity e: entities)
- Entities.manage(e);
- }
-
- @Test
- public void testSubscribeToEntityAttributeChange() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- app.subscribe(entity, TestEntity.SEQUENCE, new SensorEventListener<Object>() {
- @Override public void onEvent(SensorEvent<Object> event) {
- latch.countDown();
- }});
- entity.setSequenceValue(1234);
- if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- fail("Timeout waiting for Event on TestEntity listener");
- }
- }
-
- @Test
- public void testSubscribeToEntityWithAttributeWildcard() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- app.subscribe(entity, null, new SensorEventListener<Object>() {
- @Override public void onEvent(SensorEvent<Object> event) {
- latch.countDown();
- }});
- entity.setSequenceValue(1234);
- if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- fail("Timeout waiting for Event on TestEntity listener");
- }
- }
-
- @Test
- public void testSubscribeToAttributeChangeWithEntityWildcard() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- app.subscribe(null, TestEntity.SEQUENCE, new SensorEventListener<Object>() {
- @Override public void onEvent(SensorEvent<Object> event) {
- latch.countDown();
- }});
- entity.setSequenceValue(1234);
- if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- fail("Timeout waiting for Event on TestEntity listener");
- }
- }
-
- @Test
- public void testSubscribeToChildAttributeChange() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- app.subscribeToChildren(app, TestEntity.SEQUENCE, new SensorEventListener<Object>() {
- @Override public void onEvent(SensorEvent<Object> event) {
- latch.countDown();
- }});
- entity.setSequenceValue(1234);
- if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- fail("Timeout waiting for Event on child TestEntity listener");
- }
- }
-
- @Test
- public void testSubscribeToMemberAttributeChange() throws Exception {
- BasicGroup group = app.createAndManageChild(EntitySpec.create(BasicGroup.class));
- TestEntity member = app.createAndManageChild(EntitySpec.create(TestEntity.class));
- manage(group, member);
-
- group.addMember(member);
-
- final List<SensorEvent<Integer>> events = new CopyOnWriteArrayList<SensorEvent<Integer>>();
- final CountDownLatch latch = new CountDownLatch(1);
- app.subscribeToMembers(group, TestEntity.SEQUENCE, new SensorEventListener<Integer>() {
- @Override public void onEvent(SensorEvent<Integer> event) {
- events.add(event);
- latch.countDown();
- }});
- member.setAttribute(TestEntity.SEQUENCE, 123);
-
- if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- fail("Timeout waiting for Event on parent TestEntity listener");
- }
- assertEquals(events.size(), 1);
- assertEquals(events.get(0).getValue(), (Integer)123);
- assertEquals(events.get(0).getSensor(), TestEntity.SEQUENCE);
- assertEquals(events.get(0).getSource().getId(), member.getId());
- }
-
- // Regression test for ConcurrentModificationException in issue #327
- @Test(groups="Integration")
- public void testConcurrentSubscribingAndPublishing() throws Exception {
- final AtomicReference<Exception> threadException = new AtomicReference<Exception>();
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
-
- // Repeatedly subscribe and unsubscribe, so listener-set constantly changing while publishing to it.
- // First create a stable listener so it is always the same listener-set object.
- Thread thread = new Thread() {
- public void run() {
- try {
- SensorEventListener<Object> noopListener = new SensorEventListener<Object>() {
- @Override public void onEvent(SensorEvent<Object> event) {
- }
- };
- app.subscribe(null, TestEntity.SEQUENCE, noopListener);
- while (!Thread.currentThread().isInterrupted()) {
- SubscriptionHandle handle = app.subscribe(null, TestEntity.SEQUENCE, noopListener);
- app.unsubscribe(null, handle);
- }
- } catch (Exception e) {
- threadException.set(e);
- }
- }
- };
-
- try {
- thread.start();
- for (int i = 0; i < 10000; i++) {
- entity.setAttribute(TestEntity.SEQUENCE, i);
- }
- } finally {
- thread.interrupt();
- }
-
- if (threadException.get() != null) throw threadException.get();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/osgi/OsgiPathTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiPathTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiPathTest.java
deleted file mode 100644
index 829b281..0000000
--- a/core/src/test/java/brooklyn/management/osgi/OsgiPathTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.osgi;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.osgi.framework.BundleException;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.config.BrooklynServerPaths;
-import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.util.os.Os;
-import brooklyn.util.text.Identifiers;
-
-
-/**
- * Tests that OSGi entities load correctly and have the right catalog information set.
- * Note further tests done elsewhere using CAMP YAML (referring to methods in this class).
- */
-public class OsgiPathTest {
-
- protected LocalManagementContext mgmt = null;
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws BundleException, IOException, InterruptedException {
- if (mgmt!=null) Entities.destroyAll(mgmt);
- }
-
- @Test(groups="Integration") // integration only because OSGi takes ~200ms
- public void testOsgiPathDefault() {
- mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).build();
- String path = BrooklynServerPaths.getOsgiCacheDir(mgmt).getAbsolutePath();
- Assert.assertTrue(path.startsWith(BrooklynServerPaths.getMgmtBaseDir(mgmt)), path);
- Assert.assertTrue(path.contains(mgmt.getManagementNodeId()), path);
-
- assertExistsThenIsCleaned(path);
- }
-
- @Test(groups="Integration") // integration only because OSGi takes ~200ms
- public void testOsgiPathCustom() {
- BrooklynProperties bp = BrooklynProperties.Factory.newEmpty();
- String randomSeg = "osgi-test-"+Identifiers.makeRandomId(4);
- bp.put(BrooklynServerConfig.OSGI_CACHE_DIR, "${brooklyn.os.tmpdir}"+"/"+randomSeg+"/"+"${brooklyn.mgmt.node.id}");
- mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).useProperties(bp).build();
- String path = BrooklynServerPaths.getOsgiCacheDir(mgmt).getAbsolutePath();
- Os.deleteOnExitRecursivelyAndEmptyParentsUpTo(new File(path), new File(Os.tmp()+"/"+randomSeg));
-
- Assert.assertTrue(path.startsWith(Os.tmp()), path);
- Assert.assertTrue(path.contains(mgmt.getManagementNodeId()), path);
-
- assertExistsThenIsCleaned(path);
- }
-
- @Test(groups="Integration") // integration only because OSGi takes ~200ms
- public void testOsgiPathCustomWithoutNodeIdNotCleaned() {
- BrooklynProperties bp = BrooklynProperties.Factory.newEmpty();
- String randomSeg = "osgi-test-"+Identifiers.makeRandomId(4);
- bp.put(BrooklynServerConfig.OSGI_CACHE_DIR, "${brooklyn.os.tmpdir}"+"/"+randomSeg+"/"+"sample");
- mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).useProperties(bp).build();
- String path = BrooklynServerPaths.getOsgiCacheDir(mgmt).getAbsolutePath();
- Os.deleteOnExitRecursivelyAndEmptyParentsUpTo(new File(path), new File(Os.tmp()+"/"+randomSeg));
-
- Assert.assertTrue(path.startsWith(Os.tmp()), path);
- Assert.assertFalse(path.contains(mgmt.getManagementNodeId()), path);
-
- assertExistsThenCorrectCleanedBehaviour(path, false);
- }
-
- private void assertExistsThenIsCleaned(String path) {
- assertExistsThenCorrectCleanedBehaviour(path, true);
- }
- private void assertExistsThenCorrectCleanedBehaviour(String path, boolean shouldBeCleanAfterwards) {
- Assert.assertTrue(new File(path).exists(), "OSGi cache "+path+" should exist when in use");
- Entities.destroyAll(mgmt);
- mgmt = null;
- if (shouldBeCleanAfterwards)
- Assert.assertFalse(new File(path).exists(), "OSGi cache "+path+" should be cleaned after");
- else
- Assert.assertTrue(new File(path).exists(), "OSGi cache "+path+" should NOT be cleaned after");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
deleted file mode 100644
index 64306c6..0000000
--- a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.osgi;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.jar.JarInputStream;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.test.TestResourceUnavailableException;
-
-import brooklyn.util.exceptions.Exceptions;
-
-import org.apache.commons.io.FileUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.launch.Framework;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.maven.MavenArtifact;
-import brooklyn.util.maven.MavenRetriever;
-import brooklyn.util.net.Urls;
-import brooklyn.util.os.Os;
-import brooklyn.util.osgi.Osgis;
-import brooklyn.util.osgi.Osgis.ManifestHelper;
-import brooklyn.util.stream.Streams;
-
-/**
- * Tests some assumptions about OSGi behaviour, in standalone mode (not part of brooklyn).
- * See {@link OsgiTestResources} for description of test resources.
- */
-public class OsgiStandaloneTest {
-
- private static final Logger log = LoggerFactory.getLogger(OsgiStandaloneTest.class);
-
- public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = OsgiTestResources.BROOKLYN_OSGI_TEST_A_0_1_0_PATH;
- public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:"+BROOKLYN_OSGI_TEST_A_0_1_0_PATH;
-
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+BROOKLYN_TEST_OSGI_ENTITIES_PATH;
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_NAME = "org.apache.brooklyn.test.resources.osgi.brooklyn-test-osgi-entities";
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_VERSION = "0.1.0";
-
- protected Framework framework = null;
- private File storageTempDir;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- storageTempDir = Os.newTempDir("osgi-standalone");
- framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws BundleException, IOException, InterruptedException {
- tearDownOsgiFramework(framework, storageTempDir);
- }
-
- public static void tearDownOsgiFramework(Framework framework, File storageTempDir) throws BundleException, InterruptedException, IOException {
- if (framework!=null) {
- framework.stop();
- Assert.assertEquals(framework.waitForStop(1000).getType(), FrameworkEvent.STOPPED);
- framework = null;
- }
- if (storageTempDir!=null) {
- FileUtils.deleteDirectory(storageTempDir);
- storageTempDir = null;
- }
- }
-
- protected Bundle install(String url) throws BundleException {
- try {
- return Osgis.install(framework, url);
- } catch (Exception e) {
- throw new IllegalStateException("test resources not available; may be an IDE issue, so try a mvn rebuild of this project", e);
- }
- }
-
- protected Bundle installFromClasspath(String resourceName) throws BundleException {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), resourceName);
- try {
- return Osgis.install(framework, String.format("classpath:%s", resourceName));
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- @Test
- public void testInstallBundle() throws Exception {
- Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
- checkMath(bundle, 3, 6);
- }
-
- @Test
- public void testBootBundle() throws Exception {
- Bundle bundle = installFromClasspath(BROOKLYN_TEST_OSGI_ENTITIES_PATH);
- Class<?> bundleCls = bundle.loadClass("brooklyn.osgi.tests.SimpleEntity");
- Assert.assertEquals(Entity.class, bundle.loadClass(Entity.class.getName()));
- Assert.assertEquals(Entity.class, bundleCls.getClassLoader().loadClass(Entity.class.getName()));
- }
-
- @Test
- public void testDuplicateBundle() throws Exception {
- MavenArtifact artifact = new MavenArtifact("org.apache.brooklyn", "brooklyn-api", "jar", "0.8.0-SNAPSHOT"); // BROOKLYN_VERSION
- String localUrl = MavenRetriever.localUrl(artifact);
- if ("file".equals(Urls.getProtocol(localUrl))) {
- helperDuplicateBundle(localUrl);
- } else {
- log.warn("Skipping test OsgiStandaloneTest.testDuplicateBundle due to " + artifact + " not available in local repo.");
- }
- }
-
- @Test(groups="Integration")
- public void testRemoteDuplicateBundle() throws Exception {
- helperDuplicateBundle(MavenRetriever.hostedUrl(new MavenArtifact("org.apache.brooklyn", "brooklyn-api", "jar", "0.8.0-SNAPSHOT"))); // BROOKLYN_VERSION
- }
-
- public void helperDuplicateBundle(String url) throws Exception {
- //The bundle is already installed from the boot path.
- //Make sure that we still get the initially loaded
- //bundle after trying to install the same version.
- Bundle bundle = install(url);
- Assert.assertTrue(Osgis.isExtensionBundle(bundle));
- }
-
- @Test
- public void testAMultiplier() throws Exception {
- Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
- checkMath(bundle, 3, 6);
- setAMultiplier(bundle, 5);
- checkMath(bundle, 3, 15);
- }
-
- /** run two multiplier tests to ensure that irrespective of order the tests run in,
- * on a fresh install the multiplier is reset */
- @Test
- public void testANOtherMultiple() throws Exception {
- Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
- checkMath(bundle, 3, 6);
- setAMultiplier(bundle, 14);
- checkMath(bundle, 3, 42);
- }
-
- @Test
- public void testGetBundle() throws Exception {
- Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
- setAMultiplier(bundle, 3);
-
- // can look it up based on the same location string (no other "location identifier" reference string seems to work here, however)
- Bundle bundle2 = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
- checkMath(bundle2, 3, 9);
- }
-
- @Test
- public void testUninstallAndReinstallBundle() throws Exception {
- Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
- checkMath(bundle, 3, 6);
- setAMultiplier(bundle, 3);
- checkMath(bundle, 3, 9);
- bundle.uninstall();
-
- Bundle bundle2 = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
- checkMath(bundle2, 3, 6);
- }
-
- protected void checkMath(Bundle bundle, int input, int output) throws Exception {
- Assert.assertNotNull(bundle);
- Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");
- Object aInst = aClass.newInstance();
- Object result = aClass.getMethod("times", int.class).invoke(aInst, input);
- Assert.assertEquals(result, output);
- }
-
- protected void setAMultiplier(Bundle bundle, int newMultiplier) throws Exception {
- Assert.assertNotNull(bundle);
- Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");
- aClass.getField("multiplier").set(null, newMultiplier);
- }
-
- @Test
- public void testReadAManifest() throws Exception {
- Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
- log.info("Bundles and exported packages:");
- MutableSet<String> allPackages = MutableSet.of();
- while (manifests.hasMoreElements()) {
- ManifestHelper mf = Osgis.ManifestHelper.forManifestContents(Streams.readFullyString( manifests.nextElement().openStream() ));
- List<String> mfPackages = mf.getExportedPackages();
- log.info(" "+mf.getSymbolicNameVersion()+": "+mfPackages);
- allPackages.addAll(mfPackages);
- }
- log.info("Total export package count: "+allPackages.size());
- Assert.assertTrue(allPackages.size()>20, "did not find enough packages"); // probably much larger
- Assert.assertTrue(allPackages.contains(Osgis.class.getPackage().getName()));
- }
-
- @Test
- public void testReadKnownManifest() throws Exception {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_ENTITIES_PATH);
- InputStream in = this.getClass().getResourceAsStream(BROOKLYN_TEST_OSGI_ENTITIES_PATH);
- JarInputStream jarIn = new JarInputStream(in);
- ManifestHelper helper = Osgis.ManifestHelper.forManifest(jarIn.getManifest());
- jarIn.close();
- Assert.assertEquals(helper.getVersion().toString(), "0.1.0");
- Assert.assertTrue(helper.getExportedPackages().contains("brooklyn.osgi.tests"));
- }
-
- @Test
- public void testLoadOsgiBundleDependencies() throws Exception {
- Bundle bundle = installFromClasspath(BROOKLYN_TEST_OSGI_ENTITIES_PATH);
- Assert.assertNotNull(bundle);
- Class<?> aClass = bundle.loadClass("brooklyn.osgi.tests.SimpleApplicationImpl");
- Object aInst = aClass.newInstance();
- Assert.assertNotNull(aInst);
- }
-
- @Test
- public void testLoadAbsoluteWindowsResourceWithInstalledOSGi() {
- //Felix installs an additional URL to the system classloader
- //which throws an IllegalArgumentException when passed a
- //windows path. See ExtensionManager.java static initializer.
- String context = "mycontext";
- String dummyPath = "C:\\dummypath";
- ResourceUtils utils = ResourceUtils.create(this, context);
- try {
- utils.getResourceFromUrl(dummyPath);
- Assert.fail("Non-reachable, should throw an exception for non-existing resource.");
- } catch (RuntimeException e) {
- Assert.assertTrue(e.getMessage().startsWith("Error getting resource '"+dummyPath+"' for "+context));
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java b/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
deleted file mode 100644
index ef0321d..0000000
--- a/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.osgi;
-
-/**
- * Many OSGi tests require OSGi bundles (of course). Test bundles have been collected here
- * for convenience and clarity. Available bundles (on the classpath, with source code
- * either embedded or in /src/dependencies) are described by the constants in this class.
- * <p>
- * Some of these bundles are also used in REST API tests, as that stretches catalog further
- * (using CAMP) and that is one area where OSGi is heavily used.
- */
-public class OsgiTestResources {
-
-
- /**
- * brooklyn-osgi-test-a_0.1.0 -
- * defines TestA which has a "times" method and a static multiplier field;
- * we set the multiplier to determine when we are sharing versions and when not
- */
- public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = "/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar";
-
- /**
- * brooklyn-test-osgi-entities (v 0.1.0) -
- * defines an entity and an application, to confirm it can be read and used by brooklyn
- */
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = "/brooklyn/osgi/brooklyn-test-osgi-entities.jar";
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_APPLICATION = "brooklyn.osgi.tests.SimpleApplication";
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY = "brooklyn.osgi.tests.SimpleEntity";
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY = "brooklyn.osgi.tests.SimplePolicy";
-
- /**
- * brooklyn-test-osgi-more-entities_0.1.0 -
- * another bundle with a minimal sayHi effector, used to test versioning and dependencies
- * (this one has no dependencies, but see also {@value #BROOKLYN_TEST_MORE_ENTITIES_V2_PATH})
- */
- public static final String BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART = "brooklyn-test-osgi-more-entities";
- public static final String BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL =
- "org.apache.brooklyn.test.resources.osgi."+BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART;
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_PATH = "/brooklyn/osgi/" + BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART + "_0.1.0.jar";
- public static final String BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY = "brooklyn.osgi.tests.more.MoreEntity";
-
- /**
- * brooklyn-test-osgi-more-entities_0.2.0 -
- * similar to {@link #BROOKLYN_TEST_MORE_ENTITIES_V1_PATH} but saying "HI NAME" rather than "Hi NAME",
- * and declaring an explicit dependency on SimplePolicy from {@link #BROOKLYN_TEST_OSGI_ENTITIES_PATH}
- */
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_PATH = "/brooklyn/osgi/" + BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART + "_0.2.0.jar";
-
- /**
- * bundle with identical metadata (same symbolic name and version -- hence being an evil twin)
- * as {@link #BROOKLYN_TEST_MORE_ENTITIES_V2_PATH},
- * but slightly different behaviour -- saying "HO NAME" -- in order to make sure we can differentiate two two
- * at runtime.
- */
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH = "/brooklyn/osgi/" + BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART + "_evil-twin_0.2.0.jar";
-
-}
[15/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
new file mode 100644
index 0000000..8a02fcf
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
@@ -0,0 +1,1105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.rebind.RebindManager;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityManager;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.api.management.ha.MementoCopyMode;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister.Delta;
+import org.apache.brooklyn.core.management.ha.BasicMasterChooser.AlphabeticMasterChooser;
+import org.apache.brooklyn.core.management.internal.BrooklynObjectManagementMode;
+import org.apache.brooklyn.core.management.internal.LocalEntityManager;
+import org.apache.brooklyn.core.management.internal.LocationManagerInternal;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.BrooklynVersion;
+import brooklyn.catalog.internal.BasicBrooklynCatalog;
+import brooklyn.catalog.internal.CatalogDto;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.rebind.RebindManagerImpl;
+import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
+import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils.CreateBackupMode;
+import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
+import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
+import brooklyn.entity.rebind.plane.dto.ManagementPlaneSyncRecordImpl;
+import brooklyn.entity.rebind.plane.dto.ManagementPlaneSyncRecordImpl.Builder;
+import brooklyn.internal.BrooklynFeatureEnablement;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.ReferenceWithError;
+import brooklyn.util.task.ScheduledTask;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Ticker;
+import com.google.common.collect.Iterables;
+
+/**
+ * This is the guts of the high-availability solution in Brooklyn.
+ * <p>
+ * Multiple brooklyn nodes can be started to form a single management plane, where one node is
+ * designated master and the others are "warm standbys". On termination or failure of the master,
+ * the standbys deterministically decide which standby should become master (see {@link MasterChooser}).
+ * That standby promotes itself.
+ * <p>
+ * The management nodes communicate their health/status via the {@link ManagementPlaneSyncRecordPersister}.
+ * For example, if using {@link ManagementPlaneSyncRecordPersisterToObjectStore} with a shared blobstore or
+ * filesystem/NFS mount, then each management-node periodically writes its state.
+ * This acts as a heartbeat, being read by the other management-nodes.
+ * <p>
+ * Promotion to master involves:
+ * <ol>
+ * <li>notifying the other management-nodes that it is now master
+ * <li>calling {@link RebindManager#rebind(ClassLoader, org.apache.brooklyn.api.entity.rebind.RebindExceptionHandler, ManagementNodeState)} to read all persisted entity state, and thus reconstitute the entities.
+ * </ol>
+ * <p>
+ * Future improvements in this area will include brooklyn-managing-brooklyn to decide + promote
+ * the standby.
+ *
+ * @since 0.7.0
+ *
+ * @author aled
+ */
+@Beta
+public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
+
+ public final ConfigKey<Duration> POLL_PERIOD = ConfigKeys.newConfigKey(Duration.class, "brooklyn.ha.pollPeriod",
+ "How often nodes should poll to detect whether master is healthy", Duration.seconds(1));
+ public final ConfigKey<Duration> HEARTBEAT_TIMEOUT = ConfigKeys.newConfigKey(Duration.class, "brooklyn.ha.heartbeatTimeout",
+ "Maximum allowable time for detection of a peer's heartbeat; if no sign of master after this time, "
+ + "another node may promote itself", Duration.THIRTY_SECONDS);
+
+ @VisibleForTesting /* only used in tests currently */
+ public static interface PromotionListener {
+ public void promotingToMaster();
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(HighAvailabilityManagerImpl.class);
+
+ private final ManagementContextInternal managementContext;
+ private volatile String ownNodeId;
+ private volatile ManagementPlaneSyncRecordPersister persister;
+ private volatile PromotionListener promotionListener;
+ private volatile MasterChooser masterChooser = new AlphabeticMasterChooser();
+ private volatile Ticker localTickerUtc = new Ticker() {
+ // strictly not a ticker because returns millis UTC, but it works fine even so
+ @Override
+ public long read() {
+ return System.currentTimeMillis();
+ }
+ };
+ private volatile Ticker optionalRemoteTickerUtc = null;
+
+ private volatile Task<?> pollingTask;
+ private volatile boolean disabled;
+ private volatile boolean running;
+ private volatile ManagementNodeState nodeState = ManagementNodeState.INITIALIZING;
+ private volatile boolean nodeStateTransitionComplete = false;
+ private volatile long priority = 0;
+
+ private final static int MAX_NODE_STATE_HISTORY = 200;
+ private final List<Map<String,Object>> nodeStateHistory = MutableList.of();
+
+ private volatile transient Duration pollPeriodLocalOverride;
+ private volatile transient Duration heartbeatTimeoutOverride;
+
+ private volatile ManagementPlaneSyncRecord lastSyncRecord;
+
+ private volatile PersistenceActivityMetrics managementStateWritePersistenceMetrics = new PersistenceActivityMetrics();
+ private volatile PersistenceActivityMetrics managementStateReadPersistenceMetrics = new PersistenceActivityMetrics();
+ private final long startTimeUtc;
+
+ public HighAvailabilityManagerImpl(ManagementContextInternal managementContext) {
+ this.managementContext = managementContext;
+ startTimeUtc = localTickerUtc.read();
+ }
+
+ @Override
+ public HighAvailabilityManagerImpl setPersister(ManagementPlaneSyncRecordPersister persister) {
+ this.persister = checkNotNull(persister, "persister");
+ return this;
+ }
+
+ @Override
+ public ManagementPlaneSyncRecordPersister getPersister() {
+ return persister;
+ }
+
+ protected synchronized Duration getPollPeriod() {
+ if (pollPeriodLocalOverride!=null) return pollPeriodLocalOverride;
+ return managementContext.getBrooklynProperties().getConfig(POLL_PERIOD);
+ }
+
+ /** Overrides {@link #POLL_PERIOD} from brooklyn config,
+ * including e.g. {@link Duration#PRACTICALLY_FOREVER} to disable polling;
+ * or <code>null</code> to clear a local override */
+ public HighAvailabilityManagerImpl setPollPeriod(Duration val) {
+ this.pollPeriodLocalOverride = val;
+ if (running) {
+ registerPollTask();
+ }
+ return this;
+ }
+
+ public HighAvailabilityManagerImpl setMasterChooser(MasterChooser val) {
+ this.masterChooser = checkNotNull(val, "masterChooser");
+ return this;
+ }
+
+ public synchronized Duration getHeartbeatTimeout() {
+ if (heartbeatTimeoutOverride!=null) return heartbeatTimeoutOverride;
+ return managementContext.getBrooklynProperties().getConfig(HEARTBEAT_TIMEOUT);
+ }
+
+ /** Overrides {@link #HEARTBEAT_TIMEOUT} from brooklyn config,
+ * including e.g. {@link Duration#PRACTICALLY_FOREVER} to prevent failover due to heartbeat absence;
+ * or <code>null</code> to clear a local override */
+ public HighAvailabilityManagerImpl setHeartbeatTimeout(Duration val) {
+ this.heartbeatTimeoutOverride = val;
+ return this;
+ }
+
+ /** A ticker that reads in milliseconds, for populating local timestamps.
+ * Defaults to System.currentTimeMillis(); may be overridden e.g. for testing. */
+ public HighAvailabilityManagerImpl setLocalTicker(Ticker val) {
+ this.localTickerUtc = checkNotNull(val);
+ return this;
+ }
+
+ /** A ticker that reads in milliseconds, for overriding remote timestamps.
+ * Defaults to null which means to use the remote timestamp.
+ * Only for testing as this records the remote timestamp in the object.
+ * <p>
+ * If this is supplied, one must also set {@link ManagementPlaneSyncRecordPersisterToObjectStore#useRemoteTimestampInMemento()}. */
+ @VisibleForTesting
+ public HighAvailabilityManagerImpl setRemoteTicker(Ticker val) {
+ this.optionalRemoteTickerUtc = val;
+ return this;
+ }
+
+ public HighAvailabilityManagerImpl setPromotionListener(PromotionListener val) {
+ this.promotionListener = checkNotNull(val, "promotionListener");
+ return this;
+ }
+
+ @Override
+ public boolean isRunning() {
+ return running;
+ }
+
+ @Override
+ public void disabled() {
+ disabled = true;
+ ownNodeId = managementContext.getManagementNodeId();
+ // this is notionally the master, just not running; see javadoc for more info
+ stop(ManagementNodeState.MASTER);
+
+ }
+
+ @Override
+ public void start(HighAvailabilityMode startMode) {
+ nodeStateTransitionComplete = true;
+ disabled = false;
+ running = true;
+ changeMode(startMode, true, true);
+ }
+
+ @Override
+ public void changeMode(HighAvailabilityMode startMode) {
+ changeMode(startMode, false, false);
+ }
+
+ @VisibleForTesting
+ @Beta
+ public void changeMode(HighAvailabilityMode startMode, boolean preventElectionOnExplicitStandbyMode, boolean failOnExplicitModesIfUnusual) {
+ if (!running) {
+ // if was not running then start as disabled mode, then proceed as normal
+ LOG.info("HA changing mode to "+startMode+" from "+getInternalNodeState()+" when not running, forcing an intermediate start as DISABLED then will convert to "+startMode);
+ start(HighAvailabilityMode.DISABLED);
+ }
+ if (getNodeState()==ManagementNodeState.FAILED || getNodeState()==ManagementNodeState.INITIALIZING) {
+ if (startMode!=HighAvailabilityMode.DISABLED) {
+ // if coming from FAILED (or INITIALIZING because we skipped start call) then treat as initializing
+ setInternalNodeState(ManagementNodeState.INITIALIZING);
+ }
+ }
+
+ ownNodeId = managementContext.getManagementNodeId();
+ // TODO Small race in that we first check, and then we'll do checkMaster() on first poll,
+ // so another node could have already become master or terminated in that window.
+ ManagementNodeSyncRecord existingMaster = hasHealthyMaster();
+ boolean weAreRecognisedAsMaster = existingMaster!=null && ownNodeId.equals(existingMaster.getNodeId());
+ boolean weAreMasterLocally = getInternalNodeState()==ManagementNodeState.MASTER;
+
+ // catch error in some tests where mgmt context has a different mgmt context
+ if (managementContext.getHighAvailabilityManager()!=this)
+ throw new IllegalStateException("Cannot start an HA manager on a management context with a different HA manager!");
+
+ if (weAreMasterLocally) {
+ // demotion may be required; do this before triggering an election
+ switch (startMode) {
+ case MASTER:
+ case AUTO:
+ case DISABLED:
+ // no action needed, will do anything necessary below (or above)
+ break;
+ case HOT_STANDBY:
+ case HOT_BACKUP:
+ case STANDBY:
+ demoteTo(ManagementNodeState.of(startMode).get()); break;
+ default:
+ throw new IllegalStateException("Unexpected high availability mode "+startMode+" requested for "+this);
+ }
+ }
+
+ ManagementNodeState oldState = getInternalNodeState();
+
+ // now do election
+ switch (startMode) {
+ case AUTO:
+ // don't care; let's start and see if we promote ourselves
+ if (getInternalNodeState()==ManagementNodeState.INITIALIZING) {
+ setInternalNodeState(ManagementNodeState.STANDBY);
+ }
+ publishAndCheck(true);
+ switch (getInternalNodeState()) {
+ case HOT_BACKUP:
+ if (!nodeStateTransitionComplete) throw new IllegalStateException("Cannot switch to AUTO when in the middle of a transition to "+getInternalNodeState());
+ // else change us to standby, desiring to go to hot standby, and continue to below
+ setInternalNodeState(ManagementNodeState.STANDBY);
+ startMode = HighAvailabilityMode.HOT_BACKUP;
+ case HOT_STANDBY:
+ case STANDBY:
+ if (getInternalNodeState()==ManagementNodeState.STANDBY && oldState==ManagementNodeState.INITIALIZING && startMode!=HighAvailabilityMode.HOT_BACKUP
+ && BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY)) {
+ // auto requested; not promoted; so it should become hot standby
+ startMode = HighAvailabilityMode.HOT_STANDBY;
+ }
+ ManagementPlaneSyncRecord newState = loadManagementPlaneSyncRecord(true);
+ String masterNodeId = newState.getMasterNodeId();
+ ManagementNodeSyncRecord masterNodeDetails = newState.getManagementNodes().get(masterNodeId);
+ LOG.info("Management node "+ownNodeId+" running as HA " + getInternalNodeState() + " autodetected"
+ + (startMode == HighAvailabilityMode.HOT_STANDBY || startMode == HighAvailabilityMode.HOT_BACKUP ?
+ " (will change to "+startMode+")" : "")
+ + ", " +
+ (Strings.isBlank(masterNodeId) ? "no master currently (other node should promote itself soon)" : "master "
+ + (existingMaster==null ? "(new) " : "")
+ + "is "+masterNodeId +
+ (masterNodeDetails==null || masterNodeDetails.getUri()==null ? " (no url)" : " at "+masterNodeDetails.getUri())));
+ break;
+ case MASTER:
+ LOG.info("Management node "+ownNodeId+" running as HA MASTER autodetected");
+ break;
+ default:
+ throw new IllegalStateException("Management node "+ownNodeId+" set to HA AUTO, encountered unexpected mode "+getInternalNodeState());
+ }
+ break;
+ case MASTER:
+ if (!failOnExplicitModesIfUnusual || existingMaster==null) {
+ promoteToMaster();
+ if (existingMaster!=null) {
+ LOG.info("Management node "+ownNodeId+" running as HA MASTER explicitly");
+ } else {
+ LOG.info("Management node "+ownNodeId+" running as HA MASTER explicitly, stealing from "+existingMaster);
+ }
+ } else if (!weAreRecognisedAsMaster) {
+ throw new IllegalStateException("Master already exists; cannot run as master (master "+existingMaster.toVerboseString()+"); "
+ + "to trigger a promotion, set a priority and demote the current master");
+ } else {
+ LOG.info("Management node "+ownNodeId+" already running as HA MASTER, when set explicitly");
+ }
+ break;
+ case HOT_BACKUP:
+ setInternalNodeState(ManagementNodeState.HOT_BACKUP);
+ // then continue into next block
+ case STANDBY:
+ case HOT_STANDBY:
+ if (startMode!=HighAvailabilityMode.HOT_BACKUP) {
+ if (ManagementNodeState.isHotProxy(getInternalNodeState()) && startMode==HighAvailabilityMode.HOT_STANDBY) {
+ // if was hot_backup, we can immediately go hot_standby
+ setInternalNodeState(ManagementNodeState.HOT_STANDBY);
+ } else {
+ // from any other state, set standby, then perhaps switch to hot_standby later on (or might become master in the next block)
+ setInternalNodeState(ManagementNodeState.STANDBY);
+ }
+ }
+ if (ManagementNodeState.isStandby(getInternalNodeState())) {
+ if (!preventElectionOnExplicitStandbyMode) {
+ publishAndCheck(true);
+ }
+ if (failOnExplicitModesIfUnusual && existingMaster==null) {
+ LOG.error("Management node "+ownNodeId+" detected no master when "+startMode+" requested and existing master required; failing.");
+ throw new IllegalStateException("No existing master; cannot start as "+startMode);
+ }
+ }
+ String message = "Management node "+ownNodeId+" running as HA "+getNodeState()+" (";
+ if (getNodeState().toString().equals(startMode.toString()))
+ message += "explicitly requested";
+ else if (startMode==HighAvailabilityMode.HOT_STANDBY && getNodeState()==ManagementNodeState.STANDBY)
+ message += "caller requested "+startMode+", will attempt rebind for HOT_STANDBY next";
+ else
+ message += "caller requested "+startMode;
+
+ if (getNodeState()==ManagementNodeState.MASTER) {
+ message += " but election re-promoted this node)";
+ } else {
+ ManagementPlaneSyncRecord newState = loadManagementPlaneSyncRecord(true);
+ if (Strings.isBlank(newState.getMasterNodeId())) {
+ message += "); no master currently";
+ if (startMode != HighAvailabilityMode.HOT_BACKUP) message += " (subsequent election may repair)";
+ } else {
+ message += "); master "+newState.getMasterNodeId();
+ }
+ }
+ LOG.info(message);
+ break;
+ case DISABLED:
+ // safe just to run even if we weren't master
+ LOG.info("Management node "+ownNodeId+" HA DISABLED (was "+getInternalNodeState()+")");
+ demoteTo(ManagementNodeState.FAILED);
+ if (pollingTask!=null) pollingTask.cancel(true);
+ break;
+ default:
+ throw new IllegalStateException("Unexpected high availability mode "+startMode+" requested for "+this);
+ }
+
+ if ((startMode==HighAvailabilityMode.HOT_STANDBY || startMode==HighAvailabilityMode.HOT_BACKUP)) {
+ if (!ManagementNodeState.isHotProxy(oldState)) {
+ // now transition to hot proxy
+ nodeStateTransitionComplete = false;
+ if (startMode==HighAvailabilityMode.HOT_STANDBY) {
+ // if it should be hot standby, then we may need to promote
+ // inform the world that we are transitioning (but not eligible for promotion while going in to hot standby)
+ // (no harm in doing this twice)
+ publishHealth();
+ }
+ try {
+ activateHotProxy(ManagementNodeState.of(startMode).get()).get();
+ // error above now throws
+ nodeStateTransitionComplete = true;
+ publishHealth();
+
+ if (getNodeState()==ManagementNodeState.HOT_STANDBY || getNodeState()==ManagementNodeState.HOT_BACKUP) {
+ LOG.info("Management node "+ownNodeId+" now running as HA "+getNodeState()+"; "
+ + managementContext.getApplications().size()+" application"+Strings.s(managementContext.getApplications().size())+" loaded");
+ } else {
+ // shouldn't come here, we should have gotten an error above
+ LOG.warn("Management node "+ownNodeId+" unable to promote to "+startMode+" (currently "+getNodeState()+"); "
+ + "(see log for further details)");
+ }
+ } catch (Exception e) {
+ LOG.warn("Management node "+ownNodeId+" unable to promote to "+startMode+" (currently "+getNodeState()+"); rethrowing: "+Exceptions.collapseText(e));
+ nodeStateTransitionComplete = true;
+ throw Exceptions.propagate(e);
+ }
+ } else {
+ // transitioning among hot proxy states - tell the rebind manager
+ managementContext.getRebindManager().stopReadOnly();
+ managementContext.getRebindManager().startReadOnly(ManagementNodeState.of(startMode).get());
+ nodeStateTransitionComplete = true;
+ }
+ } else {
+ nodeStateTransitionComplete = true;
+ }
+ if (startMode!=HighAvailabilityMode.DISABLED)
+ registerPollTask();
+ }
+
+ @Override
+ public void setPriority(long priority) {
+ this.priority = priority;
+ if (persister!=null) publishHealth();
+ }
+
+ @Override
+ public long getPriority() {
+ return priority;
+ }
+
+ @Override
+ public void stop() {
+ LOG.debug("Stopping "+this);
+ stop(ManagementNodeState.TERMINATED);
+ }
+
+ private void stop(ManagementNodeState newState) {
+ boolean wasRunning = running;
+
+ running = false;
+ setInternalNodeState(newState);
+ if (pollingTask != null) pollingTask.cancel(true);
+
+ if (wasRunning) {
+ try {
+ publishHealth();
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ LOG.error("Problem publishing manager-node health on termination (continuing)", e);
+ }
+ }
+ }
+
+ /** returns the node state this node is trying to be in */
+ public ManagementNodeState getTransitionTargetNodeState() {
+ return getInternalNodeState();
+ }
+
+ protected ManagementNodeState getInternalNodeState() {
+ return nodeState;
+ }
+
+ protected void setInternalNodeState(ManagementNodeState newState) {
+ ManagementNodeState oldState = getInternalNodeState();
+ synchronized (nodeStateHistory) {
+ if (this.nodeState != newState) {
+ nodeStateHistory.add(0, MutableMap.<String,Object>of("state", newState, "timestamp", currentTimeMillis()));
+ while (nodeStateHistory.size()>MAX_NODE_STATE_HISTORY) {
+ nodeStateHistory.remove(nodeStateHistory.size()-1);
+ }
+ }
+ ((RebindManagerImpl)managementContext.getRebindManager()).setAwaitingInitialRebind(running &&
+ (ManagementNodeState.isHotProxy(newState) || newState==ManagementNodeState.MASTER));
+ this.nodeState = newState;
+ }
+
+ if (ManagementNodeState.isHotProxy(oldState) && !ManagementNodeState.isHotProxy(newState)) {
+ // could perhaps promote standby items on some transitions; but for now we stop the old read-only and re-load them
+ // TODO ideally there'd be an incremental rebind as well as an incremental persist
+ managementContext.getRebindManager().stopReadOnly();
+ clearManagedItems(ManagementTransitionMode.transitioning(BrooklynObjectManagementMode.LOADED_READ_ONLY, BrooklynObjectManagementMode.UNMANAGED_PERSISTED));
+ }
+ }
+
+ @Override
+ public ManagementNodeState getNodeState() {
+ ManagementNodeState myNodeState = getInternalNodeState();
+ if (myNodeState==ManagementNodeState.FAILED) return getInternalNodeState();
+ // if target is master then we claim already being master, to prevent other nodes from taking it
+ // (we may fail subsequently of course)
+ if (myNodeState==ManagementNodeState.MASTER) return myNodeState;
+
+ if (!nodeStateTransitionComplete) return ManagementNodeState.INITIALIZING;
+ return myNodeState;
+ }
+
+ public ManagementPlaneSyncRecord getLastManagementPlaneSyncRecord() {
+ return lastSyncRecord;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void registerPollTask() {
+ final Runnable job = new Runnable() {
+ @Override public void run() {
+ try {
+ publishAndCheck(false);
+ } catch (Exception e) {
+ if (running) {
+ LOG.error("Problem in HA-poller: "+e, e);
+ } else {
+ if (LOG.isDebugEnabled()) LOG.debug("Problem in HA-poller, but no longer running: "+e, e);
+ }
+ } catch (Throwable t) {
+ LOG.error("Problem in HA-poller: "+t, t);
+ throw Exceptions.propagate(t);
+ }
+ }
+ };
+ Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
+ @Override public Task<?> call() {
+ return Tasks.builder().dynamic(false).body(job).name("HA poller task").tag(BrooklynTaskTags.TRANSIENT_TASK_TAG)
+ .description("polls HA status to see whether this node should promote").build();
+ }
+ };
+
+ LOG.debug("Registering poll task for "+this+", period "+getPollPeriod());
+ if (getPollPeriod().equals(Duration.PRACTICALLY_FOREVER)) {
+ // don't schedule - used for tests
+ // (scheduling fires off one initial task in the background before the delay,
+ // which affects tests that want to know exactly when publishing happens;
+ // TODO would be nice if scheduled task had a "no initial submission" flag )
+ } else {
+ if (pollingTask!=null) pollingTask.cancel(true);
+
+ ScheduledTask task = new ScheduledTask(MutableMap.of("period", getPollPeriod(), "displayName", "scheduled:[HA poller task]"), taskFactory);
+ pollingTask = managementContext.getExecutionManager().submit(task);
+ }
+ }
+
+ /** invoked manually when initializing, and periodically thereafter */
+ @VisibleForTesting
+ public synchronized void publishAndCheck(boolean initializing) {
+ publishHealth();
+ checkMaster(initializing);
+ }
+
+ protected synchronized void publishHealth() {
+ if (persister == null) {
+ LOG.info("Cannot publish management-node health as no persister");
+ return;
+ }
+
+ Stopwatch timer = Stopwatch.createStarted();
+ try {
+ ManagementNodeSyncRecord memento = createManagementNodeSyncRecord(false);
+ Delta delta = ManagementPlaneSyncRecordDeltaImpl.builder().node(memento).build();
+ persister.delta(delta);
+ managementStateWritePersistenceMetrics.noteSuccess(Duration.of(timer));
+ if (LOG.isTraceEnabled()) LOG.trace("Published management-node health: {}", memento);
+ } catch (Throwable t) {
+ managementStateWritePersistenceMetrics.noteFailure(Duration.of(timer));
+ managementStateWritePersistenceMetrics.noteError(t.toString());
+ LOG.debug("Error publishing management-node health (rethrowing): "+t);
+ throw Exceptions.propagate(t);
+ }
+ }
+
+ public void publishClearNonMaster() {
+ ManagementPlaneSyncRecord plane = getLastManagementPlaneSyncRecord();
+ if (plane==null || persister==null) {
+ LOG.warn("Cannot clear HA node records; HA not active (or not yet loaded)");
+ return;
+ }
+ org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordDeltaImpl.Builder db = ManagementPlaneSyncRecordDeltaImpl.builder();
+ for (Map.Entry<String,ManagementNodeSyncRecord> node: plane.getManagementNodes().entrySet()) {
+ // only keep a node if it both claims master and is recognised as master;
+ // else ex-masters who died are kept around!
+ if (!ManagementNodeState.MASTER.equals(node.getValue().getStatus()) ||
+ !Objects.equal(plane.getMasterNodeId(), node.getValue().getNodeId())) {
+ db.removedNodeId(node.getKey());
+ }
+ }
+ persister.delta(db.build());
+ // then get, so model is updated
+ loadManagementPlaneSyncRecord(true);
+ }
+
+ protected synchronized void publishDemotion(boolean demotingFromMaster) {
+ checkState(getNodeState() != ManagementNodeState.MASTER, "node status must not be master when demoting", getNodeState());
+
+ if (persister == null) {
+ LOG.info("Cannot publish management-node health as no persister");
+ return;
+ }
+
+ ManagementNodeSyncRecord memento = createManagementNodeSyncRecord(false);
+ ManagementPlaneSyncRecordDeltaImpl.Builder deltaBuilder = ManagementPlaneSyncRecordDeltaImpl.builder()
+ .node(memento);
+ if (demotingFromMaster) {
+ deltaBuilder.clearMaster(ownNodeId);
+ }
+
+ Delta delta = deltaBuilder.build();
+ persister.delta(delta);
+ if (LOG.isTraceEnabled()) LOG.trace("Published management-node health: {}", memento);
+ }
+
+ /**
+ * Publishes (via {@link #persister}) the state of this management node with itself set to master.
+ */
+ protected synchronized void publishPromotionToMaster() {
+ checkState(getNodeState() == ManagementNodeState.MASTER, "node status must be master on publish, but is %s", getNodeState());
+
+ if (persister == null) {
+ LOG.info("Cannot publish management-node health as no persister");
+ return;
+ }
+
+ ManagementNodeSyncRecord memento = createManagementNodeSyncRecord(false);
+ Delta delta = ManagementPlaneSyncRecordDeltaImpl.builder()
+ .node(memento)
+ .setMaster(ownNodeId)
+ .build();
+ persister.delta(delta);
+ if (LOG.isTraceEnabled()) LOG.trace("Published management-node health: {}", memento);
+ }
+
+ protected boolean isHeartbeatOk(ManagementNodeSyncRecord masterNode, ManagementNodeSyncRecord meNode) {
+ if (masterNode==null) return false;
+ if (meNode==null) {
+ // we can't confirm it's healthy, but it appears so as far as we can tell
+ return true;
+ }
+ Long timestampMaster = masterNode.getRemoteTimestamp();
+ Long timestampMe = meNode.getRemoteTimestamp();
+ if (timestampMaster==null || timestampMe==null) return false;
+ return (timestampMe - timestampMaster) <= getHeartbeatTimeout().toMilliseconds();
+ }
+
+ protected ManagementNodeSyncRecord hasHealthyMaster() {
+ ManagementPlaneSyncRecord memento = loadManagementPlaneSyncRecord(false);
+
+ String nodeId = memento.getMasterNodeId();
+ ManagementNodeSyncRecord masterMemento = (nodeId == null) ? null : memento.getManagementNodes().get(nodeId);
+
+ ManagementNodeSyncRecord ourMemento = memento.getManagementNodes().get(ownNodeId);
+ boolean result = masterMemento != null && masterMemento.getStatus() == ManagementNodeState.MASTER
+ && isHeartbeatOk(masterMemento, ourMemento);
+
+ if (LOG.isDebugEnabled()) LOG.debug("Healthy-master check result={}; masterId={}; masterMemento={}; ourMemento={}",
+ new Object[] {result, nodeId, (masterMemento == null ? "<none>" : masterMemento.toVerboseString()), (ourMemento == null ? "<none>" : ourMemento.toVerboseString())});
+
+ return (result ? masterMemento : null);
+ }
+
+ /**
+ * Looks up the state of all nodes in the management plane, and checks if the master is still ok.
+ * If it's not then determines which node should be promoted to master. If it is ourself, then promotes.
+ */
+ protected void checkMaster(boolean initializing) {
+ ManagementPlaneSyncRecord memento = loadManagementPlaneSyncRecord(false);
+
+ if (getNodeState()==ManagementNodeState.FAILED || getNodeState()==ManagementNodeState.HOT_BACKUP) {
+ // if failed or hot backup then we can't promote ourselves, so no point in checking who is master
+ return;
+ }
+
+ String currMasterNodeId = memento.getMasterNodeId();
+ ManagementNodeSyncRecord currMasterNodeRecord = memento.getManagementNodes().get(currMasterNodeId);
+ ManagementNodeSyncRecord ownNodeRecord = memento.getManagementNodes().get(ownNodeId);
+
+ ManagementNodeSyncRecord newMasterNodeRecord = null;
+ boolean demotingSelfInFavourOfOtherMaster = false;
+
+ if (currMasterNodeRecord != null && currMasterNodeRecord.getStatus() == ManagementNodeState.MASTER && isHeartbeatOk(currMasterNodeRecord, ownNodeRecord)) {
+ // master seems healthy
+ if (ownNodeId.equals(currMasterNodeId)) {
+ if (LOG.isTraceEnabled()) LOG.trace("Existing master healthy (us): master={}", currMasterNodeRecord.toVerboseString());
+ return;
+ } else {
+ if (ownNodeRecord!=null && ownNodeRecord.getStatus() == ManagementNodeState.MASTER) {
+ LOG.error("Management node "+ownNodeId+" detected master change, stolen from us, deferring to "+currMasterNodeId);
+ newMasterNodeRecord = currMasterNodeRecord;
+ demotingSelfInFavourOfOtherMaster = true;
+ } else {
+ if (LOG.isTraceEnabled()) LOG.trace("Existing master healthy (remote): master={}", currMasterNodeRecord.toVerboseString());
+ return;
+ }
+ }
+ } else if (ownNodeRecord == null || !isHeartbeatOk(ownNodeRecord, ownNodeRecord)) {
+ // our heartbeats are also out-of-date! perhaps something wrong with persistence? just log, and don't over-react!
+ if (ownNodeRecord == null) {
+ LOG.error("No management node memento for self ("+ownNodeId+"); perhaps persister unwritable? "
+ + "Master ("+currMasterNodeId+") reported failed but no-op as cannot tell conclusively");
+ } else {
+ LOG.error("This management node ("+ownNodeId+") memento heartbeats out-of-date; perhaps perister unwritable? "
+ + "Master ("+currMasterNodeId+") reported failed but no-op as cannot tell conclusively"
+ + ": self="+ownNodeRecord.toVerboseString());
+ }
+ return;
+ } else if (ownNodeId.equals(currMasterNodeId)) {
+ // we are supposed to be the master, but seem to be unhealthy!
+ LOG.warn("This management node ("+ownNodeId+") supposed to be master but reportedly unhealthy? "
+ + "no-op as expect other node to fix: self="+ownNodeRecord.toVerboseString());
+ return;
+ }
+
+ if (demotingSelfInFavourOfOtherMaster) {
+ LOG.debug("Master-change for this node only, demoting "+ownNodeRecord.toVerboseString()+" in favour of official master "+newMasterNodeRecord.toVerboseString());
+ demoteTo(
+ BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY) ?
+ ManagementNodeState.HOT_STANDBY : ManagementNodeState.STANDBY);
+ return;
+ } else {
+ LOG.debug("Detected master heartbeat timeout. Initiating a new master election. Master was " + currMasterNodeRecord);
+ }
+
+ // Need to choose a new master
+ newMasterNodeRecord = masterChooser.choose(memento, getHeartbeatTimeout(), ownNodeId);
+
+ String newMasterNodeId = (newMasterNodeRecord == null) ? null : newMasterNodeRecord.getNodeId();
+ URI newMasterNodeUri = (newMasterNodeRecord == null) ? null : newMasterNodeRecord.getUri();
+ boolean weAreNewMaster = ownNodeId.equals(newMasterNodeId);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Management node master-change required: newMaster={}; oldMaster={}; plane={}, self={}; heartbeatTimeout={}",
+ new Object[] {
+ (newMasterNodeRecord == null ? "<none>" : newMasterNodeRecord.toVerboseString()),
+ (currMasterNodeRecord == null ? currMasterNodeId+" (no memento)": currMasterNodeRecord.toVerboseString()),
+ memento,
+ ownNodeRecord.toVerboseString(),
+ getHeartbeatTimeout()
+ });
+ }
+ String message = "Management node "+ownNodeId+" detected ";
+ String currMasterSummary = currMasterNodeId + "(" + (currMasterNodeRecord==null ? "<none>" : timestampString(currMasterNodeRecord.getRemoteTimestamp())) + ")";
+ if (weAreNewMaster && (ownNodeRecord.getStatus() == ManagementNodeState.MASTER)) {
+ LOG.warn(message + "we must reassert master status, as was stolen and then failed at "+
+ (currMasterNodeRecord==null ? "a node which has gone away" : currMasterSummary));
+ publishPromotionToMaster();
+ publishHealth();
+ return;
+ }
+
+ if (!initializing) {
+ if (weAreNewMaster) {
+ message += "we should be master, changing from ";
+ }
+ else if (currMasterNodeRecord==null && newMasterNodeId==null) message += "master change attempted but no candidates ";
+ else message += "master change, from ";
+ message += currMasterSummary + " to "
+ + (newMasterNodeId == null ? "<none>" :
+ (weAreNewMaster ? "us " : "")
+ + newMasterNodeId + " (" + timestampString(newMasterNodeRecord.getRemoteTimestamp()) + ")"
+ + (newMasterNodeUri!=null ? " "+newMasterNodeUri : "") );
+ // always log, if you're looking at a standby node it's useful to see the new master's URL
+ LOG.info(message);
+ }
+
+ // New master is ourself: promote
+ if (weAreNewMaster) {
+ promoteToMaster();
+ }
+ }
+
+ private static String timestampString(Long remoteTimestamp) {
+ if (remoteTimestamp==null) return null;
+ return remoteTimestamp+" / "+Time.makeTimeStringRounded( Duration.sinceUtc(remoteTimestamp))+" ago";
+ }
+
+ protected void promoteToMaster() {
+ if (!running) {
+ LOG.warn("Ignoring promote-to-master request, as HighAvailabilityManager is not running");
+ return;
+ }
+
+ if (promotionListener != null) {
+ try {
+ promotionListener.promotingToMaster();
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ LOG.warn("Problem in promption-listener (continuing)", e);
+ }
+ }
+ setInternalNodeState(ManagementNodeState.MASTER);
+ publishPromotionToMaster();
+ try {
+ managementContext.getRebindManager().rebind(managementContext.getCatalogClassLoader(), null, getInternalNodeState());
+ } catch (Exception e) {
+ LOG.error("Management node "+managementContext.getManagementNodeId()+" enountered problem during rebind when promoting self to master; demoting to FAILED and rethrowing: "+e);
+ demoteTo(ManagementNodeState.FAILED);
+ throw Exceptions.propagate(e);
+ }
+ managementContext.getRebindManager().start();
+ }
+
+ protected void backupOnDemotionIfNeeded() {
+ if (managementContext.getBrooklynProperties().getConfig(BrooklynServerConfig.PERSISTENCE_BACKUPS_REQUIRED_ON_DEMOTION)) {
+ BrooklynPersistenceUtils.createBackup(managementContext, CreateBackupMode.DEMOTION, MementoCopyMode.LOCAL);
+ }
+ }
+
+ /** @deprecated since 0.7.0, use {@link #demoteTo(ManagementNodeState)} */ @Deprecated
+ protected void demoteToFailed() {
+ demoteTo(ManagementNodeState.FAILED);
+ }
+ /** @deprecated since 0.7.0, use {@link #demoteTo(ManagementNodeState)} */ @Deprecated
+ protected void demoteToStandby(boolean hot) {
+ demoteTo(hot ? ManagementNodeState.HOT_STANDBY : ManagementNodeState.STANDBY);
+ }
+
+ protected void demoteTo(ManagementNodeState toState) {
+ if (toState!=ManagementNodeState.FAILED && !running) {
+ LOG.warn("Ignoring demote-from-master request, as HighAvailabilityManager is no longer running");
+ return;
+ }
+ boolean wasMaster = (getInternalNodeState() == ManagementNodeState.MASTER);
+ if (wasMaster) backupOnDemotionIfNeeded();
+ // TODO target may be RO ?
+ ManagementTransitionMode mode = ManagementTransitionMode.transitioning(
+ wasMaster ? BrooklynObjectManagementMode.MANAGED_PRIMARY : BrooklynObjectManagementMode.LOADED_READ_ONLY,
+ BrooklynObjectManagementMode.UNMANAGED_PERSISTED);
+
+ nodeStateTransitionComplete = false;
+
+ switch (toState) {
+ case FAILED:
+ case HOT_BACKUP:
+ case STANDBY:
+ setInternalNodeState(toState); break;
+ case HOT_STANDBY:
+ setInternalNodeState(ManagementNodeState.STANDBY); break;
+ default:
+ throw new IllegalStateException("Illegal target state: "+toState);
+ }
+ onDemotionStopItems(mode);
+ nodeStateTransitionComplete = true;
+ publishDemotion(wasMaster);
+
+ if (toState==ManagementNodeState.HOT_BACKUP || toState==ManagementNodeState.HOT_STANDBY) {
+ nodeStateTransitionComplete = false;
+ try {
+ activateHotProxy(toState).get();
+ } finally {
+ nodeStateTransitionComplete = true;
+ }
+ publishHealth();
+ }
+ }
+
+ protected void onDemotionStopItems(ManagementTransitionMode mode) {
+ // stop persistence and remove all apps etc
+ managementContext.getRebindManager().stopPersistence();
+ managementContext.getRebindManager().stopReadOnly();
+ clearManagedItems(mode);
+
+ // tasks are cleared as part of unmanaging entities above
+ }
+
+ /** clears all managed items from the management context; same items destroyed as in the course of a rebind cycle */
+ protected void clearManagedItems(ManagementTransitionMode mode) {
+ // start with the root applications
+ for (Application app: managementContext.getApplications()) {
+ if (((EntityInternal)app).getManagementSupport().isDeployed()) {
+ ((LocalEntityManager)((EntityInternal)app).getManagementContext().getEntityManager()).unmanage(app, mode);
+ }
+ }
+ // for active management, call above will remove recursively at present,
+ // but for read-only, and if we stop recursively, go through them all
+ for (Entity entity: managementContext.getEntityManager().getEntities()) {
+ ((LocalEntityManager)managementContext.getEntityManager()).unmanage(entity, mode);
+ }
+
+ // again, for locations, call unmanage on parents first
+ for (Location loc: managementContext.getLocationManager().getLocations()) {
+ if (loc.getParent()==null)
+ ((LocationManagerInternal)managementContext.getLocationManager()).unmanage(loc, mode);
+ }
+ for (Location loc: managementContext.getLocationManager().getLocations()) {
+ ((LocationManagerInternal)managementContext.getLocationManager()).unmanage(loc, mode);
+ }
+
+ ((BasicBrooklynCatalog)managementContext.getCatalog()).reset(CatalogDto.newEmptyInstance("<reset-by-ha-status-change>"));
+ }
+
+ /** @deprecated since 0.7.0, use {@link #activateHotProxy(ManagementNodeState)} */ @Deprecated
+ protected boolean attemptHotStandby() {
+ return activateHotProxy(ManagementNodeState.HOT_STANDBY).getWithoutError();
+ }
+
+ /** Starts hot standby or hot backup, in foreground
+ * <p>
+ * In the case of the former, the caller is responsible for publishing health afterwards,
+ * but if it fails, this method will {@link #demoteTo(ManagementNodeState)} {@link ManagementNodeState#FAILED}.
+ * <p>
+ * @return whether the requested {@link ManagementNodeState} was possible;
+ * (if not, errors should be stored elsewhere), callers may want to rethrow */
+ protected ReferenceWithError<Boolean> activateHotProxy(ManagementNodeState toState) {
+ try {
+ Preconditions.checkState(nodeStateTransitionComplete==false, "Must be in transitioning state to go into "+toState);
+ setInternalNodeState(toState);
+ managementContext.getRebindManager().startReadOnly(toState);
+
+ return ReferenceWithError.newInstanceWithoutError(true);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ LOG.warn("Unable to change "+ownNodeId+" to "+toState+", switching to FAILED: "+e, e);
+ demoteTo(ManagementNodeState.FAILED);
+ return ReferenceWithError.newInstanceThrowingError(false, e);
+ }
+ }
+
+ @Override
+ public ManagementPlaneSyncRecord loadManagementPlaneSyncRecord(boolean useLocalKnowledgeForThisNode) {
+ ManagementPlaneSyncRecord record = loadManagementPlaneSyncRecordInternal(useLocalKnowledgeForThisNode);
+ lastSyncRecord = record;
+ return record;
+ }
+
+ private ManagementPlaneSyncRecord loadManagementPlaneSyncRecordInternal(boolean useLocalKnowledgeForThisNode) {
+ if (disabled) {
+ // if HA is disabled, then we are the only node - no persistence; just load a memento to describe this node
+ Builder builder = ManagementPlaneSyncRecordImpl.builder()
+ .node(createManagementNodeSyncRecord(true));
+ if (getTransitionTargetNodeState() == ManagementNodeState.MASTER) {
+ builder.masterNodeId(ownNodeId);
+ }
+ return builder.build();
+ }
+ if (persister == null) {
+ // e.g. web-console may be polling before we've started up
+ LOG.debug("High availablity manager has no persister; returning empty record");
+ return ManagementPlaneSyncRecordImpl.builder().build();
+ }
+
+ int maxLoadAttempts = 5;
+ Exception lastException = null;
+ Stopwatch timer = Stopwatch.createStarted();
+
+ for (int i = 0; i < maxLoadAttempts; i++) {
+ try {
+ ManagementPlaneSyncRecord result = persister.loadSyncRecord();
+
+ if (useLocalKnowledgeForThisNode) {
+ // Report this node's most recent state, and detect AWOL nodes
+ ManagementNodeSyncRecord me = BasicManagementNodeSyncRecord.builder()
+ .from(result.getManagementNodes().get(ownNodeId), true)
+ .from(createManagementNodeSyncRecord(false), true)
+ .build();
+ Iterable<ManagementNodeSyncRecord> allNodes = result.getManagementNodes().values();
+ if (me.getRemoteTimestamp()!=null)
+ allNodes = Iterables.transform(allNodes, new MarkAwolNodes(me));
+ Builder builder = ManagementPlaneSyncRecordImpl.builder()
+ .masterNodeId(result.getMasterNodeId())
+ .nodes(allNodes);
+ builder.node(me);
+ if (getTransitionTargetNodeState() == ManagementNodeState.MASTER) {
+ builder.masterNodeId(ownNodeId);
+ }
+ result = builder.build();
+ }
+
+ if (i>0) {
+ managementStateReadPersistenceMetrics.noteError("Succeeded only on attempt "+(i+1)+": "+lastException);
+ }
+ managementStateReadPersistenceMetrics.noteSuccess(Duration.of(timer));
+ return result;
+ } catch (IOException e) {
+ if (i < (maxLoadAttempts - 1)) {
+ if (LOG.isDebugEnabled()) LOG.debug("Problem loading mangement-plane memento attempt "+(i+1)+"/"+maxLoadAttempts+"; retrying", e);
+ }
+ lastException = e;
+ }
+ }
+ String message = "Failed to load mangement-plane memento "+maxLoadAttempts+" consecutive times";
+ managementStateReadPersistenceMetrics.noteError(message+": "+lastException);
+ managementStateReadPersistenceMetrics.noteFailure(Duration.of(timer));
+
+ throw new IllegalStateException(message, lastException);
+ }
+
+ protected ManagementNodeSyncRecord createManagementNodeSyncRecord(boolean useLocalTimestampAsRemoteTimestamp) {
+ long timestamp = currentTimeMillis();
+ brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord.Builder builder = BasicManagementNodeSyncRecord.builder()
+ .brooklynVersion(BrooklynVersion.get())
+ .nodeId(ownNodeId)
+ .status(getNodeState())
+ .priority(getPriority())
+ .localTimestamp(timestamp)
+ .uri(managementContext.getManagementNodeUri().orNull());
+ if (useLocalTimestampAsRemoteTimestamp)
+ builder.remoteTimestamp(timestamp);
+ else if (optionalRemoteTickerUtc!=null) {
+ builder.remoteTimestamp(optionalRemoteTickerUtc.read());
+ }
+ return builder.build();
+ }
+
+ /**
+ * Gets the current time, using the {@link #localTickerUtc}. Normally this is equivalent of {@link System#currentTimeMillis()},
+ * but in test environments a custom {@link Ticker} can be injected via {@link #setLocalTicker(Ticker)} to allow testing of
+ * specific timing scenarios.
+ */
+ protected long currentTimeMillis() {
+ return localTickerUtc.read();
+ }
+
+ /**
+ * Infers the health of a node - if it last reported itself as healthy (standby or master), but we haven't heard
+ * from it in a long time then report that node as failed; otherwise report its health as-is.
+ */
+ private class MarkAwolNodes implements Function<ManagementNodeSyncRecord, ManagementNodeSyncRecord> {
+ private final ManagementNodeSyncRecord referenceNode;
+ private MarkAwolNodes(ManagementNodeSyncRecord referenceNode) {
+ this.referenceNode = referenceNode;
+ }
+ @Nullable
+ @Override
+ public ManagementNodeSyncRecord apply(@Nullable ManagementNodeSyncRecord input) {
+ if (input == null) return null;
+ if (!(input.getStatus() == ManagementNodeState.STANDBY || input.getStatus() == ManagementNodeState.HOT_STANDBY || input.getStatus() == ManagementNodeState.MASTER || input.getStatus() == ManagementNodeState.HOT_BACKUP)) return input;
+ if (isHeartbeatOk(input, referenceNode)) return input;
+ return BasicManagementNodeSyncRecord.builder()
+ .from(input)
+ .status(ManagementNodeState.FAILED)
+ .build();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"[node:"+ownNodeId+";running="+running+"]";
+ }
+
+ @Override
+ public Map<String,Object> getMetrics() {
+ Map<String,Object> result = MutableMap.of();
+
+ result.put("state", getNodeState());
+ result.put("uptime", Time.makeTimeStringRounded(Duration.millis(currentTimeMillis()-startTimeUtc)));
+ result.put("currentTimeUtc", currentTimeMillis());
+ result.put("startTimeUtc", startTimeUtc);
+ result.put("highAvailability", MutableMap.<String,Object>of(
+ "priority", getPriority(),
+ "pollPeriod", getPollPeriod().toMilliseconds(),
+ "heartbeatTimeout", getHeartbeatTimeout().toMilliseconds(),
+ "history", nodeStateHistory));
+
+ result.putAll(managementContext.getRebindManager().getMetrics());
+ result.put("managementStatePersistence",
+ MutableMap.of("read", managementStateReadPersistenceMetrics, "write", managementStateWritePersistenceMetrics));
+
+ return result;
+ }
+
+ @Override
+ public long getLastStateChange() {
+ if (nodeStateHistory.size() > 0) {
+ return (Long)nodeStateHistory.get(0).get("timestamp");
+ } else {
+ return 0;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordDeltaImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordDeltaImpl.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordDeltaImpl.java
new file mode 100644
index 0000000..1ae4ea7
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordDeltaImpl.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Collection;
+
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister.Delta;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Sets;
+
+/**
+ * @since 0.7.0
+ *
+ * @author aled
+ */
+@Beta
+public class ManagementPlaneSyncRecordDeltaImpl implements Delta {
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private Collection<ManagementNodeSyncRecord> nodes = Sets.newLinkedHashSet();
+ private Collection <String> removedNodeIds = Sets.newLinkedHashSet();
+ private MasterChange masterChange = MasterChange.NO_CHANGE;
+ private String master;
+ private String expectedOldMaster;
+
+ public Builder node(ManagementNodeSyncRecord node) {
+ nodes.add(checkNotNull(node, "node")); return this;
+ }
+ public Builder removedNodeId(String id) {
+ removedNodeIds.add(checkNotNull(id, "id")); return this;
+ }
+ public Builder setMaster(String nodeId) {
+ masterChange = MasterChange.SET_MASTER;
+ master = checkNotNull(nodeId, "masterId");
+ return this;
+ }
+ public Builder clearMaster(String optionalExpectedNodeId) {
+ masterChange = MasterChange.CLEAR_MASTER;
+ this.expectedOldMaster = optionalExpectedNodeId;
+ return this;
+ }
+ public Delta build() {
+ return new ManagementPlaneSyncRecordDeltaImpl(this);
+ }
+ }
+
+ private final Collection<ManagementNodeSyncRecord> nodes;
+ private final Collection <String> removedNodeIds;
+ private final MasterChange masterChange;
+ private String masterId;
+ private String expectedOldMaster;
+
+ ManagementPlaneSyncRecordDeltaImpl(Builder builder) {
+ nodes = builder.nodes;
+ removedNodeIds = builder.removedNodeIds;
+ masterChange = builder.masterChange;
+ masterId = builder.master;
+ this.expectedOldMaster = builder.expectedOldMaster;
+ checkState((masterChange == MasterChange.SET_MASTER) ? (masterId != null) : (masterId == null),
+ "invalid combination: change=%s; masterId=%s", masterChange, masterId);
+ }
+
+ @Override
+ public Collection<ManagementNodeSyncRecord> getNodes() {
+ return nodes;
+ }
+
+ @Override
+ public Collection<String> getRemovedNodeIds() {
+ return removedNodeIds;
+ }
+
+ @Override
+ public MasterChange getMasterChange() {
+ return masterChange;
+ }
+
+ @Override
+ public String getNewMasterOrNull() {
+ return masterId;
+ }
+
+ @Override
+ public String getExpectedMasterToClear() {
+ return expectedOldMaster;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getCanonicalName()+"["+
+ (masterChange!=null && masterChange != MasterChange.NO_CHANGE ?
+ masterChange+": "+expectedOldMaster+"->"+masterId+"; " : "")+
+ "nodes: "+nodes+
+ (removedNodeIds!=null && !removedNodeIds.isEmpty() ? "; removing: "+removedNodeIds : "")
+ +"]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java
new file mode 100644
index 0000000..7f188be
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java
@@ -0,0 +1,355 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.rebind.persister.MementoSerializer;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore.StoreObjectAccessorWithLock;
+import brooklyn.entity.rebind.persister.RetryingMementoSerializer;
+import brooklyn.entity.rebind.persister.StoreObjectAccessorLocking;
+import brooklyn.entity.rebind.persister.XmlMementoSerializer;
+import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
+import brooklyn.entity.rebind.plane.dto.ManagementPlaneSyncRecordImpl;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Maps;
+
+/**
+ * Structure of files is:
+ * <ul>
+ * <li>{@code plane/} - top-level directory
+ * <ul>
+ * <li>{@code master} - contains the id of the management-node that is currently master
+ * <li>{@code change.log} - log of changes made
+ * <li>{@code nodes/} - sub-directory, containing one file per management-node
+ * <ul>
+ * <li>{@code a9WiuVKp} - file named after the management-node's id, containing the management node's current state
+ * <li>{@code E1eDXQF3}
+ * </ul>
+ * </ul>
+ * </ul>
+ *
+ * All writes are done synchronously.
+ *
+ * @since 0.7.0
+ *
+ * @author aled
+ */
+@Beta
+public class ManagementPlaneSyncRecordPersisterToObjectStore implements ManagementPlaneSyncRecordPersister {
+
+ // TODO Multiple node appending to change.log could cause strange interleaving, or perhaps even data loss?
+ // But this file is not critical to functionality.
+
+ // TODO Should ManagementPlaneSyncRecordPersister.Delta be different so can tell what is a significant event,
+ // and thus log it in change.log - currently only subset of significant things being logged.
+
+ private static final Logger LOG = LoggerFactory.getLogger(ManagementPlaneSyncRecordPersisterToObjectStore.class);
+
+ private static final Duration SHUTDOWN_TIMEOUT = Duration.TEN_SECONDS;
+ private static final Duration SYNC_WRITE_TIMEOUT = Duration.TEN_SECONDS;
+ public static final String NODES_SUB_PATH = "nodes";
+
+ // TODO Leak if we go through lots of managers; but tiny!
+ private final ConcurrentMap<String, StoreObjectAccessorWithLock> nodeWriters = Maps.newConcurrentMap();
+
+ private StoreObjectAccessorWithLock masterWriter;
+ private StoreObjectAccessorWithLock changeLogWriter;
+
+ private ManagementContext mgmt;
+ private final PersistenceObjectStore objectStore;
+ private final MementoSerializer<Object> serializer;
+
+ private static final int MAX_SERIALIZATION_ATTEMPTS = 5;
+
+ private boolean started = false;
+ private volatile boolean running = true;
+
+ @VisibleForTesting
+ /** allows, when testing, to be able to override file times / blobstore times with time from the ticker */
+ private boolean preferRemoteTimestampInMemento = false;
+
+ /**
+ * @param mgmt not used much at present but handy to ensure we know it so that obj store is prepared
+ * @param objectStore the objectStore use to read/write management-plane data;
+ * this must have been {@link PersistenceObjectStore#prepareForSharedUse(brooklyn.entity.rebind.persister.PersistMode, HighAvailabilityMode)}
+ * @param classLoader ClassLoader to use when deserializing data
+ */
+ public ManagementPlaneSyncRecordPersisterToObjectStore(ManagementContext mgmt, PersistenceObjectStore objectStore, ClassLoader classLoader) {
+ this.mgmt = mgmt;
+ this.objectStore = checkNotNull(objectStore, "objectStore");
+
+ MementoSerializer<Object> rawSerializer = new XmlMementoSerializer<Object>(checkNotNull(classLoader, "classLoader"));
+ this.serializer = new RetryingMementoSerializer<Object>(rawSerializer, MAX_SERIALIZATION_ATTEMPTS);
+
+ objectStore.createSubPath(NODES_SUB_PATH);
+
+ LOG.debug("ManagementPlaneMemento-persister will use store "+objectStore);
+ }
+
+ protected synchronized void init() {
+ if (!started) {
+ started = true;
+ //Leading slash causes problems in SL, it's not a correct file name so remove it.
+ //But once removed we can't load the master file from existing persistence stores.
+ //Try to detect if the old file exists, if so use old-style names, otherwise use the correct names.
+ masterWriter = new StoreObjectAccessorLocking(objectStore.newAccessor("/master"));
+ if (masterWriter.get() != null) {
+ changeLogWriter = new StoreObjectAccessorLocking(objectStore.newAccessor("/change.log"));
+ } else {
+ masterWriter = new StoreObjectAccessorLocking(objectStore.newAccessor("master"));
+ changeLogWriter = new StoreObjectAccessorLocking(objectStore.newAccessor("change.log"));
+ }
+ }
+ }
+
+ @VisibleForTesting
+ public void preferRemoteTimestampInMemento() {
+ preferRemoteTimestampInMemento = true;
+ }
+
+ @Override
+ public void stop() {
+ running = false;
+ try {
+ for (StoreObjectAccessorWithLock writer : nodeWriters.values()) {
+ try {
+ writer.waitForCurrentWrites(SHUTDOWN_TIMEOUT);
+ } catch (TimeoutException e) {
+ LOG.warn("Timeout during shutdown, waiting for write of "+writer+"; continuing");
+ }
+ }
+ try {
+ masterWriter.waitForCurrentWrites(SHUTDOWN_TIMEOUT);
+ } catch (TimeoutException e) {
+ LOG.warn("Timeout during shutdown, waiting for write of "+masterWriter+"; continuing");
+ }
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public ManagementPlaneSyncRecord loadSyncRecord() throws IOException {
+ if (!running) {
+ throw new IllegalStateException("Persister not running; cannot load memento from "+ objectStore.getSummaryName());
+ }
+ init();
+
+ // Note this is called a lot - every time we check the heartbeats
+ if (LOG.isTraceEnabled()) LOG.trace("Loading management-plane memento from {}", objectStore.getSummaryName());
+
+ Stopwatch stopwatch = Stopwatch.createStarted();
+
+ ManagementPlaneSyncRecordImpl.Builder builder = ManagementPlaneSyncRecordImpl.builder();
+
+ // Be careful about order: if the master-file says nodeX then nodeX's file must have an up-to-date timestamp.
+ // Therefore read master file first, followed by the other node-files.
+ String masterNodeId = masterWriter.get();
+ if (masterNodeId == null) {
+ LOG.debug("No master-memento deserialized from file "+masterWriter+"; ignoring and continuing (normal on startup, should cause an error later in live operation)");
+ } else {
+ builder.masterNodeId(masterNodeId);
+ }
+
+ // Load node-files
+ List<String> nodeFiles = objectStore.listContentsWithSubPath(NODES_SUB_PATH);
+ LOG.trace("Loading nodes from {}; {} nodes.",
+ new Object[]{objectStore.getSummaryName(), nodeFiles.size()});
+
+ for (String nodeFile : nodeFiles) {
+ PersistenceObjectStore.StoreObjectAccessor objectAccessor = objectStore.newAccessor(nodeFile);
+ String nodeContents = null;
+ Exception problem = null;
+ try {
+ nodeContents = objectAccessor.get();
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ problem = e;
+ }
+ if (problem!=null || Strings.isBlank(nodeContents)) {
+ // happens if node has gone away, or if FileBasedObjectStore.moveFile is not atomic,
+ // i.e. it has deleted but not updated it yet
+ if (objectAccessor.exists()) {
+ throw Exceptions.propagate(new IllegalStateException("Node record "+nodeFile+" could not be read when "+mgmt.getManagementNodeId()+" was scanning", problem));
+ } else {
+ LOG.warn("Node record "+nodeFile+" went away while "+mgmt.getManagementNodeId()+" was scanning, ignoring (it has probably been terminated)");
+ // if file was deleted, silently ignore
+ continue;
+ }
+ }
+ ManagementNodeSyncRecord memento = (ManagementNodeSyncRecord) serializer.fromString(nodeContents);
+ if (memento == null) {
+ // shouldn't happen
+ throw Exceptions.propagate(new IllegalStateException("Node record "+nodeFile+" could not be deserialized when "+mgmt.getManagementNodeId()+" was scanning: "+nodeContents, problem));
+ } else {
+ if (memento.getRemoteTimestamp()!=null && preferRemoteTimestampInMemento) {
+ // in test mode, the remote timestamp is stored in the file
+ } else {
+ if (memento.getRemoteTimestamp()!=null) {
+ LOG.debug("Ignoring remote timestamp in memento file ("+memento+"); looks like this data has been manually copied in");
+ }
+ Date lastModifiedDate = objectAccessor.getLastModifiedDate();
+ ((BasicManagementNodeSyncRecord)memento).setRemoteTimestamp(lastModifiedDate!=null ? lastModifiedDate.getTime() : null);
+ }
+ builder.node(memento);
+ }
+ }
+
+ if (LOG.isDebugEnabled()) LOG.trace("Loaded management-plane memento; {} nodes, took {}",
+ nodeFiles.size(),
+ Time.makeTimeStringRounded(stopwatch.elapsed(TimeUnit.MILLISECONDS)));
+ return builder.build();
+ }
+
+ @Override
+ public void delta(Delta delta) {
+ if (!running) {
+ if (LOG.isDebugEnabled()) LOG.debug("Persister not running; ignoring checkpointed delta of manager-memento");
+ return;
+ }
+ init();
+
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ if (LOG.isTraceEnabled()) LOG.trace("Checkpointing delta of manager-memento; updating {}", delta);
+
+ for (ManagementNodeSyncRecord m : delta.getNodes()) {
+ persist(m);
+ }
+ for (String id : delta.getRemovedNodeIds()) {
+ deleteNode(id);
+ }
+ switch (delta.getMasterChange()) {
+ case NO_CHANGE:
+ break; // no-op
+ case SET_MASTER:
+ persistMaster(checkNotNull(delta.getNewMasterOrNull()), null);
+ break;
+ case CLEAR_MASTER:
+ persistMaster("", delta.getExpectedMasterToClear());
+ break; // no-op
+ default:
+ throw new IllegalStateException("Unknown state for master-change: "+delta.getMasterChange());
+ }
+ if (LOG.isDebugEnabled()) LOG.debug("Checkpointed delta of manager-memento in "+Time.makeTimeStringRounded(stopwatch)+": "+delta);
+ }
+
+ private void persistMaster(String nodeId, String optionalExpectedId) {
+ if (optionalExpectedId!=null) {
+ String currentRemoteMaster = masterWriter.get();
+ if (currentRemoteMaster==null) {
+ // okay to have nothing at remote
+ } else if (!currentRemoteMaster.trim().equals(optionalExpectedId.trim())) {
+ LOG.warn("Master at server is "+(Strings.isBlank(currentRemoteMaster) ? "<none>" : currentRemoteMaster)+"; expected "+optionalExpectedId+" "
+ + (Strings.isNonBlank(nodeId) ? "and would set as "+nodeId : "and would clear")
+ + ", so not applying (yet)");
+ return;
+ }
+ }
+ masterWriter.put(nodeId);
+ try {
+ masterWriter.waitForCurrentWrites(SYNC_WRITE_TIMEOUT);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ changeLogWriter.append(Time.makeDateString() + ": set master to " + nodeId + "\n");
+ try {
+ changeLogWriter.waitForCurrentWrites(SYNC_WRITE_TIMEOUT);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ @VisibleForTesting
+ public void waitForWritesCompleted(Duration timeout) throws InterruptedException, TimeoutException {
+ for (StoreObjectAccessorWithLock writer : nodeWriters.values()) {
+ writer.waitForCurrentWrites(timeout);
+ }
+ masterWriter.waitForCurrentWrites(timeout);
+ }
+
+ public void checkpoint(ManagementPlaneSyncRecord record) {
+ init();
+ for (ManagementNodeSyncRecord node : record.getManagementNodes().values()) {
+ // Check included in case the node in the memento is the one being initialised by
+ // BrooklynLauncher in the copy state command.
+ if (!ManagementNodeState.INITIALIZING.equals(node.getStatus()) && node.getNodeId() != null) {
+ persist(node);
+ }
+ }
+ }
+
+ private void persist(ManagementNodeSyncRecord node) {
+ StoreObjectAccessorWithLock writer = getOrCreateNodeWriter(node.getNodeId());
+ boolean fileExists = writer.exists();
+ writer.put(serializer.toString(node));
+ try {
+ writer.waitForCurrentWrites(SYNC_WRITE_TIMEOUT);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ if (!fileExists) {
+ changeLogWriter.append(Time.makeDateString()+": created node "+node.getNodeId()+"\n");
+ }
+ if (node.getStatus() == ManagementNodeState.TERMINATED || node.getStatus() == ManagementNodeState.FAILED) {
+ changeLogWriter.append(Time.makeDateString()+": set node "+node.getNodeId()+" status to "+node.getStatus()+"\n");
+ }
+ }
+
+ private void deleteNode(String nodeId) {
+ getOrCreateNodeWriter(nodeId).delete();
+ changeLogWriter.append(Time.makeDateString()+": deleted node "+nodeId+"\n");
+ }
+
+ private StoreObjectAccessorWithLock getOrCreateNodeWriter(String nodeId) {
+ PersistenceObjectStore.StoreObjectAccessorWithLock writer = nodeWriters.get(nodeId);
+ if (writer == null) {
+ nodeWriters.putIfAbsent(nodeId,
+ new StoreObjectAccessorLocking(objectStore.newAccessor(NODES_SUB_PATH+"/"+nodeId)));
+ writer = nodeWriters.get(nodeId);
+ }
+ return writer;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/ha/MasterChooser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/MasterChooser.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/MasterChooser.java
new file mode 100644
index 0000000..2a2bd09
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/MasterChooser.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * For choosing which management node to promote, when master detected as failed or stopped.
+ *
+ * @since 0.7.0
+ *
+ * @author aled
+ */
+@Beta
+public interface MasterChooser {
+
+ ManagementNodeSyncRecord choose(ManagementPlaneSyncRecord memento, Duration heartbeatTimeout, String ownNodeId);
+
+}
[11/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java
new file mode 100644
index 0000000..99b79ec
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManager.java
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static brooklyn.util.JavaGroovyEquivalents.elvis;
+import static brooklyn.util.JavaGroovyEquivalents.groovyTruth;
+import static brooklyn.util.JavaGroovyEquivalents.join;
+import static brooklyn.util.JavaGroovyEquivalents.mapOf;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+import org.apache.brooklyn.api.management.SubscriptionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.util.task.BasicExecutionManager;
+import brooklyn.util.task.SingleThreadedScheduler;
+import brooklyn.util.text.Identifiers;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimaps;
+
+/**
+ * A {@link SubscriptionManager} that stores subscription details locally.
+ */
+public class LocalSubscriptionManager extends AbstractSubscriptionManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LocalSubscriptionManager.class);
+
+ protected final ExecutionManager em;
+
+ private final String tostring = "SubscriptionContext("+Identifiers.getBase64IdFromValue(System.identityHashCode(this), 5)+")";
+
+ private final AtomicLong totalEventsPublishedCount = new AtomicLong();
+ private final AtomicLong totalEventsDeliveredCount = new AtomicLong();
+
+ @SuppressWarnings("rawtypes")
+ protected final ConcurrentMap<String, Subscription> allSubscriptions = new ConcurrentHashMap<String, Subscription>();
+ @SuppressWarnings("rawtypes")
+ protected final ConcurrentMap<Object, Set<Subscription>> subscriptionsBySubscriber = new ConcurrentHashMap<Object, Set<Subscription>>();
+ @SuppressWarnings("rawtypes")
+ protected final ConcurrentMap<Object, Set<Subscription>> subscriptionsByToken = new ConcurrentHashMap<Object, Set<Subscription>>();
+
+ public LocalSubscriptionManager(ExecutionManager m) {
+ this.em = m;
+ }
+
+ public long getNumSubscriptions() {
+ return allSubscriptions.size();
+ }
+
+ public long getTotalEventsPublished() {
+ return totalEventsPublishedCount.get();
+ }
+
+ public long getTotalEventsDelivered() {
+ return totalEventsDeliveredCount.get();
+ }
+
+ @SuppressWarnings("unchecked")
+ protected synchronized <T> SubscriptionHandle subscribe(Map<String, Object> flags, Subscription<T> s) {
+ Entity producer = s.producer;
+ Sensor<T> sensor= s.sensor;
+ s.subscriber = getSubscriber(flags, s);
+ if (flags.containsKey("subscriberExecutionManagerTag")) {
+ s.subscriberExecutionManagerTag = flags.remove("subscriberExecutionManagerTag");
+ s.subscriberExecutionManagerTagSupplied = true;
+ } else {
+ s.subscriberExecutionManagerTag =
+ s.subscriber instanceof Entity ? "subscription-delivery-entity-"+((Entity)s.subscriber).getId()+"["+s.subscriber+"]" :
+ s.subscriber instanceof String ? "subscription-delivery-string["+s.subscriber+"]" :
+ "subscription-delivery-object["+s.subscriber+"]";
+ s.subscriberExecutionManagerTagSupplied = false;
+ }
+ s.eventFilter = (Predicate<SensorEvent<T>>) flags.remove("eventFilter");
+ s.flags = flags;
+
+ if (LOG.isDebugEnabled()) LOG.debug("Creating subscription {} for {} on {} {} in {}", new Object[] {s.id, s.subscriber, producer, sensor, this});
+ allSubscriptions.put(s.id, s);
+ addToMapOfSets(subscriptionsByToken, makeEntitySensorToken(s.producer, s.sensor), s);
+ if (s.subscriber!=null) {
+ addToMapOfSets(subscriptionsBySubscriber, s.subscriber, s);
+ }
+ if (!s.subscriberExecutionManagerTagSupplied && s.subscriberExecutionManagerTag!=null) {
+ ((BasicExecutionManager) em).setTaskSchedulerForTag(s.subscriberExecutionManagerTag, SingleThreadedScheduler.class);
+ }
+ return s;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Set<SubscriptionHandle> getSubscriptionsForSubscriber(Object subscriber) {
+ return (Set<SubscriptionHandle>) ((Set<?>) elvis(subscriptionsBySubscriber.get(subscriber), Collections.emptySet()));
+ }
+
+ public synchronized Set<SubscriptionHandle> getSubscriptionsForEntitySensor(Entity source, Sensor<?> sensor) {
+ Set<SubscriptionHandle> subscriptions = new LinkedHashSet<SubscriptionHandle>();
+ subscriptions.addAll(elvis(subscriptionsByToken.get(makeEntitySensorToken(source, sensor)), Collections.emptySet()));
+ subscriptions.addAll(elvis(subscriptionsByToken.get(makeEntitySensorToken(null, sensor)), Collections.emptySet()));
+ subscriptions.addAll(elvis(subscriptionsByToken.get(makeEntitySensorToken(source, null)), Collections.emptySet()));
+ subscriptions.addAll(elvis(subscriptionsByToken.get(makeEntitySensorToken(null, null)), Collections.emptySet()));
+ return subscriptions;
+ }
+
+ /**
+ * Unsubscribe the given subscription id.
+ *
+ * @see #subscribe(Map, Entity, Sensor, SensorEventListener)
+ */
+ @SuppressWarnings("rawtypes")
+ public synchronized boolean unsubscribe(SubscriptionHandle sh) {
+ if (!(sh instanceof Subscription)) throw new IllegalArgumentException("Only subscription handles of type Subscription supported: sh="+sh+"; type="+(sh != null ? sh.getClass().getCanonicalName() : null));
+ Subscription s = (Subscription) sh;
+ boolean result = allSubscriptions.remove(s.id) != null;
+ boolean b2 = removeFromMapOfCollections(subscriptionsByToken, makeEntitySensorToken(s.producer, s.sensor), s);
+ assert result==b2;
+ if (s.subscriber!=null) {
+ boolean b3 = removeFromMapOfCollections(subscriptionsBySubscriber, s.subscriber, s);
+ assert b3 == b2;
+ }
+
+ // FIXME ALEX - this seems wrong
+ ((BasicExecutionManager) em).setTaskSchedulerForTag(s.subscriberExecutionManagerTag, SingleThreadedScheduler.class);
+ return result;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public <T> void publish(final SensorEvent<T> event) {
+ // REVIEW 1459 - execution
+
+ // delivery in parallel/background, using execution manager
+
+ // subscriptions, should define SingleThreadedScheduler for any subscriber ID tag
+ // in order to ensure callbacks are invoked in the order they are submitted
+ // (recommend exactly one per subscription to prevent deadlock)
+ // this is done with:
+ // em.setTaskSchedulerForTag(subscriberId, SingleThreadedScheduler.class);
+
+ //note, generating the notifications must be done in the calling thread to preserve order
+ //e.g. emit(A); emit(B); should cause onEvent(A); onEvent(B) in that order
+ if (LOG.isTraceEnabled()) LOG.trace("{} got event {}", this, event);
+ totalEventsPublishedCount.incrementAndGet();
+
+ Set<Subscription> subs = (Set<Subscription>) ((Set<?>) getSubscriptionsForEntitySensor(event.getSource(), event.getSensor()));
+ if (groovyTruth(subs)) {
+ if (LOG.isTraceEnabled()) LOG.trace("sending {}, {} to {}", new Object[] {event.getSensor().getName(), event, join(subs, ",")});
+ for (Subscription s : subs) {
+ if (s.eventFilter!=null && !s.eventFilter.apply(event))
+ continue;
+ final Subscription sAtClosureCreation = s;
+
+// Set<Object> tags = MutableSet.of();
+// if (s.subscriberExecutionManagerTag!=null) tags.add(s.subscriberExecutionManagerTag);
+// if (event.getSource()!=null) tags.add(BrooklynTaskTags.tagForContextEntity(event.getSource()));
+// Map<String, Object> tagsMap = mapOf("tags", (Object)tags);
+ // use code above, instead of line below, if we want subscription deliveries associated with the entity;
+ // that will cause them to be cancelled when the entity is unmanaged
+ // (not sure that is useful, and likely NOT worth the expense, but it might be...) -Alex Oct 2014
+ Map<String, Object> tagsMap = mapOf("tag", s.subscriberExecutionManagerTag);
+
+ em.submit(tagsMap, new Runnable() {
+ @Override
+ public String toString() {
+ return "LSM.publish("+event+")";
+ }
+ public void run() {
+ try {
+ sAtClosureCreation.listener.onEvent(event);
+ } catch (Throwable t) {
+ if (event!=null && event.getSource()!=null && Entities.isNoLongerManaged(event.getSource())) {
+ LOG.debug("Error processing subscriptions to "+this+", after entity unmanaged: "+t, t);
+ } else {
+ LOG.warn("Error processing subscriptions to "+this+": "+t, t);
+ }
+ }
+ }});
+ totalEventsDeliveredCount.incrementAndGet();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return tostring;
+ }
+
+ /**
+ * Copied from LanguageUtils.groovy, to remove dependency.
+ *
+ * Adds the given value to a collection in the map under the key.
+ *
+ * A collection (as {@link LinkedHashMap}) will be created if necessary,
+ * synchronized on map for map access/change and set for addition there
+ *
+ * @return the updated set (instance, not copy)
+ *
+ * @deprecated since 0.5; use {@link HashMultimap}, and {@link Multimaps#synchronizedSetMultimap(com.google.common.collect.SetMultimap)}
+ */
+ @Deprecated
+ private static <K,V> Set<V> addToMapOfSets(Map<K,Set<V>> map, K key, V valueInCollection) {
+ Set<V> coll;
+ synchronized (map) {
+ coll = map.get(key);
+ if (coll==null) {
+ coll = new LinkedHashSet<V>();
+ map.put(key, coll);
+ }
+ if (coll.isEmpty()) {
+ synchronized (coll) {
+ coll.add(valueInCollection);
+ }
+ //if collection was empty then add to the collection while holding the map lock, to prevent removal
+ return coll;
+ }
+ }
+ synchronized (coll) {
+ if (!coll.isEmpty()) {
+ coll.add(valueInCollection);
+ return coll;
+ }
+ }
+ //if was empty, recurse, because someone else might be removing the collection
+ return addToMapOfSets(map, key, valueInCollection);
+ }
+
+ /**
+ * Copied from LanguageUtils.groovy, to remove dependency.
+ *
+ * Removes the given value from a collection in the map under the key.
+ *
+ * @return the updated set (instance, not copy)
+ *
+ * @deprecated since 0.5; use {@link ArrayListMultimap} or {@link HashMultimap}, and {@link Multimaps#synchronizedListMultimap(com.google.common.collect.ListMultimap)} etc
+ */
+ @Deprecated
+ private static <K,V> boolean removeFromMapOfCollections(Map<K,? extends Collection<V>> map, K key, V valueInCollection) {
+ Collection<V> coll;
+ synchronized (map) {
+ coll = map.get(key);
+ if (coll==null) return false;
+ }
+ boolean result;
+ synchronized (coll) {
+ result = coll.remove(valueInCollection);
+ }
+ if (coll.isEmpty()) {
+ synchronized (map) {
+ synchronized (coll) {
+ if (coll.isEmpty()) {
+ //only remove from the map if no one is adding to the collection or to the map, and the collection is still in the map
+ if (map.get(key)==coll) {
+ map.remove(key);
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java
new file mode 100644
index 0000000..dc95d11
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalUsageManager.java
@@ -0,0 +1,430 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage;
+import org.apache.brooklyn.core.management.usage.LocationUsage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.internal.storage.BrooklynStorage;
+
+import org.apache.brooklyn.location.basic.AbstractLocation;
+import org.apache.brooklyn.location.basic.LocationConfigKeys;
+import org.apache.brooklyn.location.basic.LocationInternal;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.javalang.Reflections;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+public class LocalUsageManager implements UsageManager {
+
+ // TODO Threading model needs revisited.
+ // Synchronizes on updates to storage; but if two Brooklyn nodes were both writing to the same
+ // ApplicationUsage or LocationUsage record there'd be a race. That currently won't happen
+ // (at least for ApplicationUsage?) because the app is mastered in just one node at a time,
+ // and because location events are just manage/unmanage which should be happening in just
+ // one place at a time for a given location.
+
+ private static final Logger log = LoggerFactory.getLogger(LocalUsageManager.class);
+
+ private static class ApplicationMetadataImpl implements org.apache.brooklyn.core.management.internal.UsageListener.ApplicationMetadata {
+ private final Application app;
+ private String applicationId;
+ private String applicationName;
+ private String entityType;
+ private String catalogItemId;
+ private Map<String, String> metadata;
+
+ ApplicationMetadataImpl(Application app) {
+ this.app = checkNotNull(app, "app");
+ applicationId = app.getId();
+ applicationName = app.getDisplayName();
+ entityType = app.getEntityType().getName();
+ catalogItemId = app.getCatalogItemId();
+ metadata = ((EntityInternal)app).toMetadataRecord();
+ }
+ @Override public Application getApplication() {
+ return app;
+ }
+ @Override public String getApplicationId() {
+ return applicationId;
+ }
+ @Override public String getApplicationName() {
+ return applicationName;
+ }
+ @Override public String getEntityType() {
+ return entityType;
+ }
+ @Override public String getCatalogItemId() {
+ return catalogItemId;
+ }
+ @Override public Map<String, String> getMetadata() {
+ return metadata;
+ }
+ }
+
+ private static class LocationMetadataImpl implements org.apache.brooklyn.core.management.internal.UsageListener.LocationMetadata {
+ private final Location loc;
+ private String locationId;
+ private Map<String, String> metadata;
+
+ LocationMetadataImpl(Location loc) {
+ this.loc = checkNotNull(loc, "loc");
+ locationId = loc.getId();
+ metadata = ((LocationInternal)loc).toMetadataRecord();
+ }
+ @Override public Location getLocation() {
+ return loc;
+ }
+ @Override public String getLocationId() {
+ return locationId;
+ }
+ @Override public Map<String, String> getMetadata() {
+ return metadata;
+ }
+ }
+
+ // Register a coercion from String->UsageListener, so that USAGE_LISTENERS defined in brooklyn.properties
+ // will be instantiated, given their class names.
+ static {
+ TypeCoercions.registerAdapter(String.class, org.apache.brooklyn.core.management.internal.UsageListener.class, new Function<String, org.apache.brooklyn.core.management.internal.UsageListener>() {
+ @Override public org.apache.brooklyn.core.management.internal.UsageListener apply(String input) {
+ // TODO Want to use classLoader = mgmt.getCatalog().getRootClassLoader();
+ ClassLoader classLoader = LocalUsageManager.class.getClassLoader();
+ Optional<Object> result = Reflections.invokeConstructorWithArgs(classLoader, input);
+ if (result.isPresent()) {
+ if (result.get() instanceof org.apache.brooklyn.core.management.internal.UsageManager.UsageListener) {
+ return new org.apache.brooklyn.core.management.internal.UsageManager.UsageListener.UsageListenerAdapter((org.apache.brooklyn.core.management.internal.UsageManager.UsageListener) result.get());
+ } else {
+ return (org.apache.brooklyn.core.management.internal.UsageListener) result.get();
+ }
+ } else {
+ throw new IllegalStateException("Failed to create UsageListener from class name '"+input+"' using no-arg constructor");
+ }
+ }
+ });
+ }
+
+ @VisibleForTesting
+ public static final String APPLICATION_USAGE_KEY = "usage-application";
+
+ @VisibleForTesting
+ public static final String LOCATION_USAGE_KEY = "usage-location";
+
+ private final LocalManagementContext managementContext;
+
+ private final Object mutex = new Object();
+
+ private final List<org.apache.brooklyn.core.management.internal.UsageListener> listeners = Lists.newCopyOnWriteArrayList();
+
+ private final AtomicInteger listenerQueueSize = new AtomicInteger();
+
+ private ListeningExecutorService listenerExecutor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
+ .setNameFormat("brooklyn-usagemanager-listener-%d")
+ .build()));
+
+ public LocalUsageManager(LocalManagementContext managementContext) {
+ this.managementContext = checkNotNull(managementContext, "managementContext");
+
+ // TODO Once org.apache.brooklyn.core.management.internal.UsageManager.UsageListener is deleted, restore this
+ // to normal generics!
+ Collection<?> listeners = managementContext.getBrooklynProperties().getConfig(UsageManager.USAGE_LISTENERS);
+ if (listeners != null) {
+ for (Object listener : listeners) {
+ if (listener instanceof ManagementContextInjectable) {
+ ((ManagementContextInjectable)listener).injectManagementContext(managementContext);
+ }
+ if (listener instanceof org.apache.brooklyn.core.management.internal.UsageManager.UsageListener) {
+ addUsageListener((org.apache.brooklyn.core.management.internal.UsageManager.UsageListener)listener);
+ } else if (listener instanceof org.apache.brooklyn.core.management.internal.UsageListener) {
+ addUsageListener((org.apache.brooklyn.core.management.internal.UsageListener)listener);
+ } else if (listener == null) {
+ throw new NullPointerException("null listener in config "+UsageManager.USAGE_LISTENERS);
+ } else {
+ throw new ClassCastException("listener "+listener+" of type "+listener.getClass()+" is not of type "+org.apache.brooklyn.core.management.internal.UsageListener.class.getName());
+ }
+ }
+ }
+ }
+
+ public void terminate() {
+ // Wait for the listeners to finish + close the listeners
+ Duration timeout = managementContext.getBrooklynProperties().getConfig(UsageManager.USAGE_LISTENER_TERMINATION_TIMEOUT);
+ if (listenerQueueSize.get() > 0) {
+ log.info("Usage manager waiting for "+listenerQueueSize+" listener events for up to "+timeout);
+ }
+ List<ListenableFuture<?>> futures = Lists.newArrayList();
+ for (final org.apache.brooklyn.core.management.internal.UsageListener listener : listeners) {
+ ListenableFuture<?> future = listenerExecutor.submit(new Runnable() {
+ public void run() {
+ if (listener instanceof Closeable) {
+ try {
+ ((Closeable)listener).close();
+ } catch (IOException e) {
+ log.warn("Problem closing usage listener "+listener+" (continuing)", e);
+ }
+ }
+ }});
+ futures.add(future);
+ }
+ try {
+ Futures.successfulAsList(futures).get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ log.warn("Problem terminiating usage listeners (continuing)", e);
+ } finally {
+ listenerExecutor.shutdownNow();
+ }
+ }
+
+ private void execOnListeners(final Function<org.apache.brooklyn.core.management.internal.UsageListener, Void> job) {
+ for (final org.apache.brooklyn.core.management.internal.UsageListener listener : listeners) {
+ listenerQueueSize.incrementAndGet();
+ listenerExecutor.execute(new Runnable() {
+ public void run() {
+ try {
+ job.apply(listener);
+ } catch (RuntimeException e) {
+ log.error("Problem notifying listener "+listener+" of "+job, e);
+ Exceptions.propagateIfFatal(e);
+ } finally {
+ listenerQueueSize.decrementAndGet();
+ }
+ }});
+ }
+ }
+
+ @Override
+ public void recordApplicationEvent(final Application app, final Lifecycle state) {
+ log.debug("Storing application lifecycle usage event: application {} in state {}", new Object[] {app, state});
+ ConcurrentMap<String, ApplicationUsage> eventMap = managementContext.getStorage().getMap(APPLICATION_USAGE_KEY);
+ synchronized (mutex) {
+ ApplicationUsage usage = eventMap.get(app.getId());
+ if (usage == null) {
+ usage = new ApplicationUsage(app.getId(), app.getDisplayName(), app.getEntityType().getName(), ((EntityInternal)app).toMetadataRecord());
+ }
+ final ApplicationUsage.ApplicationEvent event = new ApplicationUsage.ApplicationEvent(state, getUser());
+ usage.addEvent(event);
+ eventMap.put(app.getId(), usage);
+
+ execOnListeners(new Function<org.apache.brooklyn.core.management.internal.UsageListener, Void>() {
+ public Void apply(org.apache.brooklyn.core.management.internal.UsageListener listener) {
+ listener.onApplicationEvent(new ApplicationMetadataImpl(Entities.proxy(app)), event);
+ return null;
+ }
+ public String toString() {
+ return "applicationEvent("+app+", "+state+")";
+ }});
+ }
+ }
+
+ /**
+ * Adds this location event to the usage record for the given location (creating the usage
+ * record if one does not already exist).
+ */
+ @Override
+ public void recordLocationEvent(final Location loc, final Lifecycle state) {
+ // TODO This approach (i.e. recording events on manage/unmanage would not work for
+ // locations that are reused. For example, in a FixedListMachineProvisioningLocation
+ // the ssh machine location is returned to the pool and handed back out again.
+ // But maybe the solution there is to hand out different instances so that one user
+ // can't change the config of the SshMachineLocation to subsequently affect the next
+ // user.
+ //
+ // TODO Should perhaps extract the location storage methods into their own class,
+ // but no strong enough feelings yet...
+
+ checkNotNull(loc, "location");
+ if (loc.getConfig(AbstractLocation.TEMPORARY_LOCATION)) {
+ log.info("Ignoring location lifecycle usage event for {} (state {}), because location is a temporary location", loc, state);
+ return;
+ }
+ checkNotNull(state, "state of location %s", loc);
+ if (loc.getId() == null) {
+ log.error("Ignoring location lifecycle usage event for {} (state {}), because location has no id", loc, state);
+ return;
+ }
+ if (managementContext.getStorage() == null) {
+ log.warn("Cannot store location lifecycle usage event for {} (state {}), because storage not available", loc, state);
+ return;
+ }
+
+ Object callerContext = loc.getConfig(LocationConfigKeys.CALLER_CONTEXT);
+
+ if (callerContext != null && callerContext instanceof Entity) {
+ log.debug("Storing location lifecycle usage event: location {} in state {}; caller context {}", new Object[] {loc, state, callerContext});
+
+ Entity caller = (Entity) callerContext;
+ String entityTypeName = caller.getEntityType().getName();
+ String appId = caller.getApplicationId();
+
+ final LocationUsage.LocationEvent event = new LocationUsage.LocationEvent(state, caller.getId(), entityTypeName, appId, getUser());
+
+ ConcurrentMap<String, LocationUsage> usageMap = managementContext.getStorage().<String, LocationUsage>getMap(LOCATION_USAGE_KEY);
+ synchronized (mutex) {
+ LocationUsage usage = usageMap.get(loc.getId());
+ if (usage == null) {
+ usage = new LocationUsage(loc.getId(), ((LocationInternal)loc).toMetadataRecord());
+ }
+ usage.addEvent(event);
+ usageMap.put(loc.getId(), usage);
+
+ execOnListeners(new Function<org.apache.brooklyn.core.management.internal.UsageListener, Void>() {
+ public Void apply(org.apache.brooklyn.core.management.internal.UsageListener listener) {
+ listener.onLocationEvent(new LocationMetadataImpl(loc), event);
+ return null;
+ }
+ public String toString() {
+ return "locationEvent("+loc+", "+state+")";
+ }});
+ }
+ } else {
+ // normal for high-level locations
+ log.trace("Not recording location lifecycle usage event for {} in state {}, because no caller context", new Object[] {loc, state});
+ }
+ }
+
+ /**
+ * Returns the usage info for the location with the given id, or null if unknown.
+ */
+ @Override
+ public LocationUsage getLocationUsage(String locationId) {
+ BrooklynStorage storage = managementContext.getStorage();
+
+ Map<String, LocationUsage> usageMap = storage.getMap(LOCATION_USAGE_KEY);
+ return usageMap.get(locationId);
+ }
+
+ /**
+ * Returns the usage info that matches the given predicate.
+ * For example, could be used to find locations used within a given time period.
+ */
+ @Override
+ public Set<LocationUsage> getLocationUsage(Predicate<? super LocationUsage> filter) {
+ // TODO could do more efficient indexing, to more easily find locations in use during a given period.
+ // But this is good enough for first-pass.
+
+ Map<String, LocationUsage> usageMap = managementContext.getStorage().getMap(LOCATION_USAGE_KEY);
+ Set<LocationUsage> result = Sets.newLinkedHashSet();
+
+ for (LocationUsage usage : usageMap.values()) {
+ if (filter.apply(usage)) {
+ result.add(usage);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the usage info for the location with the given id, or null if unknown.
+ */
+ @Override
+ public ApplicationUsage getApplicationUsage(String appId) {
+ BrooklynStorage storage = managementContext.getStorage();
+
+ Map<String, ApplicationUsage> usageMap = storage.getMap(APPLICATION_USAGE_KEY);
+ return usageMap.get(appId);
+ }
+
+ /**
+ * Returns the usage info that matches the given predicate.
+ * For example, could be used to find applications used within a given time period.
+ */
+ @Override
+ public Set<ApplicationUsage> getApplicationUsage(Predicate<? super ApplicationUsage> filter) {
+ // TODO could do more efficient indexing, to more easily find locations in use during a given period.
+ // But this is good enough for first-pass.
+
+ Map<String, ApplicationUsage> usageMap = managementContext.getStorage().getMap(APPLICATION_USAGE_KEY);
+ Set<ApplicationUsage> result = Sets.newLinkedHashSet();
+
+ for (ApplicationUsage usage : usageMap.values()) {
+ if (filter.apply(usage)) {
+ result.add(usage);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ @Deprecated
+ public void addUsageListener(org.apache.brooklyn.core.management.internal.UsageManager.UsageListener listener) {
+ addUsageListener(new org.apache.brooklyn.core.management.internal.UsageManager.UsageListener.UsageListenerAdapter(listener));
+ }
+
+ @Override
+ @Deprecated
+ public void removeUsageListener(org.apache.brooklyn.core.management.internal.UsageManager.UsageListener listener) {
+ removeUsageListener(new org.apache.brooklyn.core.management.internal.UsageManager.UsageListener.UsageListenerAdapter(listener));
+ }
+
+ @Override
+ public void addUsageListener(org.apache.brooklyn.core.management.internal.UsageListener listener) {
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeUsageListener(org.apache.brooklyn.core.management.internal.UsageListener listener) {
+ listeners.remove(listener);
+ }
+
+ private String getUser() {
+ EntitlementContext entitlementContext = Entitlements.getEntitlementContext();
+ if (entitlementContext != null) {
+ return entitlementContext.user();
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/LocationManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocationManagerInternal.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocationManagerInternal.java
new file mode 100644
index 0000000..ba426ec
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocationManagerInternal.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.LocationManager;
+
+public interface LocationManagerInternal extends LocationManager, BrooklynObjectManagerInternal<Location> {
+
+ public Iterable<String> getLocationIds();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
new file mode 100644
index 0000000..97a3d73
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementContextInternal.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.ha.OsgiManager;
+
+import brooklyn.catalog.internal.CatalogInitialization;
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.proxying.InternalEntityFactory;
+import brooklyn.entity.proxying.InternalLocationFactory;
+import brooklyn.entity.proxying.InternalPolicyFactory;
+import brooklyn.internal.storage.BrooklynStorage;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.task.TaskTags;
+
+import com.google.common.annotations.Beta;
+
+public interface ManagementContextInternal extends ManagementContext {
+
+ public static final String SUB_TASK_TAG = TaskTags.SUB_TASK_TAG;
+
+ public static final String EFFECTOR_TAG = BrooklynTaskTags.EFFECTOR_TAG;
+ public static final String NON_TRANSIENT_TASK_TAG = BrooklynTaskTags.NON_TRANSIENT_TASK_TAG;
+ public static final String TRANSIENT_TASK_TAG = BrooklynTaskTags.TRANSIENT_TASK_TAG;
+
+ public static final String EMPTY_CATALOG_URL = "classpath://brooklyn/empty.catalog.bom";
+
+ ClassLoader getBaseClassLoader();
+
+ Iterable<URL> getBaseClassPathForScanning();
+
+ void setBaseClassPathForScanning(Iterable<URL> urls);
+
+ void setManagementNodeUri(URI uri);
+
+ void addEntitySetListener(CollectionChangeListener<Entity> listener);
+
+ void removeEntitySetListener(CollectionChangeListener<Entity> listener);
+
+ void terminate();
+
+ long getTotalEffectorInvocations();
+
+ <T> T invokeEffectorMethodSync(final Entity entity, final Effector<T> eff, final Object args) throws ExecutionException;
+
+ <T> Task<T> invokeEffector(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters);
+
+ BrooklynStorage getStorage();
+
+ BrooklynProperties getBrooklynProperties();
+
+ AccessManager getAccessManager();
+
+ UsageManager getUsageManager();
+
+ /**
+ * @return The OSGi manager, if available; may be absent if OSGi is not supported,
+ * e.g. in test contexts (but will be supported in all major contexts).
+ */
+ Maybe<OsgiManager> getOsgiManager();
+
+ InternalEntityFactory getEntityFactory();
+
+ InternalLocationFactory getLocationFactory();
+
+ InternalPolicyFactory getPolicyFactory();
+
+ /**
+ * Registers an entity that has been created, but that has not yet begun to be managed.
+ * <p>
+ * This differs from the idea of "preManaged" where the entities are in the process of being
+ * managed, but where management is not yet complete.
+ */
+ // TODO would benefit from better naming! The name has percolated up from LocalEntityManager.
+ // should we just rename here as register or preManage?
+ void prePreManage(Entity entity);
+
+ /**
+ * Registers a location that has been created, but that has not yet begun to be managed.
+ */
+ void prePreManage(Location location);
+
+ /** Object which allows adding, removing, and clearing errors.
+ * TODO In future this will change to a custom interface with a unique identifier for each error. */
+ @Beta
+ List<Throwable> errors();
+
+ @Beta
+ CatalogInitialization getCatalogInitialization();
+
+ @Beta
+ void setCatalogInitialization(CatalogInitialization catalogInitialization);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementTransitionInfo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementTransitionInfo.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementTransitionInfo.java
new file mode 100644
index 0000000..2d944d9
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementTransitionInfo.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+
+/** Stores a management transition mode, and the management context. */
+// TODO does this class really pull its weight?
+public class ManagementTransitionInfo {
+
+ final ManagementContext mgmtContext;
+ final ManagementTransitionMode mode;
+
+ public ManagementTransitionInfo(ManagementContext mgmtContext, ManagementTransitionMode mode) {
+ this.mgmtContext = mgmtContext;
+ this.mode = mode;
+ }
+
+
+ public ManagementContext getManagementContext() {
+ return mgmtContext;
+ }
+
+ public ManagementTransitionMode getMode() {
+ return mode;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"["+mgmtContext+";"+mode+"]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementTransitionMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementTransitionMode.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementTransitionMode.java
new file mode 100644
index 0000000..3adc625
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/ManagementTransitionMode.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Records details of a management transition, specifically the {@link BrooklynObjectManagementMode} before and after,
+ * and allows easy checking of various aspects of that.
+ * <p>
+ * This helps make code readable and keep correct logic if we expand/change the management modes.
+ */
+public class ManagementTransitionMode {
+
+ private static final Logger log = LoggerFactory.getLogger(ManagementTransitionMode.class);
+
+ private final BrooklynObjectManagementMode modeBefore, modeAfter;
+
+ private ManagementTransitionMode(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+ this.modeBefore = modeBefore;
+ this.modeAfter = modeAfter;
+ }
+
+ public static ManagementTransitionMode transitioning(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+ return new ManagementTransitionMode(Preconditions.checkNotNull(modeBefore, "modeBefore"), Preconditions.checkNotNull(modeAfter, "modeAfter"));
+ }
+
+ @Deprecated /** @deprecated marking places where we aren't sure */
+ public static ManagementTransitionMode guessing(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
+ return transitioning(modeBefore, modeAfter);
+ }
+
+ /** @return the mode this object was previously managed as */
+ public BrooklynObjectManagementMode getModeBefore() {
+ return modeBefore;
+ }
+
+ /** @return the mode this object is now being managed as */
+ public BrooklynObjectManagementMode getModeAfter() {
+ return modeAfter;
+ }
+
+ /** This management node was previously not loaded here,
+ * either it did not exist (and is just being created) or it was in persisted state but
+ * not loaded at this node. */
+ public boolean wasNotLoaded() {
+ return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT || getModeBefore()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED;
+ }
+
+ /** This management node is now not going to be loaded here, either it is being destroyed
+ * (not known anywhere, not even persisted) or simply forgotten here */
+ public boolean isNoLongerLoaded() {
+ return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT || getModeAfter()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED;
+ }
+
+ /** This management node was the master for the given object */
+ public boolean wasPrimary() {
+ return getModeBefore()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
+ }
+
+ /** This management node is now the master for the given object */
+ public boolean isPrimary() {
+ return getModeAfter()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
+ }
+
+ /** Object was previously loaded as read-only at this management node;
+ * active management was occurring elsewhere (or not at all)
+ */
+ public boolean wasReadOnly() {
+ return getModeBefore()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
+ }
+
+ /** Object is now being loaded as read-only at this management node;
+ * expect active management to be occurring elsewhere
+ */
+ public boolean isReadOnly() {
+ return getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
+ }
+
+ /** Object is being created:
+ * previously did not exist (not even in persisted state);
+ * implies that we are the active manager creating it,
+ * i.e. {@link #getModeAfter()} should indicate {@link BrooklynObjectManagementMode#MANAGED_PRIMARY}.
+ * (if we're read-only and the manager has just created it,
+ * {@link #getModeBefore()} should indicate {@link BrooklynObjectManagementMode#UNMANAGED_PERSISTED})
+ */
+ public boolean isCreating() {
+ if (getModeBefore()!=BrooklynObjectManagementMode.NONEXISTENT)
+ return false;
+
+ if (getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY) {
+ log.warn("isCreating set on RO object; highly irregular!");
+ }
+ return true;
+ }
+
+ /** Object is being destroyed:
+ * either destroyed elsewhere and we're catching up (in read-only mode),
+ * or we've been the active manager and are destroying it */
+ public boolean isDestroying() {
+ return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT;
+ }
+
+ @Override
+ public String toString() {
+ return ManagementTransitionMode.class.getSimpleName()+"["+getModeBefore()+"->"+getModeAfter()+"]";
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentAccessManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentAccessManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentAccessManager.java
new file mode 100644
index 0000000..1d94f02
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentAccessManager.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import org.apache.brooklyn.api.management.AccessController;
+
+
+public class NonDeploymentAccessManager implements AccessManager {
+
+ private final ManagementContextInternal initialManagementContext;
+
+ public NonDeploymentAccessManager(ManagementContextInternal initialManagementContext) {
+ this.initialManagementContext = initialManagementContext;
+ }
+
+ private boolean isInitialManagementContextReal() {
+ return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
+ }
+
+ @Override
+ public AccessController getAccessController() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getAccessManager().getAccessController();
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public boolean isLocationProvisioningAllowed() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getAccessManager().isLocationProvisioningAllowed();
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public boolean isLocationManagementAllowed() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getAccessManager().isLocationManagementAllowed();
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public boolean isEntityManagementAllowed() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getAccessManager().isEntityManagementAllowed();
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public void setLocationProvisioningAllowed(boolean allowed) {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.getAccessManager().setLocationProvisioningAllowed(allowed);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public void setLocationManagementAllowed(boolean allowed) {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.getAccessManager().setLocationManagementAllowed(allowed);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public void setEntityManagementAllowed(boolean allowed) {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.getAccessManager().setEntityManagementAllowed(allowed);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentEntityManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentEntityManager.java
new file mode 100644
index 0000000..658bbf7
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentEntityManager.java
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.entity.proxying.EntityTypeRegistry;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.policy.Enricher;
+import org.apache.brooklyn.api.policy.EnricherSpec;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
+
+import com.google.common.base.Predicate;
+
+public class NonDeploymentEntityManager implements EntityManagerInternal {
+
+ private final ManagementContext initialManagementContext;
+
+ public NonDeploymentEntityManager(ManagementContext initialManagementContext) {
+ this.initialManagementContext = initialManagementContext;
+ }
+
+ @Override
+ public EntityTypeRegistry getEntityTypeRegistry() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().getEntityTypeRegistry();
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
+ }
+ }
+
+ @Override
+ public <T extends Entity> T createEntity(EntitySpec<T> spec) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().createEntity(spec);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
+ }
+ }
+
+ @Override
+ public <T extends Entity> T createEntity(Map<?,?> config, Class<T> type) {
+ return createEntity(EntitySpec.create(type).configure(config));
+ }
+
+ @Override
+ public <T extends Policy> T createPolicy(PolicySpec<T> spec) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().createPolicy(spec);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
+ }
+ }
+
+ @Override
+ public <T extends Enricher> T createEnricher(EnricherSpec<T> spec) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().createEnricher(spec);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
+ }
+ }
+
+ @Override
+ public Collection<Entity> getEntities() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().getEntities();
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public Collection<Entity> getEntitiesInApplication(Application application) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().getEntitiesInApplication(application);
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public Collection<Entity> findEntities(Predicate<? super Entity> filter) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().findEntities(filter);
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public Collection<Entity> findEntitiesInApplication(Application application, Predicate<? super Entity> filter) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().findEntitiesInApplication(application, filter);
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public Entity getEntity(String id) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getEntityManager().getEntity(id);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Iterable<String> getEntityIds() {
+ if (isInitialManagementContextReal()) {
+ return ((EntityManagerInternal)initialManagementContext.getEntityManager()).getEntityIds();
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public ManagementTransitionMode getLastManagementTransitionMode(String itemId) {
+ if (isInitialManagementContextReal()) {
+ return ((EntityManagerInternal)initialManagementContext.getEntityManager()).getLastManagementTransitionMode(itemId);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public void setManagementTransitionMode(Entity item, ManagementTransitionMode mode) {
+ if (isInitialManagementContextReal()) {
+ ((EntityManagerInternal)initialManagementContext.getEntityManager()).setManagementTransitionMode(item, mode);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public boolean isManaged(Entity entity) {
+ return false;
+ }
+
+ @Override
+ public void manage(Entity e) {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot manage "+e);
+ }
+
+ @Override
+ public void unmanage(Entity e, ManagementTransitionMode info) {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+
+ @Override
+ public void manageRebindedRoot(Entity item) {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+
+ @Override
+ public void unmanage(Entity e) {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot unmanage "+e);
+ }
+
+ private boolean isInitialManagementContextReal() {
+ return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
+ }
+
+ @Override
+ public Iterable<Entity> getAllEntitiesInApplication(Application application) {
+ if (isInitialManagementContextReal()) {
+ return ((EntityManagerInternal)initialManagementContext.getEntityManager()).getAllEntitiesInApplication(application);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentLocationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentLocationManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentLocationManager.java
new file mode 100644
index 0000000..5c81648
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentLocationManager.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.management.ManagementContext;
+
+public class NonDeploymentLocationManager implements LocationManagerInternal {
+
+ private final ManagementContext initialManagementContext;
+
+ public NonDeploymentLocationManager(ManagementContext initialManagementContext) {
+ this.initialManagementContext = initialManagementContext;
+ }
+
+ @Override
+ public <T extends Location> T createLocation(LocationSpec<T> spec) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getLocationManager().createLocation(spec);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot create "+spec);
+ }
+ }
+
+ @Override
+ public <T extends Location> T createLocation(Map<?, ?> config, Class<T> type) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getLocationManager().createLocation(config, type);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot create "+type);
+ }
+ }
+
+ @Override
+ public Collection<Location> getLocations() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getLocationManager().getLocations();
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public Location getLocation(String id) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getLocationManager().getLocation(id);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public Iterable<String> getLocationIds() {
+ if (isInitialManagementContextReal()) {
+ return ((LocationManagerInternal)initialManagementContext.getLocationManager()).getLocationIds();
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public boolean isManaged(Location loc) {
+ return false;
+ }
+
+ @Override
+ public void manageRebindedRoot(Location loc) {
+ if (isInitialManagementContextReal()) {
+ ((LocationManagerInternal)initialManagementContext.getLocationManager()).manageRebindedRoot(loc);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot manage "+loc);
+ }
+ }
+
+ @Override
+ @Deprecated
+ public Location manage(Location loc) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getLocationManager().manage(loc);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot manage "+loc);
+ }
+ }
+
+
+ @Override
+ public ManagementTransitionMode getLastManagementTransitionMode(String itemId) {
+ if (isInitialManagementContextReal()) {
+ return ((LocationManagerInternal)initialManagementContext.getLocationManager()).getLastManagementTransitionMode(itemId);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public void setManagementTransitionMode(Location item, ManagementTransitionMode mode) {
+ if (isInitialManagementContextReal()) {
+ ((LocationManagerInternal)initialManagementContext.getLocationManager()).setManagementTransitionMode(item, mode);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public void unmanage(Location item, ManagementTransitionMode info) {
+ if (isInitialManagementContextReal()) {
+ ((LocationManagerInternal)initialManagementContext.getLocationManager()).unmanage(item, info);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public void unmanage(Location loc) {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.getLocationManager().unmanage(loc);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot unmanage "+loc);
+ }
+ }
+
+ private boolean isInitialManagementContextReal() {
+ return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
+ }
+}
[32/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/catalog
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java
deleted file mode 100644
index 1fb5bf3..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogBundleDto.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-
-public class CatalogBundleDto implements CatalogBundle {
- private String symbolicName;
- private String version;
- private String url;
-
- public CatalogBundleDto() {}
-
- public CatalogBundleDto(String name, String version, String url) {
- if (name == null && version == null) {
- Preconditions.checkNotNull(url, "url to an OSGi bundle is required");
- } else {
- Preconditions.checkNotNull(name, "both name and version are required");
- Preconditions.checkNotNull(version, "both name and version are required");
- }
-
- this.symbolicName = name;
- this.version = version;
- this.url = url;
- }
-
- @Override
- public boolean isNamed() {
- return symbolicName != null && version != null;
- }
-
- @Override
- public String getSymbolicName() {
- return symbolicName;
- }
-
- @Override
- public String getVersion() {
- return version;
- }
-
- @Override
- public String getUrl() {
- return url;
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this)
- .add("symbolicName", symbolicName)
- .add("version", version)
- .add("url", url)
- .toString();
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(symbolicName, version, url);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- CatalogBundleDto other = (CatalogBundleDto) obj;
- if (!Objects.equal(symbolicName, other.symbolicName)) return false;
- if (!Objects.equal(version, other.version)) return false;
- if (!Objects.equal(url, other.url)) return false;
- return true;
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
deleted file mode 100644
index b81b439..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDo.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.lang.reflect.Modifier;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-import org.reflections.util.ClasspathHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.api.catalog.Catalog;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.javalang.AggregateClassLoader;
-import brooklyn.util.javalang.ReflectionScanner;
-import brooklyn.util.javalang.UrlClassLoader;
-import brooklyn.util.os.Os;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Iterables;
-
-public class CatalogClasspathDo {
-
- public static enum CatalogScanningModes {
- /** the classpath is not scanned;
- * for any catalog which is presented over the internet this is recommended (to prevent loading) and is the default;
- * (you should explicitly list the items to include; it may be useful to autogenerate it by using a local catalog
- * scanning with ANNOTATIONS, viwing that by running mgmt.getCatalog().toXmlString(),
- * then editing the resulting XML (e.g. setting the classpath and removing the scan attribute) */
- NONE,
-
- /** types in the classpath are scanned for annotations indicating inclusion in the catalog ({@link Catalog});
- * this is the default if no catalog is supplied, scanning the local classpath */
- ANNOTATIONS,
-
- @Beta
- /** all catalog-friendly types are included,
- * even if not annotated for inclusion in the catalog; useful for quick hacking,
- * or a classpath (and possibly in future a regex, if added) which is known to have only good things in it;
- * however the precise semantics of what is included is subject to change,
- * and it is strongly recommended to use the {@link Catalog} annotation and scan for annotations
- * <p>
- * a catalog-friendly type is currently defined as:
- * any concrete non-anonymous (and not a non-static inner) class implementing Entity or Policy;
- * and additionally for entities and applications, an interface with the {@link ImplementedBy} annotation;
- * note that this means classes done "properly" with both an interface and an implementation
- * will be included twice, once as interface and once as implementation;
- * this guarantees inclusion of anything previously included (implementations;
- * and this will be removed from catalog in future likely),
- * plus things now done properly (which will become the only way in the future)
- **/
- TYPES
- }
-
- private static final Logger log = LoggerFactory.getLogger(CatalogClasspathDo.class);
-
- private final CatalogDo catalog;
- private final CatalogClasspathDto classpath;
- private final CatalogScanningModes scanMode;
-
- boolean isLoaded = false;
- private URL[] urls;
-
- private final AggregateClassLoader classloader = AggregateClassLoader.newInstanceWithNoLoaders();
- private volatile boolean classloaderLoaded = false;
-
- public CatalogClasspathDo(CatalogDo catalog) {
- this.catalog = Preconditions.checkNotNull(catalog, "catalog");
- this.classpath = catalog.dto.classpath;
- this.scanMode = (classpath != null) ? classpath.scan : null;
- }
-
- /** causes all scanning-based classpaths to scan the classpaths
- * (but does _not_ load all JARs) */
- // TODO this does a Java scan; we also need an OSGi scan which uses the OSGi classloaders when loading for scanning and resolving dependencies
- synchronized void load() {
- if (classpath == null || isLoaded) return;
-
- if (classpath.getEntries() == null) {
- urls = new URL[0];
- } else {
- urls = new URL[classpath.getEntries().size()];
- for (int i=0; i<urls.length; i++) {
- try {
- String u = classpath.getEntries().get(i);
- if (u.startsWith("classpath:")) {
- // special support for classpath: url's
- // TODO put convenience in ResourceUtils for extracting to a normal url
- // (or see below)
- InputStream uin = ResourceUtils.create(this).getResourceFromUrl(u);
- File f = Os.newTempFile("brooklyn-catalog-"+u, null);
- FileOutputStream fout = new FileOutputStream(f);
- try {
- Streams.copy(uin, fout);
- } finally {
- Streams.closeQuietly(fout);
- Streams.closeQuietly(uin);
- }
- u = f.toURI().toString();
- }
- urls[i] = new URL(u);
-
- // TODO potential disk leak above as we have no way to know when the temp file can be removed earlier than server shutdown;
- // a better way to handle this is to supply a stream handler (but URLConnection is a little bit hard to work with):
-// urls[i] = new URL(null, classpath.getEntries().get(i) // (handy construtor for reparsing urls, without splitting into uri first)
-// , new URLStreamHandler() {
-// @Override
-// protected URLConnection openConnection(URL u) throws IOException {
-// new ResourceUtils(null). ???
-// }
-// });
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- log.error("Error loading URL "+classpath.getEntries().get(i)+" in definition of catalog "+catalog+"; skipping definition");
- throw Exceptions.propagate(e);
- }
- }
- }
-
- // prefix is supported (but not really used yet) --
- // seems to have _better_ URL-discovery with prefixes
- // (might also offer regex ? but that is post-load filter as opposed to native optimisation)
- String prefix = null;
-
- if (scanMode==null || scanMode==CatalogScanningModes.NONE)
- return;
-
- Stopwatch timer = Stopwatch.createStarted();
- ReflectionScanner scanner = null;
- if (!catalog.isLocal()) {
- log.warn("Scanning not supported for remote catalogs; ignoring scan request in "+catalog);
- } else if (classpath.getEntries() == null || classpath.getEntries().isEmpty()) {
- // scan default classpath:
- ClassLoader baseCL = null;
- Iterable<URL> baseCP = null;
- if (catalog.mgmt instanceof ManagementContextInternal) {
- baseCL = ((ManagementContextInternal)catalog.mgmt).getBaseClassLoader();
- baseCP = ((ManagementContextInternal)catalog.mgmt).getBaseClassPathForScanning();
- }
- scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
- if (scanner.getSubTypesOf(Entity.class).isEmpty()) {
- try {
- ((ManagementContextInternal)catalog.mgmt).setBaseClassPathForScanning(ClasspathHelper.forJavaClassPath());
- log.debug("Catalog scan of default classloader returned nothing; reverting to java.class.path");
- baseCP = ((ManagementContextInternal)catalog.mgmt).getBaseClassPathForScanning();
- scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
- } catch (Exception e) {
- log.info("Catalog scan is empty, and unable to use java.class.path (base classpath is "+baseCP+"): "+e);
- Exceptions.propagateIfFatal(e);
- }
- }
- } else {
- // scan specified jars:
- scanner = new ReflectionScanner(urls==null || urls.length==0 ? null : Arrays.asList(urls), prefix, getLocalClassLoader());
- }
-
- if (scanner!=null) {
- int count = 0, countApps = 0;
- if (scanMode==CatalogScanningModes.ANNOTATIONS) {
- Set<Class<?>> catalogClasses = scanner.getTypesAnnotatedWith(Catalog.class);
- for (Class<?> c: catalogClasses) {
- try {
- CatalogItem<?,?> item = addCatalogEntry(c);
- count++;
- if (CatalogTemplateItemDto.class.isInstance(item)) countApps++;
- } catch (Exception e) {
- log.warn("Failed to add catalog entry for "+c+"; continuing scan...", e);
- }
- }
- } else if (scanMode==CatalogScanningModes.TYPES) {
- Iterable<Class<?>> entities = this.excludeInvalidClasses(
- Iterables.concat(scanner.getSubTypesOf(Entity.class),
- // not sure why we have to look for sub-types of Application,
- // they should be picked up as sub-types of Entity, but in maven builds (only!)
- // they are not -- i presume a bug in scanner
- scanner.getSubTypesOf(Application.class),
- scanner.getSubTypesOf(ApplicationBuilder.class)));
- for (Class<?> c: entities) {
- if (Application.class.isAssignableFrom(c) || ApplicationBuilder.class.isAssignableFrom(c)) {
- addCatalogEntry(new CatalogTemplateItemDto(), c);
- countApps++;
- } else {
- addCatalogEntry(new CatalogEntityItemDto(), c);
- }
- count++;
- }
- Iterable<Class<? extends Policy>> policies = this.excludeInvalidClasses(scanner.getSubTypesOf(Policy.class));
- for (Class<?> c: policies) {
- addCatalogEntry(new CatalogPolicyItemDto(), c);
- count++;
- }
-
- Iterable<Class<? extends Location>> locations = this.excludeInvalidClasses(scanner.getSubTypesOf(Location.class));
- for (Class<?> c: locations) {
- addCatalogEntry(new CatalogLocationItemDto(), c);
- count++;
- }
- } else {
- throw new IllegalStateException("Unsupported catalog scan mode "+scanMode+" for "+this);
- }
- log.debug("Catalog '"+catalog.dto.name+"' classpath scan completed: loaded "+
- count+" item"+Strings.s(count)+" ("+countApps+" app"+Strings.s(countApps)+") in "+Time.makeTimeStringRounded(timer));
- }
-
- isLoaded = true;
- }
-
- /** removes inner classes (non-static nesteds) and others;
- * bear in mind named ones will be hard to instantiate without the outer class instance) */
- private <T> Iterable<Class<? extends T>> excludeInvalidClasses(Iterable<Class<? extends T>> input) {
- Predicate<Class<? extends T>> f = new Predicate<Class<? extends T>>() {
- @Override
- public boolean apply(@Nullable Class<? extends T> input) {
- if (input==null) return false;
- if (input.isLocalClass() || input.isAnonymousClass()) return false;
- if (Modifier.isAbstract(input.getModifiers())) {
- if (input.getAnnotation(ImplementedBy.class)==null)
- return false;
- }
- // non-abstract top-level classes are okay
- if (!input.isMemberClass()) return true;
- if (!Modifier.isStatic(input.getModifiers())) return false;
- // nested classes only okay if static
- return true;
- }
- };
- return Iterables.filter(input, f);
- }
-
- /** augments the given item with annotations and class data for the given class, then adds to catalog
- * @deprecated since 0.7.0 the classpath DO is replaced by libraries */
- @Deprecated
- public CatalogItem<?,?> addCatalogEntry(Class<?> c) {
- if (Application.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
- if (ApplicationBuilder.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
- if (Entity.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogEntityItemDto(), c);
- if (Policy.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogPolicyItemDto(), c);
- if (Location.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogLocationItemDto(), c);
- throw new IllegalStateException("Cannot add "+c+" to catalog: unsupported type "+c.getName());
- }
-
- /** augments the given item with annotations and class data for the given class, then adds to catalog
- * @deprecated since 0.7.0 the classpath DO is replaced by libraries */
- @Deprecated
- public CatalogItem<?,?> addCatalogEntry(CatalogItemDtoAbstract<?,?> item, Class<?> c) {
- Catalog annotations = c.getAnnotation(Catalog.class);
- item.setSymbolicName(c.getName());
- item.setJavaType(c.getName());
- item.setDisplayName(firstNonEmpty(c.getSimpleName(), c.getName()));
- if (annotations!=null) {
- item.setDisplayName(firstNonEmpty(annotations.name(), item.getDisplayName()));
- item.setDescription(firstNonEmpty(annotations.description()));
- item.setIconUrl(firstNonEmpty(annotations.iconUrl()));
- }
- if (log.isTraceEnabled())
- log.trace("adding to catalog: "+c+" (from catalog "+catalog+")");
- catalog.addEntry(item);
- return item;
- }
-
- private static String firstNonEmpty(String ...candidates) {
- for (String c: candidates)
- if (c!=null && !c.isEmpty()) return c;
- return null;
- }
-
- /** returns classloader for the entries specified here */
- public ClassLoader getLocalClassLoader() {
- if (!classloaderLoaded) loadLocalClassLoader();
- return classloader;
- }
-
- protected synchronized void loadLocalClassLoader() {
- if (classloaderLoaded) return;
- if (urls==null) return;
- classloader.addFirst(new UrlClassLoader(urls));
- classloaderLoaded = true;
- return;
- }
-
- /** adds the given URL as something this classloader will load
- * (however no scanning is done) */
- public void addToClasspath(URL u, boolean updateDto) {
- if (updateDto) classpath.getEntries().add(u.toExternalForm());
- addToClasspath(new UrlClassLoader(u));
- }
-
- /** adds the given URL as something this classloader will load
- * (however no scanning is done).
- * <p>
- * the DTO will _not_ be updated. */
- public void addToClasspath(ClassLoader loader) {
- classloader.addFirst(loader);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDto.java
deleted file mode 100644
index c9e97f7..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogClasspathDto.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-
-public class CatalogClasspathDto {
-
- /** whether/what to scan; defaults to 'none' */
- CatalogScanningModes scan;
- private List<String> entries;
-
- public synchronized void addEntry(String url) {
- if (entries==null)
- entries = new CopyOnWriteArrayList<String>();
-
- entries.add(url);
- }
-
- public synchronized List<String> getEntries() {
- return entries;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
deleted file mode 100644
index 25fabff..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.javalang.AggregateClassLoader;
-import brooklyn.util.net.Urls;
-import brooklyn.util.time.CountdownTimer;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
-public class CatalogDo {
-
- private static final Logger log = LoggerFactory.getLogger(CatalogDo.class);
-
- volatile boolean isLoaded = false;
- final CatalogDto dto;
- ManagementContext mgmt = null;
- CatalogDo parent = null;
-
- List<CatalogDo> childrenCatalogs = new ArrayList<CatalogDo>();
- CatalogClasspathDo classpath;
- private Map<String, CatalogItemDo<?,?>> cacheById;
-
- AggregateClassLoader childrenClassLoader = AggregateClassLoader.newInstanceWithNoLoaders();
- ClassLoader recursiveClassLoader;
-
- protected CatalogDo(CatalogDto dto) {
- this.dto = Preconditions.checkNotNull(dto);
- }
-
- public CatalogDo(ManagementContext mgmt, CatalogDto dto) {
- this(dto);
- this.mgmt = mgmt;
- }
-
- boolean isLoaded() {
- return isLoaded;
- }
-
- /** Calls {@link #load(CatalogDo)} with a null parent. */
- public CatalogDo load() {
- return load(null);
- }
-
- /** Calls {@link #load(ManagementContext, CatalogDo)} with the catalog's existing management context. */
- public CatalogDo load(CatalogDo parent) {
- return load(mgmt, parent);
- }
-
- /** Calls {@link #load(ManagementContext, CatalogDo, boolean)} failing on load errors. */
- public synchronized CatalogDo load(ManagementContext mgmt, CatalogDo parent) {
- return load(mgmt, parent, true);
- }
-
- /** causes all URL-based catalogs to have their manifests loaded,
- * and all scanning-based classpaths to scan the classpaths
- * (but does not load all JARs)
- */
- public synchronized CatalogDo load(ManagementContext mgmt, CatalogDo parent, boolean failOnLoadError) {
- if (isLoaded()) {
- if (mgmt!=null && !Objects.equal(mgmt, this.mgmt)) {
- throw new IllegalStateException("Cannot set mgmt "+mgmt+" on "+this+" after catalog is loaded");
- }
- log.debug("Catalog "+this+" is already loaded");
- return this;
- }
- loadThisCatalog(mgmt, parent, failOnLoadError);
- loadChildrenCatalogs(failOnLoadError);
- buildCaches();
- return this;
- }
-
- protected synchronized void loadThisCatalog(ManagementContext mgmt, CatalogDo parent, boolean failOnLoadError) {
- if (isLoaded()) return;
- CatalogUtils.logDebugOrTraceIfRebinding(log, "Loading catalog {} into {}", this, parent);
- if (this.parent!=null && !this.parent.equals(parent))
- log.warn("Catalog "+this+" being initialised with different parent "+parent+" when already parented by "+this.parent, new Throwable("source of reparented "+this));
- if (this.mgmt!=null && !this.mgmt.equals(mgmt))
- log.warn("Catalog "+this+" being initialised with different mgmt "+mgmt+" when already managed by "+this.mgmt, new Throwable("source of reparented "+this));
- this.parent = parent;
- this.mgmt = mgmt;
- dto.populate();
- loadCatalogClasspath();
- loadCatalogItems(failOnLoadError);
- isLoaded = true;
- synchronized (this) {
- notifyAll();
- }
- }
-
- private void loadCatalogClasspath() {
- try {
- classpath = new CatalogClasspathDo(this);
- classpath.load();
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- log.error("Unable to load catalog "+this+" (ignoring): "+e);
- log.info("Trace for failure to load "+this+": "+e, e);
- }
- }
-
- private void loadCatalogItems(boolean failOnLoadError) {
- Iterable<CatalogItemDtoAbstract<?, ?>> entries = dto.getUniqueEntries();
- if (entries!=null) {
- for (CatalogItemDtoAbstract<?,?> entry : entries) {
- try {
- CatalogUtils.installLibraries(mgmt, entry.getLibraries());
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- if (failOnLoadError) {
- Exceptions.propagate(e);
- } else {
- log.error("Loading bundles for catalog item " + entry + " failed: " + e.getMessage(), e);
- }
- }
- }
- }
- }
-
- public boolean blockIfNotLoaded(Duration timeout) throws InterruptedException {
- if (isLoaded()) return true;
- synchronized (this) {
- if (isLoaded()) return true;
- CountdownTimer timer = CountdownTimer.newInstanceStarted(timeout);
- while (!isLoaded())
- if (!timer.waitOnForExpiry(this))
- return false;
- return true;
- }
- }
-
- protected void loadChildrenCatalogs(boolean failOnLoadError) {
- if (dto.catalogs!=null) {
- for (CatalogDto child: dto.catalogs) {
- loadCatalog(child, failOnLoadError);
- }
- }
- }
-
- CatalogDo loadCatalog(CatalogDto child, boolean failOnLoadError) {
- CatalogDo childL = new CatalogDo(child);
- childrenCatalogs.add(childL);
- childL.load(mgmt, this, failOnLoadError);
- childrenClassLoader.addFirst(childL.getRecursiveClassLoader());
- clearCache(false);
- return childL;
- }
-
- protected Map<String, CatalogItemDo<?,?>> getIdCache() {
- Map<String, CatalogItemDo<?,?>> cache = this.cacheById;
- if (cache==null) cache = buildCaches();
- return cache;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected synchronized Map<String, CatalogItemDo<?,?>> buildCaches() {
- if (cacheById != null) return cacheById;
- CatalogUtils.logDebugOrTraceIfRebinding(log, "Building cache for {}", this);
- if (!isLoaded())
- log.debug("Catalog not fully loaded when loading cache of "+this);
-
- Map<String, CatalogItemDo<?,?>> cache = new LinkedHashMap<String, CatalogItemDo<?,?>>();
-
- // build the cache; first from children catalogs, then from local entities
- // so that root and near-root takes precedence over deeper items;
- // and go through in reverse order so that things at the top of the file take precedence
- // (both in the cache and in the aggregate class loader);
- // however anything added _subsequently_ will take precedence (again in both)
- if (dto.catalogs!=null) {
- List<CatalogDo> catalogsReversed = new ArrayList<CatalogDo>(childrenCatalogs);
- Collections.reverse(catalogsReversed);
- for (CatalogDo child: catalogsReversed) {
- cache.putAll(child.getIdCache());
- }
- }
- if (dto.getUniqueEntries()!=null) {
- List<CatalogItemDtoAbstract<?,?>> entriesReversed = MutableList.copyOf(dto.getUniqueEntries());
- Collections.reverse(entriesReversed);
- for (CatalogItemDtoAbstract<?,?> entry: entriesReversed)
- cache.put(entry.getId(), new CatalogItemDo(this, entry));
- }
- this.cacheById = cache;
- return cache;
- }
-
- protected synchronized void clearCache(boolean deep) {
- this.cacheById = null;
- if (deep) {
- for (CatalogDo child : childrenCatalogs) {
- child.clearCache(true);
- }
- }
- clearParentCache();
- }
- protected void clearParentCache() {
- if (this.parent!=null)
- this.parent.clearCache(false);
- }
-
- /**
- * Adds the given entry to the catalog, with no enrichment.
- * Callers may prefer {@link CatalogClasspathDo#addCatalogEntry(CatalogItemDtoAbstract, Class)}
- */
- public synchronized void addEntry(CatalogItemDtoAbstract<?,?> entry) {
- dto.addEntry(entry);
-
- // could do clearCache(false); but this is slightly more efficient...
- if (cacheById != null) {
- @SuppressWarnings({ "unchecked", "rawtypes" })
- CatalogItemDo<?, ?> cdo = new CatalogItemDo(this, entry);
- cacheById.put(entry.getId(), cdo);
- }
- clearParentCache();
-
- if (mgmt != null) {
- mgmt.getRebindManager().getChangeListener().onManaged(entry);
- }
- }
-
- /**
- * Removes the given entry from the catalog.
- */
- public synchronized void deleteEntry(CatalogItemDtoAbstract<?, ?> entry) {
- dto.removeEntry(entry);
-
- // could do clearCache(false); but this is slightly more efficient...
- if (cacheById != null) {
- cacheById.remove(entry.getId());
- }
- clearParentCache();
-
- if (mgmt != null) {
- // TODO: Can the entry be in more than one catalogue? The management context has no notion of
- // catalogue hierarchy so this will effectively remove it from all catalogues.
- // (YES- we're assuming ID's are unique across all catalogues; if not, things get out of sync;
- // however see note at top of BasicBrooklynCatalog --
- // manualCatalog and OSGi is used for everything now except legacy XML trees)
- mgmt.getRebindManager().getChangeListener().onUnmanaged(entry);
- }
- }
-
- /** returns loaded catalog, if this has been loaded */
- CatalogDo addCatalog(CatalogDto child) {
- if (dto.catalogs == null)
- dto.catalogs = new ArrayList<CatalogDto>();
- dto.catalogs.add(child);
- if (!isLoaded())
- return null;
- return loadCatalog(child, true);
- }
-
- /** adds the given urls; filters out any nulls supplied */
- public synchronized void addToClasspath(String ...urls) {
- if (dto.classpath == null)
- dto.classpath = new CatalogClasspathDto();
- for (String url: urls) {
- if (url!=null)
- dto.classpath.addEntry(url);
- }
- if (isLoaded())
- throw new IllegalStateException("dynamic classpath entry value update not supported");
- // easy enough to add, just support unload+reload (and can also allow dynamic setScan below)
- // but more predictable if we don't; the one exception is in the manualAdditionsCatalog
- // where BasicBrooklynCatalog reaches in and updates the DTO and/or CompositeClassLoader directly, if necessary
-// for (String url: urls)
-// loadedClasspath.addEntry(url);
- }
-
- public synchronized void setClasspathScanForEntities(CatalogScanningModes value) {
- if (dto.classpath == null)
- dto.classpath = new CatalogClasspathDto();
- dto.classpath.scan = value;
- if (isLoaded())
- throw new IllegalStateException("dynamic classpath scan value update not supported");
- // easy enough to add, see above
- }
-
- @Override
- public String toString() {
- String size = cacheById == null ? "not yet loaded" : "size " + cacheById.size();
- return "Loaded:" + dto + "(" + size + ")";
- }
-
- /** is "local" if it and all ancestors are not based on any remote urls */
- public boolean isLocal() {
- if (dto.url != null) {
- String proto = Urls.getProtocol(dto.url);
- if (proto != null) {
- // 'file' is the only protocol accepted as "local"
- if (!"file".equals(proto)) return false;
- }
- }
- return parent == null || parent.isLocal();
- }
-
- /** classloader for only the entries in this catalog's classpath */
- public ClassLoader getLocalClassLoader() {
- if (classpath != null) return classpath.getLocalClassLoader();
- return null;
- }
-
- /** recursive classloader is the local classloader plus all children catalog's classloader */
- public ClassLoader getRecursiveClassLoader() {
- if (recursiveClassLoader == null) loadRecursiveClassLoader();
- return recursiveClassLoader;
- }
-
- protected synchronized void loadRecursiveClassLoader() {
- if (recursiveClassLoader!=null) return;
- AggregateClassLoader cl = AggregateClassLoader.newInstanceWithNoLoaders();
- cl.addFirst(childrenClassLoader);
- ClassLoader local = getLocalClassLoader();
- if (local != null) cl.addFirst(local);
- if (parent == null) {
- // we are root. include the mgmt base classloader and/or standard class loaders
- ClassLoader base = mgmt != null ? ((ManagementContextInternal)mgmt).getBaseClassLoader() : null;
- if (base != null) cl.addFirst(base);
- else {
- cl.addFirst(getClass().getClassLoader());
- cl.addFirst(Object.class.getClassLoader());
- }
- }
- recursiveClassLoader = cl;
- }
-
- /** the root classloader is the recursive CL from the outermost catalog
- * (which includes the base classloader from the mgmt context, if set) */
- public ClassLoader getRootClassLoader() {
- if (parent != null) return parent.getRootClassLoader();
- return getRecursiveClassLoader();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
deleted file mode 100644
index 535ce33..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDto.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.io.InputStream;
-import java.io.StringReader;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.PropagatedRuntimeException;
-import brooklyn.util.stream.Streams;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Lists;
-
-@Beta
-public class CatalogDto {
-
- private static final Logger LOG = LoggerFactory.getLogger(CatalogDto.class);
-
- String id;
- String url;
- String contents;
- String contentsDescription;
- String name;
- String description;
- CatalogClasspathDto classpath;
- private List<CatalogItemDtoAbstract<?,?>> entries = null;
-
- // for thread-safety, any dynamic additions to this should be handled by a method
- // in this class which does copy-on-write
- List<CatalogDto> catalogs = null;
-
- public static CatalogDto newDefaultLocalScanningDto(CatalogClasspathDo.CatalogScanningModes scanMode) {
- CatalogDo result = new CatalogDo(
- newNamedInstance("Local Scanned Catalog", "All annotated Brooklyn entities detected in the default classpath", "scanning-local-classpath") );
- result.setClasspathScanForEntities(scanMode);
- return result.dto;
- }
-
- /** @deprecated since 0.7.0 use {@link #newDtoFromXmlUrl(String)} if you must, but note the xml format itself is deprecated */
- @Deprecated
- public static CatalogDto newDtoFromUrl(String url) {
- return newDtoFromXmlUrl(url);
- }
-
- /** @deprecated since 0.7.0 the xml format is deprecated; use YAML parse routines on BasicBrooklynCatalog */
- @Deprecated
- public static CatalogDto newDtoFromXmlUrl(String url) {
- if (LOG.isDebugEnabled()) LOG.debug("Retrieving catalog from: {}", url);
- try {
- InputStream source = ResourceUtils.create().getResourceFromUrl(url);
- String contents = Streams.readFullyString(source);
- return newDtoFromXmlContents(contents, url);
- } catch (Throwable t) {
- Exceptions.propagateIfFatal(t);
- throw new PropagatedRuntimeException("Unable to retrieve catalog from " + url + ": " + t, t);
- }
- }
-
- /** @deprecated since 0.7.0 the xml format is deprecated; use YAML parse routines on BasicBrooklynCatalog */
- @Deprecated
- public static CatalogDto newDtoFromXmlContents(String xmlContents, String originDescription) {
- CatalogDto result = (CatalogDto) new CatalogXmlSerializer().deserialize(new StringReader(xmlContents));
- result.contentsDescription = originDescription;
-
- if (LOG.isDebugEnabled()) LOG.debug("Retrieved catalog from: {}", originDescription);
- return result;
- }
-
- /**
- * Creates a DTO.
- * <p>
- * The way contents is treated may change; thus this (and much of catalog) should be treated as beta.
- *
- * @param name
- * @param description
- * @param optionalContentsDescription optional description of contents; if null, we normally expect source 'contents' to be set later;
- * if the DTO has no 'contents' (ie XML source) then a description should be supplied so we know who is populating it
- * (e.g. manual additions); without this, warnings may be generated
- *
- * @return a new Catalog DTO
- */
- public static CatalogDto newNamedInstance(String name, String description, String optionalContentsDescription) {
- CatalogDto result = new CatalogDto();
- result.name = name;
- result.description = description;
- if (optionalContentsDescription!=null) result.contentsDescription = optionalContentsDescription;
- return result;
- }
-
- /** Used when caller wishes to create an explicitly empty catalog */
- public static CatalogDto newEmptyInstance(String optionalContentsDescription) {
- CatalogDto result = new CatalogDto();
- if (optionalContentsDescription!=null) result.contentsDescription = optionalContentsDescription;
- return result;
- }
-
- public static CatalogDto newLinkedInstance(String url) {
- CatalogDto result = new CatalogDto();
- result.contentsDescription = url;
- result.contents = ResourceUtils.create().getResourceAsString(url);
- return result;
- }
-
- /** @deprecated since 0.7.0 use {@link #newDtoFromCatalogItems(Collection, String)}, supplying a description for tracking */
- @Deprecated
- public static CatalogDto newDtoFromCatalogItems(Collection<CatalogItem<?, ?>> entries) {
- return newDtoFromCatalogItems(entries, null);
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static CatalogDto newDtoFromCatalogItems(Collection<CatalogItem<?, ?>> entries, String description) {
- CatalogDto result = new CatalogDto();
- result.contentsDescription = description;
- // Weird casts because compiler does not seem to like
- // .copyInto(Lists.<CatalogItemDtoAbstract<?, ?>>newArrayListWithExpectedSize(entries.size()));
- result.entries = (List<CatalogItemDtoAbstract<?, ?>>) (List) FluentIterable.from(entries)
- .filter(CatalogItemDtoAbstract.class)
- .copyInto(Lists.newArrayListWithExpectedSize(entries.size()));
- return result;
- }
-
- void populate() {
- if (contents==null) {
- if (url != null) {
- contents = ResourceUtils.create().getResourceAsString(url);
- contentsDescription = url;
- } else if (contentsDescription==null) {
- LOG.debug("Catalog DTO has no contents and no description; ignoring call to populate it. Description should be set to suppress this message.");
- return;
- } else {
- LOG.trace("Nothing needs doing (no contents or URL) for catalog with contents described as "+contentsDescription+".");
- return;
- }
- }
-
- CatalogDto remoteDto = newDtoFromXmlContents(contents, contentsDescription);
- try {
- copyFrom(remoteDto, true);
- } catch (Exception e) {
- Exceptions.propagate(e);
- }
- }
-
- /**
- * @throws NullPointerException If source is null (and !skipNulls)
- */
- void copyFrom(CatalogDto source, boolean skipNulls) throws IllegalAccessException {
- if (source==null) {
- if (skipNulls) return;
- throw new NullPointerException("source DTO is null, when copying to "+this);
- }
-
- if (!skipNulls || source.id != null) id = source.id;
- if (!skipNulls || source.contentsDescription != null) contentsDescription = source.contentsDescription;
- if (!skipNulls || source.contents != null) contents = source.contents;
- if (!skipNulls || source.name != null) name = source.name;
- if (!skipNulls || source.description != null) description = source.description;
- if (!skipNulls || source.classpath != null) classpath = source.classpath;
- if (!skipNulls || source.entries != null) entries = source.entries;
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this)
- .omitNullValues()
- .add("name", name)
- .add("id", id)
- .add("contentsDescription", contentsDescription)
- .toString();
- }
-
- // temporary fix for issue where entries might not be unique
- Iterable<CatalogItemDtoAbstract<?, ?>> getUniqueEntries() {
- if (entries==null) return null;
- Map<String, CatalogItemDtoAbstract<?, ?>> result = getEntriesMap();
- return result.values();
- }
-
- private Map<String, CatalogItemDtoAbstract<?, ?>> getEntriesMap() {
- if (entries==null) return null;
- Map<String,CatalogItemDtoAbstract<?, ?>> result = MutableMap.of();
- for (CatalogItemDtoAbstract<?,?> entry: entries) {
- result.put(entry.getId(), entry);
- }
- return result;
- }
-
- void removeEntry(CatalogItemDtoAbstract<?, ?> entry) {
- if (entries!=null)
- entries.remove(entry);
- }
-
- void addEntry(CatalogItemDtoAbstract<?, ?> entry) {
- if (entries == null) entries = MutableList.of();
- CatalogItemDtoAbstract<?, ?> oldEntry = getEntriesMap().get(entry.getId());
- entries.add(entry);
- if (oldEntry!=null)
- removeEntry(oldEntry);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDtoUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDtoUtils.java
deleted file mode 100644
index cb44cb0..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDtoUtils.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.exceptions.Exceptions;
-
-public class CatalogDtoUtils {
-
- private static final Logger log = LoggerFactory.getLogger(CatalogDtoUtils.class);
-
- public static CatalogDto newDefaultLocalScanningDto(CatalogScanningModes scanMode) {
- return CatalogDto.newDefaultLocalScanningDto(scanMode);
- }
-
- /** throws if there are any problems in retrieving or copying */
- public static void populateFromUrl(CatalogDto dto, String url) {
- CatalogDto remoteDto = newDtoFromUrl(url);
- try {
- copyDto(remoteDto, dto, true);
- } catch (Exception e) {
- Exceptions.propagate(e);
- }
- }
-
- /** does a shallow copy.
- * "skipNulls" means not to copy any fields from the source which are null */
- static void copyDto(CatalogDto source, CatalogDto target, boolean skipNulls) throws IllegalArgumentException, IllegalAccessException {
- target.copyFrom(source, skipNulls);
- }
-
- public static CatalogDto newDtoFromUrl(String url) {
- if (log.isDebugEnabled()) log.debug("Retrieving catalog from: {}", url);
- try {
- InputStream source = ResourceUtils.create().getResourceFromUrl(url);
- CatalogDto result = (CatalogDto) new CatalogXmlSerializer().deserialize(new InputStreamReader(source));
- if (log.isDebugEnabled()) log.debug("Retrieved catalog from: {}", url);
- return result;
- } catch (Throwable t) {
- log.debug("Unable to retrieve catalog from: "+url+" ("+t+")");
- throw Exceptions.propagate(t);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
deleted file mode 100644
index 577eff5..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogEntityItemDto.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-
-
-public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySpec<?>> {
-
- @Override
- public CatalogItemType getCatalogItemType() {
- return CatalogItemType.ENTITY;
- }
-
- @Override
- public Class<Entity> getCatalogItemJavaType() {
- return Entity.class;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Class<EntitySpec<?>> getSpecType() {
- return (Class)EntitySpec.class;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java b/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
deleted file mode 100644
index 07eac9b..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.core.management.ManagementContextInjectable;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.FatalRuntimeException;
-import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.os.Os;
-import brooklyn.util.text.Strings;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
-@Beta
-public class CatalogInitialization implements ManagementContextInjectable {
-
- /*
-
- A1) if not persisting, go to B1
- A2) if --catalog-reset, delete persisted catalog items
- A3) if there is a persisted catalog (and it wasn't not deleted by A2), read it and go to C1
- A4) go to B1
-
- B1) look for --catalog-initial, if so read it, then go to C1
- B2) look for BrooklynServerConfig.BROOKLYN_CATALOG_URL, if so, read it, supporting YAML or XML (warning if XML), then go to C1
- B3) look for ~/.brooklyn/catalog.bom, if exists, read it then go to C1
- B4) look for ~/.brooklyn/brooklyn.xml, if exists, warn, read it then go to C1
- B5) read all classpath://brooklyn/default.catalog.bom items, if they exist (and for now they will)
- B6) go to C1
-
- C1) if --catalog-add, read and add those items
-
- D1) if persisting, read the rest of the persisted items (entities etc)
-
- */
-
- private static final Logger log = LoggerFactory.getLogger(CatalogInitialization.class);
-
- private String initialUri;
- private boolean reset;
- private String additionsUri;
- private boolean force;
-
- private boolean disallowLocal = false;
- private List<Function<CatalogInitialization, Void>> callbacks = MutableList.of();
- private boolean
- /** has run an unofficial initialization (i.e. an early load, triggered by an early read of the catalog) */
- hasRunUnofficialInitialization = false,
- /** has run an official initialization, but it is not a permanent one (e.g. during a hot standby mode, or a run failed) */
- hasRunTransientOfficialInitialization = false,
- /** has run an official initialization which is permanent (node is master, and the new catalog is now set) */
- hasRunFinalInitialization = false;
- /** is running a populate method; used to prevent recursive loops */
- private boolean isPopulating = false;
-
- private ManagementContext managementContext;
- private boolean isStartingUp = false;
- private boolean failOnStartupErrors = false;
-
- private Object populatingCatalogMutex = new Object();
-
- public CatalogInitialization(String initialUri, boolean reset, String additionUri, boolean force) {
- this.initialUri = initialUri;
- this.reset = reset;
- this.additionsUri = additionUri;
- this.force = force;
- }
-
- public CatalogInitialization() {
- this(null, false, null, false);
- }
-
- @Override
- public void injectManagementContext(ManagementContext managementContext) {
- Preconditions.checkNotNull(managementContext, "management context");
- if (this.managementContext!=null && managementContext!=this.managementContext)
- throw new IllegalStateException("Cannot switch management context, from "+this.managementContext+" to "+managementContext);
- this.managementContext = managementContext;
- }
-
- /** Called by the framework to set true while starting up, and false afterwards,
- * in order to assist in appropriate logging and error handling. */
- public void setStartingUp(boolean isStartingUp) {
- this.isStartingUp = isStartingUp;
- }
-
- public void setFailOnStartupErrors(boolean startupFailOnCatalogErrors) {
- this.failOnStartupErrors = startupFailOnCatalogErrors;
- }
-
- public CatalogInitialization addPopulationCallback(Function<CatalogInitialization, Void> callback) {
- callbacks.add(callback);
- return this;
- }
-
- public ManagementContext getManagementContext() {
- return Preconditions.checkNotNull(managementContext, "management context has not been injected into "+this);
- }
-
- public boolean isInitialResetRequested() {
- return reset;
- }
-
- /** Returns true if the canonical initialization has completed,
- * that is, an initialization which is done when a node is rebinded as master
- * (or an initialization done by the startup routines when not running persistence);
- * see also {@link #hasRunAnyInitialization()}. */
- public boolean hasRunFinalInitialization() { return hasRunFinalInitialization; }
- /** Returns true if an official initialization has run,
- * even if it was a transient run, e.g. so that the launch sequence can tell whether rebind has triggered initialization */
- public boolean hasRunOfficialInitialization() { return hasRunFinalInitialization || hasRunTransientOfficialInitialization; }
- /** Returns true if the initializer has run at all,
- * including transient initializations which might be needed before a canonical becoming-master rebind,
- * for instance because the catalog is being accessed before loading rebind information
- * (done by {@link #populateUnofficial(BasicBrooklynCatalog)}) */
- public boolean hasRunAnyInitialization() { return hasRunFinalInitialization || hasRunTransientOfficialInitialization || hasRunUnofficialInitialization; }
-
- /** makes or updates the mgmt catalog, based on the settings in this class
- * @param nodeState the management node for which this is being read; if master, then we expect this run to be the last one,
- * and so subsequent applications should ignore any initialization data (e.g. on a subsequent promotion to master,
- * after a master -> standby -> master cycle)
- * @param needsInitialItemsLoaded whether the catalog needs the initial items loaded
- * @param needsAdditionalItemsLoaded whether the catalog needs the additions loaded
- * @param optionalExcplicitItemsForResettingCatalog
- * if supplied, the catalog is reset to contain only these items, before calling any other initialization
- * for use primarily when rebinding
- */
- public void populateCatalog(ManagementNodeState nodeState, boolean needsInitialItemsLoaded, boolean needsAdditionsLoaded, Collection<CatalogItem<?, ?>> optionalExcplicitItemsForResettingCatalog) {
- if (log.isDebugEnabled()) {
- String message = "Populating catalog for "+nodeState+", needsInitial="+needsInitialItemsLoaded+", needsAdditional="+needsAdditionsLoaded+", explicitItems="+(optionalExcplicitItemsForResettingCatalog==null ? "null" : optionalExcplicitItemsForResettingCatalog.size())+"; from "+JavaClassNames.callerNiceClassAndMethod(1);
- if (!ManagementNodeState.isHotProxy(nodeState)) {
- log.debug(message);
- } else {
- // in hot modes, make this message trace so we don't get too much output then
- log.trace(message);
- }
- }
- synchronized (populatingCatalogMutex) {
- try {
- if (hasRunFinalInitialization() && (needsInitialItemsLoaded || needsAdditionsLoaded)) {
- // if we have already run "final" then we should only ever be used to reset the catalog,
- // not to initialize or add; e.g. we are being given a fixed list on a subsequent master rebind after the initial master rebind
- log.warn("Catalog initialization called to populate initial, even though it has already run the final official initialization");
- }
- isPopulating = true;
- BasicBrooklynCatalog catalog = (BasicBrooklynCatalog) managementContext.getCatalog();
- if (!catalog.getCatalog().isLoaded()) {
- catalog.load();
- } else {
- if (needsInitialItemsLoaded && hasRunAnyInitialization()) {
- // an indication that something caused it to load early; not severe, but unusual
- if (hasRunTransientOfficialInitialization) {
- log.debug("Catalog initialization now populating, but has noted a previous official run which was not final (probalby loaded while in a standby mode, or a previous run failed); overwriting any items installed earlier");
- } else {
- log.warn("Catalog initialization now populating, but has noted a previous unofficial run (it may have been an early web request); overwriting any items installed earlier");
- }
- catalog.reset(ImmutableList.<CatalogItem<?,?>>of());
- }
- }
-
- populateCatalogImpl(catalog, needsInitialItemsLoaded, needsAdditionsLoaded, optionalExcplicitItemsForResettingCatalog);
- if (nodeState == ManagementNodeState.MASTER) {
- // TODO ideally this would remain false until it has *persisted* the changed catalog;
- // if there is a subsequent startup failure the forced additions will not be persisted,
- // but nor will they be loaded on a subsequent run.
- // callers will have to restart a brooklyn, or reach into this class to change this field,
- // or (recommended) manually adjust the catalog.
- // TODO also, if a node comes up in standby, the addition might not take effector for a while
- //
- // however since these options are mainly for use on the very first brooklyn run, it's not such a big deal;
- // once up and running the typical way to add items is via the REST API
- hasRunFinalInitialization = true;
- }
- } finally {
- if (!hasRunFinalInitialization) {
- hasRunTransientOfficialInitialization = true;
- }
- isPopulating = false;
- }
- }
- }
-
- private void populateCatalogImpl(BasicBrooklynCatalog catalog, boolean needsInitialItemsLoaded, boolean needsAdditionsLoaded, Collection<CatalogItem<?, ?>> optionalItemsForResettingCatalog) {
- applyCatalogLoadMode();
-
- if (optionalItemsForResettingCatalog!=null) {
- catalog.reset(optionalItemsForResettingCatalog);
- }
-
- if (needsInitialItemsLoaded) {
- populateInitial(catalog);
- }
-
- if (needsAdditionsLoaded) {
- populateAdditions(catalog);
- populateViaCallbacks(catalog);
- }
- }
-
- private enum PopulateMode { YAML, XML, AUTODETECT }
-
- protected void populateInitial(BasicBrooklynCatalog catalog) {
- if (disallowLocal) {
- if (!hasRunFinalInitialization()) {
- log.debug("CLI initial catalog not being read when local catalog load mode is disallowed.");
- }
- return;
- }
-
-// B1) look for --catalog-initial, if so read it, then go to C1
-// B2) look for BrooklynServerConfig.BROOKLYN_CATALOG_URL, if so, read it, supporting YAML or XML (warning if XML), then go to C1
-// B3) look for ~/.brooklyn/catalog.bom, if exists, read it then go to C1
-// B4) look for ~/.brooklyn/brooklyn.xml, if exists, warn, read it then go to C1
-// B5) read all classpath://brooklyn/default.catalog.bom items, if they exist (and for now they will)
-// B6) go to C1
-
- if (initialUri!=null) {
- populateInitialFromUri(catalog, initialUri, PopulateMode.AUTODETECT);
- return;
- }
-
- String catalogUrl = managementContext.getConfig().getConfig(BrooklynServerConfig.BROOKLYN_CATALOG_URL);
- if (Strings.isNonBlank(catalogUrl)) {
- populateInitialFromUri(catalog, catalogUrl, PopulateMode.AUTODETECT);
- return;
- }
-
- catalogUrl = Os.mergePaths(BrooklynServerConfig.getMgmtBaseDir( managementContext.getConfig() ), "catalog.bom");
- if (new File(catalogUrl).exists()) {
- populateInitialFromUri(catalog, new File(catalogUrl).toURI().toString(), PopulateMode.YAML);
- return;
- }
-
- catalogUrl = Os.mergePaths(BrooklynServerConfig.getMgmtBaseDir( managementContext.getConfig() ), "catalog.xml");
- if (new File(catalogUrl).exists()) {
- populateInitialFromUri(catalog, new File(catalogUrl).toURI().toString(), PopulateMode.XML);
- return;
- }
-
- // otherwise look for for classpath:/brooklyn/default.catalog.bom --
- // there is one on the classpath which says to scan, and provides a few templates;
- // if one is supplied by user in the conf/ dir that will override the item from the classpath
- // (TBD - we might want to scan for all such bom's?)
-
- catalogUrl = "classpath:/brooklyn/default.catalog.bom";
- if (new ResourceUtils(this).doesUrlExist(catalogUrl)) {
- populateInitialFromUri(catalog, catalogUrl, PopulateMode.YAML);
- return;
- }
-
- log.info("No catalog found on classpath or specified; catalog will not be initialized.");
- return;
- }
-
- private void populateInitialFromUri(BasicBrooklynCatalog catalog, String catalogUrl, PopulateMode mode) {
- log.debug("Loading initial catalog from {}", catalogUrl);
-
- Exception problem = null;
- Object result = null;
-
- String contents = null;
- try {
- contents = new ResourceUtils(this).getResourceAsString(catalogUrl);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- if (problem==null) problem = e;
- }
-
- if (contents!=null && (mode==PopulateMode.YAML || mode==PopulateMode.AUTODETECT)) {
- // try YAML first
- try {
- catalog.reset(MutableList.<CatalogItem<?,?>>of());
- result = catalog.addItems(contents);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- if (problem==null) problem = e;
- }
- }
-
- if (result==null && contents!=null && (mode==PopulateMode.XML || mode==PopulateMode.AUTODETECT)) {
- // then try XML
- try {
- populateInitialFromUriXml(catalog, catalogUrl, contents);
- // clear YAML problem
- problem = null;
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- if (problem==null) problem = e;
- }
- }
-
- if (result!=null) {
- log.debug("Loaded initial catalog from {}: {}", catalogUrl, result);
- }
- if (problem!=null) {
- log.warn("Error importing catalog from " + catalogUrl + ": " + problem, problem);
- // TODO inform mgmt of error
- }
-
- }
-
- // deprecated XML format
- @SuppressWarnings("deprecation")
- private void populateInitialFromUriXml(BasicBrooklynCatalog catalog, String catalogUrl, String contents) {
- CatalogDto dto = CatalogDto.newDtoFromXmlContents(contents, catalogUrl);
- if (dto!=null) {
- catalog.reset(dto);
- }
- }
-
- boolean hasRunAdditions = false;
- protected void populateAdditions(BasicBrooklynCatalog catalog) {
- if (Strings.isNonBlank(additionsUri)) {
- if (disallowLocal) {
- if (!hasRunAdditions) {
- log.warn("CLI additions supplied but not supported when catalog load mode disallows local loads; ignoring.");
- }
- return;
- }
- if (!hasRunAdditions) {
- log.debug("Adding to catalog from CLI: "+additionsUri+" (force: "+force+")");
- }
- Iterable<? extends CatalogItem<?, ?>> items = catalog.addItems(
- new ResourceUtils(this).getResourceAsString(additionsUri), force);
-
- if (!hasRunAdditions)
- log.debug("Added to catalog from CLI: "+items);
- else
- log.debug("Added to catalog from CLI: count "+Iterables.size(items));
-
- hasRunAdditions = true;
- }
- }
-
- protected void populateViaCallbacks(BasicBrooklynCatalog catalog) {
- for (Function<CatalogInitialization, Void> callback: callbacks)
- callback.apply(this);
- }
-
- private Object setFromCLMMutex = new Object();
- private boolean setFromCatalogLoadMode = false;
-
- /** @deprecated since introduced in 0.7.0, only for legacy compatibility with
- * {@link CatalogLoadMode} {@link BrooklynServerConfig#CATALOG_LOAD_MODE},
- * allowing control of catalog loading from a brooklyn property */
- @Deprecated
- public void applyCatalogLoadMode() {
- synchronized (setFromCLMMutex) {
- if (setFromCatalogLoadMode) return;
- setFromCatalogLoadMode = true;
- Maybe<Object> clmm = ((ManagementContextInternal)managementContext).getConfig().getConfigRaw(BrooklynServerConfig.CATALOG_LOAD_MODE, false);
- if (clmm.isAbsent()) return;
- brooklyn.catalog.CatalogLoadMode clm = TypeCoercions.coerce(clmm.get(), brooklyn.catalog.CatalogLoadMode.class);
- log.warn("Legacy CatalogLoadMode "+clm+" set: applying, but this should be changed to use new CLI --catalogXxx commands");
- switch (clm) {
- case LOAD_BROOKLYN_CATALOG_URL:
- reset = true;
- break;
- case LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE:
- // now the default
- break;
- case LOAD_PERSISTED_STATE:
- disallowLocal = true;
- break;
- }
- }
- }
-
- /** Creates the catalog based on parameters set here, if not yet loaded,
- * but ignoring persisted state and warning if persistence is on and we are starting up
- * (because the official persistence is preferred and the catalog will be subsequently replaced);
- * for use when the catalog is accessed before persistence is completed.
- * <p>
- * This method is primarily used during testing, which in many cases does not enforce the full startup order
- * and which wants a local catalog in any case. It may also be invoked if a client requests the catalog
- * while the server is starting up. */
- public void populateUnofficial(BasicBrooklynCatalog catalog) {
- synchronized (populatingCatalogMutex) {
- // check isPopulating in case this method gets called from inside another populate call
- if (hasRunAnyInitialization() || isPopulating) return;
- log.debug("Populating catalog unofficially ("+catalog+")");
- isPopulating = true;
- try {
- if (isStartingUp) {
- log.warn("Catalog access requested when not yet initialized; populating best effort rather than through recommended pathway. Catalog data may be replaced subsequently.");
- }
- populateCatalogImpl(catalog, true, true, null);
- } finally {
- hasRunUnofficialInitialization = true;
- isPopulating = false;
- }
- }
- }
-
- public void handleException(Throwable throwable, Object details) {
- if (throwable instanceof InterruptedException)
- throw new RuntimeInterruptedException((InterruptedException) throwable);
- if (throwable instanceof RuntimeInterruptedException)
- throw (RuntimeInterruptedException) throwable;
-
- log.error("Error loading catalog item '"+details+"': "+throwable);
- log.debug("Trace for error loading catalog item '"+details+"': "+throwable, throwable);
-
- // TODO give more detail when adding
- ((ManagementContextInternal)getManagementContext()).errors().add(throwable);
-
- if (isStartingUp && failOnStartupErrors) {
- throw new FatalRuntimeException("Unable to load catalog item '"+details+"': "+throwable, throwable);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
deleted file mode 100644
index 0001ac9..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemBuilder.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-
-import com.google.common.base.Preconditions;
-
-public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?, ?>> {
- private CatalogItemType dto;
-
- public static CatalogItemBuilder<CatalogEntityItemDto> newEntity(String symbolicName, String version) {
- return new CatalogItemBuilder<CatalogEntityItemDto>(new CatalogEntityItemDto())
- .symbolicName(symbolicName)
- .version(version);
- }
-
- public static CatalogItemBuilder<CatalogTemplateItemDto> newTemplate(String symbolicName, String version) {
- return new CatalogItemBuilder<CatalogTemplateItemDto>(new CatalogTemplateItemDto())
- .symbolicName(symbolicName)
- .version(version);
- }
-
- public static CatalogItemBuilder<CatalogPolicyItemDto> newPolicy(String symbolicName, String version) {
- return new CatalogItemBuilder<CatalogPolicyItemDto>(new CatalogPolicyItemDto())
- .symbolicName(symbolicName)
- .version(version);
- }
-
- public static CatalogItemBuilder<CatalogLocationItemDto> newLocation(String symbolicName, String version) {
- return new CatalogItemBuilder<CatalogLocationItemDto>(new CatalogLocationItemDto())
- .symbolicName(symbolicName)
- .version(version);
- }
-
- public CatalogItemBuilder(CatalogItemType dto) {
- this.dto = dto;
- this.dto.setLibraries(Collections.<CatalogBundle>emptyList());
- }
-
- public CatalogItemBuilder<CatalogItemType> symbolicName(String symbolicName) {
- dto.setSymbolicName(symbolicName);
- return this;
- }
-
- @Deprecated
- public CatalogItemBuilder<CatalogItemType> javaType(String javaType) {
- dto.setJavaType(javaType);
- return this;
- }
-
- /** @deprecated since 0.7.0 use {@link #displayName}*/
- @Deprecated
- public CatalogItemBuilder<CatalogItemType> name(String name) {
- return displayName(name);
- }
-
- public CatalogItemBuilder<CatalogItemType> displayName(String displayName) {
- dto.setDisplayName(displayName);
- return this;
- }
-
- public CatalogItemBuilder<CatalogItemType> description(String description) {
- dto.setDescription(description);
- return this;
- }
-
- public CatalogItemBuilder<CatalogItemType> iconUrl(String iconUrl) {
- dto.setIconUrl(iconUrl);
- return this;
- }
-
- public CatalogItemBuilder<CatalogItemType> version(String version) {
- dto.setVersion(version);
- return this;
- }
-
- public CatalogItemBuilder<CatalogItemType> deprecated(boolean deprecated) {
- dto.setDeprecated(deprecated);
- return this;
- }
-
- public CatalogItemBuilder<CatalogItemType> libraries(Collection<CatalogBundle> libraries) {
- dto.setLibraries(libraries);
- return this;
- }
-
- public CatalogItemBuilder<CatalogItemType> plan(String yaml) {
- dto.setPlanYaml(yaml);
- return this;
- }
-
- public CatalogItemType build() {
- Preconditions.checkNotNull(dto.getSymbolicName());
- Preconditions.checkNotNull(dto.getVersion());
-
- if (dto.getLibraries() == null) {
- dto.setLibraries(Collections.<CatalogBundle>emptyList());
- }
-
- CatalogItemType ret = dto;
-
- //prevent mutations through the builder
- dto = null;
-
- return ret;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogItemComparator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemComparator.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemComparator.java
deleted file mode 100644
index 8b868cc..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemComparator.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-
-import brooklyn.util.text.NaturalOrderComparator;
-
-/**
- * Largest version first order.
- *
- * When using the comparator to sort - first using symbolicName
- * and if equal puts larger versions first, snapshots at the back.
- */
-public class CatalogItemComparator<T,SpecT> implements Comparator<CatalogItem<T, SpecT>> {
- private static final String SNAPSHOT = "SNAPSHOT";
-
- public static final CatalogItemComparator<?, ?> INSTANCE = new CatalogItemComparator<Object, Object>();
-
- @SuppressWarnings("unchecked")
- public static <T,SpecT> CatalogItemComparator<T,SpecT> getInstance() {
- return (CatalogItemComparator<T, SpecT>) INSTANCE;
- }
-
- @Override
- public int compare(CatalogItem<T, SpecT> o1, CatalogItem<T, SpecT> o2) {
- int symbolicNameComparison = o1.getSymbolicName().compareTo(o2.getSymbolicName());
- if (symbolicNameComparison != 0) {
- return symbolicNameComparison;
- } else {
- String v1 = o1.getVersion();
- String v2 = o2.getVersion();
-
- boolean isV1Snapshot = v1.toUpperCase().contains(SNAPSHOT);
- boolean isV2Snapshot = v2.toUpperCase().contains(SNAPSHOT);
- if (isV1Snapshot == isV2Snapshot) {
- String[] v1Parts = split(v1);
- String[] v2Parts = split(v2);
- return -compare(v1Parts, v2Parts);
- } else if (isV1Snapshot) {
- return 1;
- } else {
- return -1;
- }
- }
- }
-
- private String[] split(String v) {
- Collection<String> parts = new ArrayList<String>();
- int startPos = 0;
- int delimPos;
- while ((delimPos = v.indexOf('.', startPos)) != -1) {
- String part = v.substring(startPos, delimPos);
- if (parse(part) != -1) {
- parts.add(part);
- } else {
- break;
- }
- startPos = delimPos+1;
- }
- String remaining = v.substring(startPos);
- parts.addAll(Arrays.asList(remaining.split("[^\\d]", 2)));
- return parts.toArray(new String[parts.size()]);
- }
-
- private int compare(String[] v1Parts, String[] v2Parts) {
- int len = Math.max(v1Parts.length, v2Parts.length);
- for (int i = 0; i < len; i++) {
- if (i == v1Parts.length) {
- return isNumber(v2Parts[i]) ? -1 : 1;
- }
- if (i == v2Parts.length) {
- return isNumber(v1Parts[i]) ? 1 : -1;
- }
-
- String p1 = v1Parts[i];
- String p2 = v2Parts[i];
- int n1 = parse(p1);
- int n2 = parse(p2);
- if (n1 != -1 && n2 != -1) {
- if (n1 != n2) {
- return compare(n1, n2);
- }
- } else if (n1 == -1 && n2 != -1) {
- return -1;
- } else if (n1 != -1 && n2 == -1) {
- return 1;
- } else {
- int cmp = NaturalOrderComparator.INSTANCE.compare(p1, p2);
- if (cmp < 0) {
- return -1;
- } else if (cmp > 0) {
- return 1;
- }
- }
- }
- return 0;
- }
-
- private boolean isNumber(String v) {
- return parse(v) != -1;
- }
-
- //Replace with Integer.compare in J7
- private int compare(int n1, int n2) {
- if (n1 == n2) {
- return 0;
- } else if (n1 < n2) {
- return -1;
- } else {
- return 1;
- }
- }
-
- private int parse(String p) {
- try {
- return Integer.parseInt(p);
- } catch (NumberFormatException e) {
- return -1;
- }
- }
-}
[31/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/catalog
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
deleted file mode 100644
index 6e9f963..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.Collection;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import brooklyn.basic.BrooklynObjectInternal;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.rebind.RebindSupport;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.mementos.CatalogItemMemento;
-
-import brooklyn.config.ConfigKey;
-
-import com.google.common.base.Preconditions;
-
-public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObjectInternal {
-
- protected final CatalogDo catalog;
- protected final CatalogItemDtoAbstract<T,SpecT> itemDto;
-
- protected volatile Class<T> javaClass;
-
- public CatalogItemDo(CatalogDo catalog, CatalogItem<T,SpecT> itemDto) {
- this.catalog = Preconditions.checkNotNull(catalog, "catalog");
- this.itemDto = (CatalogItemDtoAbstract<T, SpecT>) Preconditions.checkNotNull(itemDto, "itemDto");
- }
-
- public CatalogItem<T,SpecT> getDto() {
- return itemDto;
- }
-
- /**
- * Config not supported for catalog item. See {@link #getPlanYaml()}.
- */
- @Override
- public ConfigurationSupportInternal config() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public <U> U setConfig(ConfigKey<U> key, U val) {
- return config().set(key, val);
- }
-
- @Override
- public CatalogItemType getCatalogItemType() {
- return itemDto.getCatalogItemType();
- }
-
- @Override
- public Class<T> getCatalogItemJavaType() {
- return itemDto.getCatalogItemJavaType();
- }
-
- @Override
- public String getId() {
- return itemDto.getId();
- }
-
- @Override
- public String getCatalogItemId() {
- return itemDto.getCatalogItemId();
- }
-
- @Override
- public void setDeprecated(boolean deprecated) {
- itemDto.setDeprecated(deprecated);
- }
-
- @Override
- public boolean isDeprecated() {
- return itemDto.isDeprecated();
- }
-
- @Override
- public void setCatalogItemId(String id) {
- itemDto.setCatalogItemId(id);
- }
-
- @Override
- public String getJavaType() {
- return itemDto.getJavaType();
- }
-
- @Deprecated
- @Override
- public String getName() {
- return getDisplayName();
- }
-
- @Deprecated
- @Override
- public String getRegisteredTypeName() {
- return getSymbolicName();
- }
-
- @Override
- public String getDisplayName() {
- return itemDto.getDisplayName();
- }
-
- @Override
- public TagSupport tags() {
- return itemDto.tags();
- }
-
- @Override
- public String getDescription() {
- return itemDto.getDescription();
- }
-
- @Override
- public String getIconUrl() {
- return itemDto.getIconUrl();
- }
-
- @Override
- public String getSymbolicName() {
- return itemDto.getSymbolicName();
- }
-
- @Override
- public String getVersion() {
- return itemDto.getVersion();
- }
-
- @Nonnull // but it is still null sometimes, see in CatalogDo.loadJavaClass
- @Override
- public Collection<CatalogBundle> getLibraries() {
- return itemDto.getLibraries();
- }
-
- /** @deprecated since 0.7.0 this is the legacy mechanism; still needed for policies and apps, but being phased out.
- * new items should use {@link #getPlanYaml} and {@link #newClassLoadingContext} */
- @Deprecated
- public Class<T> getJavaClass() {
- if (javaClass==null) loadJavaClass(null);
- return javaClass;
- }
-
- @SuppressWarnings("unchecked")
- Class<? extends T> loadJavaClass(final ManagementContext mgmt) {
- if (javaClass!=null) return javaClass;
- javaClass = (Class<T>)CatalogUtils.newClassLoadingContext(mgmt, getId(), getLibraries(), catalog.getRootClassLoader()).loadClass(getJavaType());
- return javaClass;
- }
-
- @Override
- public String toString() {
- return getClass().getCanonicalName()+"["+itemDto+"]";
- }
-
- @Override
- public String toXmlString() {
- return itemDto.toXmlString();
- }
-
- @Override
- public Class<SpecT> getSpecType() {
- return itemDto.getSpecType();
- }
-
- @Nullable @Override
- public String getPlanYaml() {
- return itemDto.getPlanYaml();
- }
-
- @Override
- public RebindSupport<CatalogItemMemento> getRebindSupport() {
- return itemDto.getRebindSupport();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
deleted file mode 100644
index b72f55f..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.basic.AbstractBrooklynObject;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.rebind.RebindSupport;
-import org.apache.brooklyn.api.mementos.CatalogItemMemento;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.rebind.BasicCatalogItemRebindSupport;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
-public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynObject implements CatalogItem<T, SpecT> {
-
- private static Logger LOG = LoggerFactory.getLogger(CatalogItemDtoAbstract.class);
-
- private @SetFromFlag String symbolicName;
- private @SetFromFlag String version = BasicBrooklynCatalog.NO_VERSION;
-
- private @SetFromFlag String displayName;
- private @SetFromFlag String description;
- private @SetFromFlag String iconUrl;
-
- private @SetFromFlag String javaType;
- /**@deprecated since 0.7.0, left for deserialization backwards compatibility */
- private @Deprecated @SetFromFlag String type;
- private @SetFromFlag String planYaml;
-
- private @SetFromFlag Collection<CatalogBundle> libraries;
- private @SetFromFlag Set<Object> tags = Sets.newLinkedHashSet();
- private @SetFromFlag boolean deprecated;
-
- /**
- * Config not supported for catalog item. See {@link #getPlanYaml()}.
- */
- @Override
- public ConfigurationSupportInternal config() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public <U> U setConfig(ConfigKey<U> key, U val) {
- return config().set(key, val);
- }
-
- @Override
- public String getId() {
- return getCatalogItemId();
- }
-
- @Override
- public String getCatalogItemId() {
- return CatalogUtils.getVersionedId(getSymbolicName(), getVersion());
- }
-
- @Override
- public String getJavaType() {
- if (javaType != null) return javaType;
- return type;
- }
-
- @Deprecated
- public String getName() {
- return getDisplayName();
- }
-
- @Deprecated
- public String getRegisteredTypeName() {
- return getSymbolicName();
- }
-
- @Override
- public String getDisplayName() {
- return displayName;
- }
-
- @Override
- public String getDescription() {
- return description;
- }
-
- @Override
- public String getIconUrl() {
- return iconUrl;
- }
-
- @Override
- public String getSymbolicName() {
- if (symbolicName != null) return symbolicName;
- return getJavaType();
- }
-
- @Override
- public String getVersion() {
- // The property is set to NO_VERSION when the object is initialized so it's not supposed to be null ever.
- // But xstream doesn't call constructors when reading from the catalog.xml file which results in null value
- // for the version property. That's why we have to fix it in the getter.
- if (version != null) {
- return version;
- } else {
- return BasicBrooklynCatalog.NO_VERSION;
- }
- }
-
- @Override
- public boolean isDeprecated() {
- return deprecated;
- }
-
- @Override
- public void setDeprecated(boolean deprecated) {
- this.deprecated = deprecated;
- }
-
- @Nonnull
- @Override
- public Collection<CatalogBundle> getLibraries() {
- if (libraries != null) {
- return ImmutableList.copyOf(libraries);
- } else {
- return Collections.emptyList();
- }
- }
-
- @Nullable @Override
- public String getPlanYaml() {
- return planYaml;
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(symbolicName, planYaml, javaType, nullIfEmpty(libraries), version, getCatalogItemId());
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- CatalogItemDtoAbstract<?,?> other = (CatalogItemDtoAbstract<?,?>) obj;
- if (!Objects.equal(symbolicName, other.symbolicName)) return false;
- if (!Objects.equal(planYaml, other.planYaml)) return false;
- if (!Objects.equal(javaType, other.javaType)) return false;
- if (!Objects.equal(nullIfEmpty(libraries), nullIfEmpty(other.libraries))) return false;
- if (!Objects.equal(getCatalogItemId(), other.getCatalogItemId())) return false;
- if (!Objects.equal(version, other.version)) return false;
- if (!Objects.equal(deprecated, other.deprecated)) return false;
- if (!Objects.equal(description, other.description)) return false;
- if (!Objects.equal(displayName, other.displayName)) return false;
- if (!Objects.equal(iconUrl, other.iconUrl)) return false;
- if (!Objects.equal(tags, other.tags)) return false;
- // 'type' not checked, because deprecated,
- // and in future we might want to allow it to be removed/blanked in some impls without affecting equality
- // (in most cases it is the same as symbolicName so doesn't matter)
- return true;
- }
-
- private static <T> Collection<T> nullIfEmpty(Collection<T> coll) {
- if (coll==null || coll.isEmpty()) return null;
- return coll;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName()+"["+getId()+"/"+getDisplayName()+"]";
- }
-
- public abstract Class<SpecT> getSpecType();
-
- transient CatalogXmlSerializer serializer;
-
- @Override
- public String toXmlString() {
- if (serializer==null) loadSerializer();
- return serializer.toString(this);
- }
-
- private synchronized void loadSerializer() {
- if (serializer == null) {
- serializer = new CatalogXmlSerializer();
- }
- }
-
- @Override
- public RebindSupport<CatalogItemMemento> getRebindSupport() {
- return new BasicCatalogItemRebindSupport(this);
- }
-
- @Override
- public void setDisplayName(String newName) {
- this.displayName = newName;
- }
-
- @Override
- protected AbstractBrooklynObject configure(Map<?, ?> flags) {
- FlagUtils.setFieldsFromFlags(flags, this);
- return this;
- }
-
- @Override
- public TagSupport tags() {
- return new BasicTagSupport();
- }
-
- /*
- * Using a custom tag support class rather than the one in AbstractBrooklynObject because
- * when XStream unmarshals a catalog item with no tags (e.g. from any catalog.xml file)
- * super.tags will be null, and any call to getTags throws a NullPointerException on the
- * synchronized (tags) statement. It can't just be initialised here because super.tags is
- * final.
- */
- private class BasicTagSupport implements TagSupport {
-
- private void setTagsIfNull() {
- // Possible if the class was unmarshalled by Xstream with no tags
- synchronized (CatalogItemDtoAbstract.this) {
- if (tags == null) {
- tags = Sets.newLinkedHashSet();
- }
- }
- }
-
- @Nonnull
- @Override
- public Set<Object> getTags() {
- synchronized (CatalogItemDtoAbstract.this) {
- setTagsIfNull();
- return ImmutableSet.copyOf(tags);
- }
- }
-
- @Override
- public boolean containsTag(Object tag) {
- synchronized (CatalogItemDtoAbstract.this) {
- setTagsIfNull();
- return tags.contains(tag);
- }
- }
-
- @Override
- public boolean addTag(Object tag) {
- boolean result;
- synchronized (CatalogItemDtoAbstract.this) {
- setTagsIfNull();
- result = tags.add(tag);
- }
- onTagsChanged();
- return result;
- }
-
- @Override
- public boolean addTags(Iterable<?> newTags) {
- boolean result;
- synchronized (CatalogItemDtoAbstract.this) {
- setTagsIfNull();
- result = Iterables.addAll(tags, newTags);
- }
- onTagsChanged();
- return result;
- }
-
- @Override
- public boolean removeTag(Object tag) {
- boolean result;
- synchronized (CatalogItemDtoAbstract.this) {
- setTagsIfNull();
- result = tags.remove(tag);
- }
- onTagsChanged();
- return result;
- }
- }
-
- @Override
- @Deprecated
- public void setCatalogItemId(String id) {
- //no op, should be used by rebind code only
- }
-
- protected void setSymbolicName(String symbolicName) {
- this.symbolicName = symbolicName;
- }
-
- protected void setVersion(String version) {
- this.version = version;
- }
-
- protected void setDescription(String description) {
- this.description = description;
- }
-
- protected void setIconUrl(String iconUrl) {
- this.iconUrl = iconUrl;
- }
-
- protected void setJavaType(String javaType) {
- this.javaType = javaType;
- this.type = null;
- }
-
- protected void setPlanYaml(String planYaml) {
- this.planYaml = planYaml;
- }
-
- protected void setLibraries(Collection<CatalogBundle> libraries) {
- this.libraries = libraries;
- }
-
- protected void setTags(Set<Object> tags) {
- this.tags = tags;
- }
-
- protected void setSerializer(CatalogXmlSerializer serializer) {
- this.serializer = serializer;
- }
-
- /**
- * Parses an instance of CatalogLibrariesDto from the given List. Expects the list entries
- * to be either Strings or Maps of String -> String. Will skip items that are not.
- */
- public static Collection<CatalogBundle> parseLibraries(Collection<?> possibleLibraries) {
- Collection<CatalogBundle> dto = MutableList.of();
- for (Object object : possibleLibraries) {
- if (object instanceof Map) {
- Map<?, ?> entry = (Map<?, ?>) object;
- String name = stringValOrNull(entry, "name");
- String version = stringValOrNull(entry, "version");
- String url = stringValOrNull(entry, "url");
- dto.add(new CatalogBundleDto(name, version, url));
- } else if (object instanceof String) {
- String inlineRef = (String) object;
-
- final String name;
- final String version;
- final String url;
-
- //Infer reference type (heuristically)
- if (inlineRef.contains("/") || inlineRef.contains("\\")) {
- //looks like an url/file path
- name = null;
- version = null;
- url = inlineRef;
- } else if (CatalogUtils.looksLikeVersionedId(inlineRef)) {
- //looks like a name+version ref
- name = CatalogUtils.getIdFromVersionedId(inlineRef);
- version = CatalogUtils.getVersionFromVersionedId(inlineRef);
- url = null;
- } else {
- //assume it to be relative url
- name = null;
- version = null;
- url = inlineRef;
- }
-
- dto.add(new CatalogBundleDto(name, version, url));
- } else {
- LOG.debug("Unexpected entry in libraries list neither string nor map: " + object);
- }
- }
- return dto;
- }
-
- private static String stringValOrNull(Map<?, ?> map, String key) {
- Object val = map.get(key);
- return val != null ? String.valueOf(val) : null;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
deleted file mode 100644
index 2adc851..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDo.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.Collection;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-
-import com.google.common.base.Preconditions;
-
-@Deprecated
-public class CatalogLibrariesDo implements CatalogItem.CatalogItemLibraries {
-
- private final CatalogLibrariesDto librariesDto;
-
-
- public CatalogLibrariesDo(CatalogLibrariesDto librariesDto) {
- this.librariesDto = Preconditions.checkNotNull(librariesDto, "librariesDto");
- }
-
- @Override
- public Collection<String> getBundles() {
- return librariesDto.getBundles();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
deleted file mode 100644
index 47dcdd5..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLibrariesDto.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-
-import com.google.common.collect.ImmutableList;
-
-@Deprecated
-public class CatalogLibrariesDto implements CatalogItem.CatalogItemLibraries {
-
- private final Collection<String> bundles;
-
- public CatalogLibrariesDto() {
- this.bundles = Collections.emptyList();
- }
-
- public CatalogLibrariesDto(Collection<String> bundles) {
- this.bundles = bundles;
- }
-
- /**
- * @return An immutable copy of the bundle URLs referenced by this object
- */
- @Override
- public Collection<String> getBundles() {
- if (bundles == null) {
- // can be null on deserialization
- return Collections.emptyList();
- }
- return ImmutableList.copyOf(bundles);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogLocationItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogLocationItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogLocationItemDto.java
deleted file mode 100644
index da185f2..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogLocationItemDto.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationSpec;
-
-
-public class CatalogLocationItemDto extends CatalogItemDtoAbstract<Location,LocationSpec<?>> {
-
- @Override
- public CatalogItemType getCatalogItemType() {
- return CatalogItemType.LOCATION;
- }
-
- @Override
- public Class<Location> getCatalogItemJavaType() {
- return Location.class;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Class<LocationSpec<?>> getSpecType() {
- return (Class)LocationSpec.class;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
deleted file mode 100644
index 0475876..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogPolicyItemDto.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.api.policy.PolicySpec;
-
-
-public class CatalogPolicyItemDto extends CatalogItemDtoAbstract<Policy,PolicySpec<?>> {
-
- @Override
- public CatalogItemType getCatalogItemType() {
- return CatalogItemType.POLICY;
- }
-
- @Override
- public Class<Policy> getCatalogItemJavaType() {
- return Policy.class;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Class<PolicySpec<?>> getSpecType() {
- return (Class)PolicySpec.class;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java b/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
deleted file mode 100644
index 1003a4c..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogTemplateItemDto.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-
-public class CatalogTemplateItemDto extends CatalogItemDtoAbstract<Application,EntitySpec<? extends Application>> {
-
- @Override
- public CatalogItemType getCatalogItemType() {
- return CatalogItemType.TEMPLATE;
- }
-
- @Override
- public Class<Application> getCatalogItemJavaType() {
- return Application.class;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Class<EntitySpec<? extends Application>> getSpecType() {
- return (Class)EntitySpec.class;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
deleted file mode 100644
index 302e17c..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.Collection;
-
-import javax.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.basic.BrooklynObjectInternal;
-
-import org.apache.brooklyn.api.basic.BrooklynObject;
-import org.apache.brooklyn.api.catalog.BrooklynCatalog;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.core.management.classloading.BrooklynClassLoadingContextSequential;
-import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
-import org.apache.brooklyn.core.management.classloading.OsgiBrooklynClassLoadingContext;
-import org.apache.brooklyn.core.management.ha.OsgiManager;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-
-import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
-import brooklyn.config.BrooklynLogging;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Joiner;
-import com.google.common.base.Stopwatch;
-
-public class CatalogUtils {
- private static final Logger log = LoggerFactory.getLogger(CatalogUtils.class);
-
- public static final char VERSION_DELIMITER = ':';
-
- public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, CatalogItem<?, ?> item) {
- // TODO getLibraries() should never be null but sometimes it is still
- // e.g. run CatalogResourceTest without the above check
- if (item.getLibraries() == null) {
- log.debug("CatalogItemDtoAbstract.getLibraries() is null.", new Exception("Trace for null CatalogItemDtoAbstract.getLibraries()"));
- }
- return newClassLoadingContext(mgmt, item.getId(), item.getLibraries());
- }
-
- public static BrooklynClassLoadingContext getClassLoadingContext(Entity entity) {
- ManagementContext mgmt = ((EntityInternal)entity).getManagementContext();
- String catId = entity.getCatalogItemId();
- if (Strings.isBlank(catId)) return JavaBrooklynClassLoadingContext.create(mgmt);
- CatalogItem<?, ?> cat = getCatalogItemOptionalVersion(mgmt, catId);
- if (cat==null) {
- log.warn("Cannot load "+catId+" to get classloader for "+entity+"; will try with standard loader, but might fail subsequently");
- return JavaBrooklynClassLoadingContext.create(mgmt);
- }
- return newClassLoadingContext(mgmt, cat);
- }
-
- public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<CatalogBundle> libraries) {
- BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
-
- if (libraries!=null && !libraries.isEmpty()) {
- result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, libraries));
- }
-
- BrooklynClassLoadingContext loader = BrooklynLoaderTracker.getLoader();
- if (loader != null) {
- result.add(loader);
- }
-
- result.addSecondary(JavaBrooklynClassLoadingContext.create(mgmt));
- return result;
- }
-
- /**
- * @deprecated since 0.7.0 only for legacy catalog items which provide a non-osgi loader; see {@link #newDefault(ManagementContext)}
- */ @Deprecated
- public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<CatalogBundle> libraries, ClassLoader customClassLoader) {
- BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
-
- if (libraries!=null && !libraries.isEmpty()) {
- result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, libraries));
- }
-
- BrooklynClassLoadingContext loader = BrooklynLoaderTracker.getLoader();
- if (loader != null) {
- result.add(loader);
- }
-
- result.addSecondary(JavaBrooklynClassLoadingContext.create(mgmt, customClassLoader));
- return result;
- }
-
- /**
- * Registers all bundles with the management context's OSGi framework.
- */
- public static void installLibraries(ManagementContext managementContext, @Nullable Collection<CatalogBundle> libraries) {
- if (libraries == null) return;
-
- ManagementContextInternal mgmt = (ManagementContextInternal) managementContext;
- if (!libraries.isEmpty()) {
- Maybe<OsgiManager> osgi = mgmt.getOsgiManager();
- if (osgi.isAbsent()) {
- throw new IllegalStateException("Unable to load bundles "+libraries+" because OSGi is not running.");
- }
- if (log.isDebugEnabled())
- logDebugOrTraceIfRebinding(log,
- "Loading bundles in {}: {}",
- new Object[] {managementContext, Joiner.on(", ").join(libraries)});
- Stopwatch timer = Stopwatch.createStarted();
- for (CatalogBundle bundleUrl : libraries) {
- osgi.get().registerBundle(bundleUrl);
- }
- if (log.isDebugEnabled())
- logDebugOrTraceIfRebinding(log,
- "Registered {} bundles in {}",
- new Object[]{libraries.size(), Time.makeTimeStringRounded(timer)});
- }
- }
-
- /** Scans the given {@link BrooklynClassLoadingContext} to detect what catalog item id is in effect. */
- public static String getCatalogItemIdFromLoader(BrooklynClassLoadingContext loader) {
- if (loader instanceof OsgiBrooklynClassLoadingContext) {
- return ((OsgiBrooklynClassLoadingContext)loader).getCatalogItemId();
- } else {
- return null;
- }
- }
-
- public static void setCatalogItemIdOnAddition(Entity entity, BrooklynObject itemBeingAdded) {
- if (entity.getCatalogItemId()!=null) {
- if (itemBeingAdded.getCatalogItemId()==null) {
- if (log.isDebugEnabled())
- BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(entity),
- "Catalog item addition: "+entity+" from "+entity.getCatalogItemId()+" applying its catalog item ID to "+itemBeingAdded);
- ((BrooklynObjectInternal)itemBeingAdded).setCatalogItemId(entity.getCatalogItemId());
- } else {
- if (!itemBeingAdded.getCatalogItemId().equals(entity.getCatalogItemId())) {
- // not a problem, but something to watch out for
- log.debug("Cross-catalog item detected: "+entity+" from "+entity.getCatalogItemId()+" has "+itemBeingAdded+" from "+itemBeingAdded.getCatalogItemId());
- }
- }
- } else if (itemBeingAdded.getCatalogItemId()!=null) {
- if (log.isDebugEnabled())
- BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(entity),
- "Catalog item addition: "+entity+" without catalog item ID has "+itemBeingAdded+" from "+itemBeingAdded.getCatalogItemId());
- }
- }
-
- @Beta
- public static void logDebugOrTraceIfRebinding(Logger log, String message, Object ...args) {
- if (RebindTracker.isRebinding())
- log.trace(message, args);
- else
- log.debug(message, args);
- }
-
- public static boolean looksLikeVersionedId(String versionedId) {
- if (versionedId==null) return false;
- int fi = versionedId.indexOf(VERSION_DELIMITER);
- if (fi<0) return false;
- int li = versionedId.lastIndexOf(VERSION_DELIMITER);
- if (li!=fi) {
- // if multiple colons, we say it isn't a versioned reference; the prefix in that case must understand any embedded versioning scheme
- // this fixes the case of: http://localhost:8080
- return false;
- }
- String candidateVersion = versionedId.substring(li+1);
- if (!candidateVersion.matches("[0-9]+(|(\\.|_).*)")) {
- // version must start with a number, followed if by anything with full stop or underscore before any other characters
- // e.g. foo:1 or foo:1.1 or foo:1_SNAPSHOT all supported, but not e.g. foo:bar (or chef:cookbook or docker:my/image)
- return false;
- }
- return true;
- }
-
- public static String getIdFromVersionedId(String versionedId) {
- if (versionedId == null) return null;
- int versionDelimiterPos = versionedId.lastIndexOf(VERSION_DELIMITER);
- if (versionDelimiterPos != -1) {
- return versionedId.substring(0, versionDelimiterPos);
- } else {
- return null;
- }
- }
-
- public static String getVersionFromVersionedId(String versionedId) {
- if (versionedId == null) return null;
- int versionDelimiterPos = versionedId.lastIndexOf(VERSION_DELIMITER);
- if (versionDelimiterPos != -1) {
- return versionedId.substring(versionDelimiterPos+1);
- } else {
- return null;
- }
- }
-
- public static String getVersionedId(String id, String version) {
- // TODO null checks
- return id + VERSION_DELIMITER + version;
- }
-
- //TODO Don't really like this, but it's better to have it here than on the interface to keep the API's
- //surface minimal. Could instead have the interface methods accept VerionedId object and have the helpers
- //construct it as needed.
- public static CatalogItem<?, ?> getCatalogItemOptionalVersion(ManagementContext mgmt, String versionedId) {
- if (versionedId == null) return null;
- if (looksLikeVersionedId(versionedId)) {
- String id = getIdFromVersionedId(versionedId);
- String version = getVersionFromVersionedId(versionedId);
- return mgmt.getCatalog().getCatalogItem(id, version);
- } else {
- return mgmt.getCatalog().getCatalogItem(versionedId, BrooklynCatalog.DEFAULT_VERSION);
- }
- }
-
- public static boolean isBestVersion(ManagementContext mgmt, CatalogItem<?,?> item) {
- CatalogItem<?, ?> bestVersion = getCatalogItemOptionalVersion(mgmt, item.getSymbolicName());
- if (bestVersion==null) return false;
- return (bestVersion.getVersion().equals(item.getVersion()));
- }
-
- public static <T,SpecT> CatalogItem<T, SpecT> getCatalogItemOptionalVersion(ManagementContext mgmt, Class<T> type, String versionedId) {
- if (looksLikeVersionedId(versionedId)) {
- String id = getIdFromVersionedId(versionedId);
- String version = getVersionFromVersionedId(versionedId);
- return mgmt.getCatalog().getCatalogItem(type, id, version);
- } else {
- return mgmt.getCatalog().getCatalogItem(type, versionedId, BrooklynCatalog.DEFAULT_VERSION);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java b/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
deleted file mode 100644
index dbfd3fc..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogXmlSerializer.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.basic.AbstractBrooklynObject;
-import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-import brooklyn.util.xstream.EnumCaseForgivingSingleValueConverter;
-import brooklyn.util.xstream.XmlSerializer;
-
-public class CatalogXmlSerializer extends XmlSerializer<Object> {
-
- @SuppressWarnings("deprecation")
- public CatalogXmlSerializer() {
- xstream.addDefaultImplementation(ArrayList.class, Collection.class);
-
- xstream.aliasType("list", List.class);
- xstream.aliasType("map", Map.class);
-
- xstream.useAttributeFor("id", String.class);
-
- xstream.aliasType("catalog", CatalogDto.class);
- xstream.useAttributeFor(CatalogDto.class, "url");
- xstream.addImplicitCollection(CatalogDto.class, "catalogs", CatalogDto.class);
- xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogTemplateItemDto.class);
- xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogEntityItemDto.class);
- xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogPolicyItemDto.class);
- xstream.addImplicitCollection(CatalogDto.class, "entries", CatalogLocationItemDto.class);
-
- xstream.aliasType("template", CatalogTemplateItemDto.class);
- xstream.aliasType("entity", CatalogEntityItemDto.class);
- xstream.aliasType("policy", CatalogPolicyItemDto.class);
- xstream.aliasType("location", CatalogPolicyItemDto.class);
-
- xstream.aliasField("registeredType", CatalogItemDtoAbstract.class, "symbolicName");
- xstream.aliasAttribute(CatalogItemDtoAbstract.class, "displayName", "name");
- xstream.useAttributeFor(CatalogItemDtoAbstract.class, "type");
- xstream.useAttributeFor(CatalogItemDtoAbstract.class, "version");
- xstream.aliasType("bundle", CatalogBundleDto.class);
- xstream.registerConverter(new CatalogBundleConverter(xstream.getMapper(), xstream.getReflectionProvider()));
-
- xstream.useAttributeFor(CatalogClasspathDto.class, "scan");
- xstream.addImplicitCollection(CatalogClasspathDto.class, "entries", "entry", String.class);
- xstream.registerConverter(new EnumCaseForgivingSingleValueConverter(CatalogScanningModes.class));
-
- // Note: the management context is being omitted because it is unnecessary for
- // representations of catalogues generated with this serializer.
- xstream.omitField(AbstractBrooklynObject.class, "managementContext");
- xstream.omitField(AbstractBrooklynObject.class, "_legacyConstruction");
- xstream.omitField(AbstractBrooklynObject.class, "hasWarnedOfNoManagementContextWhenPersistRequested");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/config/BrooklynServerConfig.java b/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
index 2eae73e..e884bdd 100644
--- a/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
+++ b/core/src/main/java/brooklyn/config/BrooklynServerConfig.java
@@ -26,10 +26,10 @@ import java.net.URI;
import java.util.Map;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.catalog.internal.CatalogInitialization;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.util.guava.Maybe;
import brooklyn.util.os.Os;
@@ -103,7 +103,7 @@ public class BrooklynServerConfig {
/** @deprecated since 0.7.0 replaced by {@link CatalogInitialization}; also note, default removed
* (it was overridden anyway, and in almost all cases the new behaviour is still the default behaviour) */
@Deprecated
- public static final ConfigKey<brooklyn.catalog.CatalogLoadMode> CATALOG_LOAD_MODE = ConfigKeys.newConfigKey(brooklyn.catalog.CatalogLoadMode.class,
+ public static final ConfigKey<org.apache.brooklyn.core.catalog.CatalogLoadMode> CATALOG_LOAD_MODE = ConfigKeys.newConfigKey(org.apache.brooklyn.core.catalog.CatalogLoadMode.class,
"brooklyn.catalog.mode",
"The mode the management context should use to load the catalog when first starting");
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index 2860b82..1d21a7e 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -53,6 +53,7 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.EntityAdjunct;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.apache.brooklyn.core.management.internal.EffectorUtils;
@@ -64,7 +65,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.basic.AbstractBrooklynObject;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.BrooklynLogging;
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
index 0d4d92c..52e87a6 100644
--- a/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/BasicCatalogItemRebindSupport.java
@@ -20,10 +20,10 @@ package brooklyn.entity.rebind;
import org.apache.brooklyn.api.entity.rebind.RebindContext;
import org.apache.brooklyn.api.mementos.CatalogItemMemento;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.catalog.internal.CatalogItemDtoAbstract;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.flags.FlagUtils;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java b/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
index 81b1321..e132a51 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindContextLookupContext.java
@@ -34,8 +34,7 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister.LookupContext;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
-
-import brooklyn.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
/** Looks in {@link RebindContext} <i>and</i> {@link ManagementContext} to find entities, locations, etc. */
public class RebindContextLookupContext implements LookupContext {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 8c6a402..1164fff 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -64,6 +64,8 @@ import org.apache.brooklyn.api.mementos.TreeNode;
import org.apache.brooklyn.api.mementos.BrooklynMementoManifest.EntityMementoManifest;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.BrooklynObjectManagementMode;
import org.apache.brooklyn.core.management.internal.BrooklynObjectManagerInternal;
@@ -72,8 +74,6 @@ import org.apache.brooklyn.core.management.internal.LocationManagerInternal;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.core.management.internal.ManagementTransitionMode;
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.BrooklynLogging;
import brooklyn.config.BrooklynLogging.LoggingLevel;
import brooklyn.enricher.basic.AbstractEnricher;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java
index b2a3068..e46a6af 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BasicCatalogItemMemento.java
@@ -26,9 +26,8 @@ import java.util.Map;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.mementos.CatalogItemMemento;
-
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
index 3525d84..dbe6e26 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
@@ -49,8 +49,8 @@ import org.apache.brooklyn.api.mementos.PolicyMemento;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EntityAdjunct;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemDo;
-import brooklyn.catalog.internal.CatalogItemDo;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.entity.basic.EntityDynamicType;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index be51b44..b5ca9c1 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -48,9 +48,9 @@ import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
import org.apache.brooklyn.api.mementos.CatalogItemMemento;
import org.apache.brooklyn.api.mementos.Memento;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.ConfigKey;
import brooklyn.config.StringConfigMap;
import brooklyn.entity.basic.ConfigKeys;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/rebind/persister/CatalogItemLibrariesConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/CatalogItemLibrariesConverter.java b/core/src/main/java/brooklyn/entity/rebind/persister/CatalogItemLibrariesConverter.java
index 7a7481c..4cf6310 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/CatalogItemLibrariesConverter.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/CatalogItemLibrariesConverter.java
@@ -23,8 +23,7 @@ import java.util.Collection;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemLibraries;
-
-import brooklyn.catalog.internal.CatalogBundleDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogBundleDto;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
index fe5a677..99ee2e5 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/XmlMementoSerializer.java
@@ -42,12 +42,12 @@ import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingConte
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister.LookupContext;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.catalog.internal.CatalogBundleDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.classloading.BrooklynClassLoadingContextSequential;
import org.apache.brooklyn.core.management.classloading.ClassLoaderFromBrooklynClassLoadingContext;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
-import brooklyn.catalog.internal.CatalogBundleDto;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.BasicParameterType;
import brooklyn.entity.effector.EffectorAndBody;
import brooklyn.entity.effector.EffectorTasks.EffectorBodyTaskFactory;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/util/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/ResourceUtils.java b/core/src/main/java/brooklyn/util/ResourceUtils.java
index 9b23b7a..338b223 100644
--- a/core/src/main/java/brooklyn/util/ResourceUtils.java
+++ b/core/src/main/java/brooklyn/util/ResourceUtils.java
@@ -40,6 +40,8 @@ import java.util.regex.Pattern;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.apache.http.HttpEntity;
@@ -51,10 +53,6 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
-import brooklyn.catalog.internal.CatalogUtils;
-
import org.apache.brooklyn.location.basic.SshMachineLocation;
import brooklyn.util.collections.MutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/CatalogLoadMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/CatalogLoadMode.java b/core/src/main/java/org/apache/brooklyn/core/catalog/CatalogLoadMode.java
new file mode 100644
index 0000000..8e9d6d5
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/CatalogLoadMode.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog;
+
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.rebind.persister.PersistMode;
+
+/** @deprecated since 0.7.0 replaced by {@link CatalogInitialization} */
+@Deprecated
+public enum CatalogLoadMode {
+ /**
+ * The server will load its initial catalog from the URL configured in
+ * {@link brooklyn.config.BrooklynServerConfig#BROOKLYN_CATALOG_URL} and will
+ * disregard existing persisted state.
+ */
+ LOAD_BROOKLYN_CATALOG_URL,
+
+ /**
+ * The server will load its initial catalog from previously persisted state,
+ * and will behave as {@link #LOAD_BROOKLYN_CATALOG_URL} if no state exists.
+ */
+ LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE,
+
+ /**
+ * The server will load its initial catalog from previously persisted state.
+ * The catalog will be empty if no previous state exists.
+ */
+ LOAD_PERSISTED_STATE;
+
+ /**
+ * @return A catalog load mode suitable for the given persistence mode:
+ * <ul>
+ * <li>disabled: {@link #LOAD_BROOKLYN_CATALOG_URL}</li>
+ * <li>rebind: {@link #LOAD_PERSISTED_STATE}</li>
+ * <li>auto or clean: {@link #LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE}</li>
+ * </ul>
+ */
+ public static CatalogLoadMode forPersistMode(PersistMode m) {
+ // Clean case relies on the persistence directory being cleaned and rebind manager
+ // believing the store to be empty.
+ switch (m) {
+ case DISABLED:
+ return LOAD_BROOKLYN_CATALOG_URL;
+ case AUTO:
+ case CLEAN:
+ return LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE;
+ case REBIND:
+ return LOAD_PERSISTED_STATE;
+ default:
+ LoggerFactory.getLogger(CatalogLoadMode.class)
+ .warn("Unhandled persistence mode {}. Catalog defaulting to {}", m.name(), LOAD_BROOKLYN_CATALOG_URL.name());
+ return LOAD_BROOKLYN_CATALOG_URL;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/CatalogPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/CatalogPredicates.java b/core/src/main/java/org/apache/brooklyn/core/catalog/CatalogPredicates.java
new file mode 100644
index 0000000..654fe56
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/CatalogPredicates.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+
+public class CatalogPredicates {
+
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> isCatalogItemType(final CatalogItemType ciType) {
+ return new Predicate<CatalogItem<T,SpecT>>() {
+ @Override
+ public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+ return (item != null) && item.getCatalogItemType()==ciType;
+ }
+ };
+ }
+
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> deprecated(final boolean deprecated) {
+ return new Predicate<CatalogItem<T,SpecT>>() {
+ @Override
+ public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+ return (item != null) && item.isDeprecated() == deprecated;
+ }
+ };
+ }
+
+ public static final Predicate<CatalogItem<Application,EntitySpec<? extends Application>>> IS_TEMPLATE =
+ CatalogPredicates.<Application,EntitySpec<? extends Application>>isCatalogItemType(CatalogItemType.TEMPLATE);
+ public static final Predicate<CatalogItem<Entity,EntitySpec<?>>> IS_ENTITY =
+ CatalogPredicates.<Entity,EntitySpec<?>>isCatalogItemType(CatalogItemType.ENTITY);
+ public static final Predicate<CatalogItem<Policy,PolicySpec<?>>> IS_POLICY =
+ CatalogPredicates.<Policy,PolicySpec<?>>isCatalogItemType(CatalogItemType.POLICY);
+ public static final Predicate<CatalogItem<Location,LocationSpec<?>>> IS_LOCATION =
+ CatalogPredicates.<Location,LocationSpec<?>>isCatalogItemType(CatalogItemType.LOCATION);
+
+ public static final Function<CatalogItem<?,?>,String> ID_OF_ITEM_TRANSFORMER = new Function<CatalogItem<?,?>, String>() {
+ @Override @Nullable
+ public String apply(@Nullable CatalogItem<?,?> input) {
+ if (input==null) return null;
+ return input.getId();
+ }
+ };
+
+ /** @deprecated since 0.7.0 use {@link #displayName(Predicate)} */
+ @Deprecated
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> name(final Predicate<? super String> filter) {
+ return displayName(filter);
+ }
+
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> displayName(final Predicate<? super String> filter) {
+ return new Predicate<CatalogItem<T,SpecT>>() {
+ @Override
+ public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+ return (item != null) && filter.apply(item.getDisplayName());
+ }
+ };
+ }
+
+ @Deprecated
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> registeredTypeName(final Predicate<? super String> filter) {
+ return symbolicName(filter);
+ }
+
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> symbolicName(final Predicate<? super String> filter) {
+ return new Predicate<CatalogItem<T,SpecT>>() {
+ @Override
+ public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+ return (item != null) && filter.apply(item.getSymbolicName());
+ }
+ };
+ }
+
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> javaType(final Predicate<? super String> filter) {
+ return new Predicate<CatalogItem<T,SpecT>>() {
+ @Override
+ public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+ return (item != null) && filter.apply(item.getJavaType());
+ }
+ };
+ }
+
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> xml(final Predicate<? super String> filter) {
+ return new Predicate<CatalogItem<T,SpecT>>() {
+ @Override
+ public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+ return (item != null) && filter.apply(item.toXmlString());
+ }
+ };
+ }
+
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> entitledToSee(final ManagementContext mgmt) {
+ return new Predicate<CatalogItem<T,SpecT>>() {
+ @Override
+ public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+ return (item != null) &&
+ Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, item.getCatalogItemId());
+ }
+ };
+ }
+
+ public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> isBestVersion(final ManagementContext mgmt) {
+ return new Predicate<CatalogItem<T,SpecT>>() {
+ @Override
+ public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
+ return CatalogUtils.isBestVersion(mgmt, item);
+ }
+ };
+ }
+
+}
\ No newline at end of file
[21/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
deleted file mode 100644
index fd98ed2..0000000
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import java.io.File;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.launch.Framework;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.BrooklynVersion;
-
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-import org.apache.brooklyn.api.management.ManagementContext;
-
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.config.BrooklynServerPaths;
-import brooklyn.config.ConfigKey;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.os.Os;
-import brooklyn.util.os.Os.DeletionResult;
-import brooklyn.util.osgi.Osgis;
-import brooklyn.util.osgi.Osgis.BundleFinder;
-import brooklyn.util.repeat.Repeater;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
-public class OsgiManager {
-
- private static final Logger log = LoggerFactory.getLogger(OsgiManager.class);
-
- public static final ConfigKey<Boolean> USE_OSGI = BrooklynServerConfig.USE_OSGI;
-
- /* see Osgis for info on starting framework etc */
-
- protected ManagementContext mgmt;
- protected Framework framework;
- protected File osgiCacheDir;
-
- public OsgiManager(ManagementContext mgmt) {
- this.mgmt = mgmt;
- }
-
- public void start() {
- try {
- osgiCacheDir = BrooklynServerPaths.getOsgiCacheDirCleanedIfNeeded(mgmt);
-
- // any extra OSGi startup args could go here
- framework = Osgis.newFrameworkStarted(osgiCacheDir.getAbsolutePath(), false, MutableMap.of());
-
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- public void stop() {
- try {
- if (framework!=null) {
- framework.stop();
- framework.waitForStop(0); // 0 means indefinite
- }
- } catch (BundleException e) {
- throw Exceptions.propagate(e);
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- if (BrooklynServerPaths.isOsgiCacheForCleaning(mgmt, osgiCacheDir)) {
- // See exception reported in https://issues.apache.org/jira/browse/BROOKLYN-72
- // We almost always fail to delete he OSGi temp directory due to a concurrent modification.
- // Therefore keep trying.
- final AtomicReference<DeletionResult> deletionResult = new AtomicReference<DeletionResult>();
- Repeater.create("Delete OSGi cache dir")
- .until(new Callable<Boolean>() {
- public Boolean call() {
- deletionResult.set(Os.deleteRecursively(osgiCacheDir));
- return deletionResult.get().wasSuccessful();
- }})
- .limitTimeTo(Duration.ONE_SECOND)
- .backoffTo(Duration.millis(50))
- .run();
- if (deletionResult.get().getThrowable()!=null) {
- log.debug("Unable to delete "+osgiCacheDir+" (possibly being modified concurrently?): "+deletionResult.get().getThrowable());
- }
- }
- osgiCacheDir = null;
- framework = null;
- }
-
- public synchronized void registerBundle(CatalogBundle bundle) {
- try {
- if (checkBundleInstalledThrowIfInconsistent(bundle)) {
- return;
- }
-
- Bundle b = Osgis.install(framework, bundle.getUrl());
-
- checkCorrectlyInstalled(bundle, b);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- throw new IllegalStateException("Bundle from "+bundle.getUrl()+" failed to install: " + e.getMessage(), e);
- }
- }
-
- private void checkCorrectlyInstalled(CatalogBundle bundle, Bundle b) {
- String nv = b.getSymbolicName()+":"+b.getVersion().toString();
-
- if (!isBundleNameEqualOrAbsent(bundle, b)) {
- throw new IllegalStateException("Bundle already installed as "+nv+" but user explicitly requested "+bundle);
- }
-
- List<Bundle> matches = Osgis.bundleFinder(framework)
- .symbolicName(b.getSymbolicName())
- .version(b.getVersion().toString())
- .findAll();
- if (matches.isEmpty()) {
- log.error("OSGi could not find bundle "+nv+" in search after installing it from "+bundle.getUrl());
- } else if (matches.size()==1) {
- log.debug("Bundle from "+bundle.getUrl()+" successfully installed as " + nv + " ("+b+")");
- } else {
- log.warn("OSGi has multiple bundles matching "+nv+", when just installed from "+bundle.getUrl()+": "+matches+"; "
- + "brooklyn will prefer the URL-based bundle for top-level references but any dependencies or "
- + "import-packages will be at the mercy of OSGi. "
- + "It is recommended to use distinct versions for different bundles, and the same URL for the same bundles.");
- }
- }
-
- private boolean checkBundleInstalledThrowIfInconsistent(CatalogBundle bundle) {
- String bundleUrl = bundle.getUrl();
- if (bundleUrl != null) {
- Maybe<Bundle> installedBundle = Osgis.bundleFinder(framework).requiringFromUrl(bundleUrl).find();
- if (installedBundle.isPresent()) {
- Bundle b = installedBundle.get();
- String nv = b.getSymbolicName()+":"+b.getVersion().toString();
- if (!isBundleNameEqualOrAbsent(bundle, b)) {
- throw new IllegalStateException("User requested bundle " + bundle + " but already installed as "+nv);
- } else {
- log.trace("Bundle from "+bundleUrl+" already installed as "+nv+"; not re-registering");
- }
- return true;
- }
- } else {
- Maybe<Bundle> installedBundle = Osgis.bundleFinder(framework).symbolicName(bundle.getSymbolicName()).version(bundle.getVersion()).find();
- if (installedBundle.isPresent()) {
- log.trace("Bundle "+bundle+" installed from "+installedBundle.get().getLocation());
- } else {
- throw new IllegalStateException("Bundle "+bundle+" not previously registered, but URL is empty.");
- }
- return true;
- }
- return false;
- }
-
- public static boolean isBundleNameEqualOrAbsent(CatalogBundle bundle, Bundle b) {
- return !bundle.isNamed() ||
- (bundle.getSymbolicName().equals(b.getSymbolicName()) &&
- bundle.getVersion().equals(b.getVersion().toString()));
- }
-
- public <T> Maybe<Class<T>> tryResolveClass(String type, CatalogBundle... catalogBundles) {
- return tryResolveClass(type, Arrays.asList(catalogBundles));
- }
- public <T> Maybe<Class<T>> tryResolveClass(String type, Iterable<CatalogBundle> catalogBundles) {
- Map<CatalogBundle,Throwable> bundleProblems = MutableMap.of();
- Set<String> extraMessages = MutableSet.of();
- for (CatalogBundle catalogBundle: catalogBundles) {
- try {
- Maybe<Bundle> bundle = findBundle(catalogBundle);
- if (bundle.isPresent()) {
- Bundle b = bundle.get();
- Class<T> clazz;
- //Extension bundles don't support loadClass.
- //Instead load from the app classpath.
- if (Osgis.isExtensionBundle(b)) {
- @SuppressWarnings("unchecked")
- Class<T> c = (Class<T>)Class.forName(type);
- clazz = c;
- } else {
- @SuppressWarnings("unchecked")
- Class<T> c = (Class<T>)b.loadClass(type);
- clazz = c;
- }
- return Maybe.of(clazz);
- } else {
- bundleProblems.put(catalogBundle, ((Maybe.Absent<?>)bundle).getException());
- }
-
- } catch (Exception e) {
- // should come from classloading now; name formatting or missing bundle errors will be caught above
- Exceptions.propagateIfFatal(e);
- bundleProblems.put(catalogBundle, e);
-
- Throwable cause = e.getCause();
- if (cause != null && cause.getMessage().contains("Unresolved constraint in bundle")) {
- if (BrooklynVersion.INSTANCE.getVersionFromOsgiManifest()==null) {
- extraMessages.add("No brooklyn-core OSGi manifest available. OSGi will not work.");
- }
- if (BrooklynVersion.isDevelopmentEnvironment()) {
- extraMessages.add("Your development environment may not have created necessary files. Doing a maven build then retrying may fix the issue.");
- }
- if (!extraMessages.isEmpty()) log.warn(Strings.join(extraMessages, " "));
- log.warn("Unresolved constraint resolving OSGi bundle "+catalogBundle+" to load "+type+": "+cause.getMessage());
- if (log.isDebugEnabled()) log.debug("Trace for OSGi resolution failure", e);
- }
- }
- }
- if (bundleProblems.size()==1) {
- Throwable error = Iterables.getOnlyElement(bundleProblems.values());
- if (error instanceof ClassNotFoundException && error.getCause()!=null && error.getCause().getMessage()!=null) {
- error = Exceptions.collapseIncludingAllCausalMessages(error);
- }
- return Maybe.absent("Unable to resolve class "+type+" in "+Iterables.getOnlyElement(bundleProblems.keySet())
- + (extraMessages.isEmpty() ? "" : " ("+Strings.join(extraMessages, " ")+")"), error);
- } else {
- return Maybe.absent(Exceptions.create("Unable to resolve class "+type+": "+bundleProblems
- + (extraMessages.isEmpty() ? "" : " ("+Strings.join(extraMessages, " ")+")"), bundleProblems.values()));
- }
- }
-
- public Maybe<Bundle> findBundle(CatalogBundle catalogBundle) {
- //Either fail at install time when the user supplied name:version is different
- //from the one reported from the bundle
- //or
- //Ignore user supplied name:version when URL is supplied to be able to find the
- //bundle even if it's with a different version.
- //
- //For now we just log a warning if there's a version discrepancy at install time,
- //so prefer URL if supplied.
- BundleFinder bundleFinder = Osgis.bundleFinder(framework);
- if (catalogBundle.getUrl() != null) {
- bundleFinder.requiringFromUrl(catalogBundle.getUrl());
- } else {
- bundleFinder.symbolicName(catalogBundle.getSymbolicName()).version(catalogBundle.getVersion());
- }
- return bundleFinder.find();
- }
-
- /**
- * Iterates through catalogBundles until one contains a resource with the given name.
- */
- public URL getResource(String name, Iterable<CatalogBundle> catalogBundles) {
- for (CatalogBundle catalogBundle: catalogBundles) {
- try {
- Maybe<Bundle> bundle = findBundle(catalogBundle);
- if (bundle.isPresent()) {
- URL result = bundle.get().getResource(name);
- if (result!=null) return result;
- }
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- }
- }
- return null;
- }
-
- /**
- * @return An iterable of all resources matching name in catalogBundles.
- */
- public Iterable<URL> getResources(String name, Iterable<CatalogBundle> catalogBundles) {
- List<URL> resources = Lists.newArrayList();
- for (CatalogBundle catalogBundle : catalogBundles) {
- try {
- Maybe<Bundle> bundle = findBundle(catalogBundle);
- if (bundle.isPresent()) {
- Enumeration<URL> result = bundle.get().getResources(name);
- resources.addAll(Collections.list(result));
- }
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- }
- }
- return resources;
- }
-
- public Framework getFramework() {
- return framework;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
deleted file mode 100644
index 5e7f4a6..0000000
--- a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.lang.String.format;
-
-import java.net.URI;
-import java.net.URL;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.api.basic.BrooklynObject;
-import org.apache.brooklyn.api.catalog.BrooklynCatalog;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.Effector;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.drivers.EntityDriverManager;
-import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager;
-import org.apache.brooklyn.api.entity.rebind.RebindManager;
-import org.apache.brooklyn.api.location.LocationRegistry;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.SubscriptionContext;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityManager;
-
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.StringConfigMap;
-import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.drivers.BasicEntityDriverManager;
-import brooklyn.entity.drivers.downloads.BasicDownloadsManager;
-import brooklyn.entity.rebind.RebindManagerImpl;
-import brooklyn.internal.storage.BrooklynStorage;
-import brooklyn.internal.storage.DataGrid;
-import brooklyn.internal.storage.DataGridFactory;
-import brooklyn.internal.storage.impl.BrooklynStorageImpl;
-import brooklyn.internal.storage.impl.inmemory.InMemoryDataGridFactory;
-
-import org.apache.brooklyn.location.basic.BasicLocationRegistry;
-
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.ha.HighAvailabilityManagerImpl;
-import brooklyn.util.GroovyJavaMethods;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.Tasks;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-
-public abstract class AbstractManagementContext implements ManagementContextInternal {
- private static final Logger log = LoggerFactory.getLogger(AbstractManagementContext.class);
-
- private static DataGridFactory loadDataGridFactory(BrooklynProperties properties) {
- String clazzName = properties.getFirst(DataGridFactory.class.getName());
- if(clazzName == null){
- clazzName = InMemoryDataGridFactory.class.getName();
- }
-
- Class<?> clazz;
- try{
- //todo: which classloader should we use?
- clazz = LocalManagementContext.class.getClassLoader().loadClass(clazzName);
- }catch(ClassNotFoundException e){
- throw new IllegalStateException(format("Could not load class [%s]",clazzName),e);
- }
-
- Object instance;
- try {
- instance = clazz.newInstance();
- } catch (InstantiationException e) {
- throw new IllegalStateException(format("Could not instantiate class [%s]",clazzName),e);
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(format("Could not instantiate class [%s]",clazzName),e);
- }
-
- if(!(instance instanceof DataGridFactory)){
- throw new IllegalStateException(format("Class [%s] not an instantiate of class [%s]",clazzName, DataGridFactory.class.getName()));
- }
-
- return (DataGridFactory)instance;
- }
-
- static {
- ResourceUtils.addClassLoaderProvider(new Function<Object, BrooklynClassLoadingContext>() {
- @Override
- public BrooklynClassLoadingContext apply(@Nullable Object input) {
- if (input instanceof EntityInternal) {
- EntityInternal internal = (EntityInternal)input;
- if (internal.getCatalogItemId() != null) {
- CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(internal.getManagementContext(), internal.getCatalogItemId());
- if (item != null) {
- return CatalogUtils.newClassLoadingContext(internal.getManagementContext(), item);
- } else {
- log.error("Can't find catalog item " + internal.getCatalogItemId() +
- " used for instantiating entity " + internal +
- ". Falling back to application classpath.");
- }
- }
- return apply(internal.getManagementSupport());
- }
-
- if (input instanceof EntityManagementSupport)
- return apply(((EntityManagementSupport)input).getManagementContext());
- if (input instanceof ManagementContext)
- return JavaBrooklynClassLoadingContext.create((ManagementContext) input);
- return null;
- }
- });
- }
-
- private final AtomicLong totalEffectorInvocationCount = new AtomicLong();
-
- protected BrooklynProperties configMap;
- protected BasicLocationRegistry locationRegistry;
- protected final BasicBrooklynCatalog catalog;
- protected ClassLoader baseClassLoader;
- protected Iterable<URL> baseClassPathForScanning;
-
- private final RebindManager rebindManager;
- private final HighAvailabilityManager highAvailabilityManager;
-
- protected volatile BrooklynGarbageCollector gc;
-
- private final EntityDriverManager entityDriverManager;
- protected DownloadResolverManager downloadsManager;
-
- protected EntitlementManager entitlementManager;
-
- private final BrooklynStorage storage;
-
- private volatile boolean running = true;
- protected boolean startupComplete = false;
- protected final List<Throwable> errors = Collections.synchronizedList(MutableList.<Throwable>of());
-
- protected Maybe<URI> uri = Maybe.absent();
- protected CatalogInitialization catalogInitialization;
-
- public AbstractManagementContext(BrooklynProperties brooklynProperties){
- this(brooklynProperties, null);
- }
-
- public AbstractManagementContext(BrooklynProperties brooklynProperties, DataGridFactory datagridFactory) {
- this.configMap = brooklynProperties;
- this.entityDriverManager = new BasicEntityDriverManager();
- this.downloadsManager = BasicDownloadsManager.newDefault(configMap);
- if (datagridFactory == null) {
- datagridFactory = loadDataGridFactory(brooklynProperties);
- }
- DataGrid datagrid = datagridFactory.newDataGrid(this);
-
- this.catalog = new BasicBrooklynCatalog(this);
-
- this.storage = new BrooklynStorageImpl(datagrid);
- this.rebindManager = new RebindManagerImpl(this); // TODO leaking "this" reference; yuck
- this.highAvailabilityManager = new HighAvailabilityManagerImpl(this); // TODO leaking "this" reference; yuck
-
- this.entitlementManager = Entitlements.newManager(this, brooklynProperties);
- }
-
- @Override
- public void terminate() {
- highAvailabilityManager.stop();
- running = false;
- rebindManager.stop();
- storage.terminate();
- // Don't unmanage everything; different entities get given their events at different times
- // so can cause problems (e.g. a group finds out that a member is unmanaged, before the
- // group itself has been told that it is unmanaged).
- }
-
- @Override
- public boolean isRunning() {
- return running;
- }
-
- @Override
- public boolean isStartupComplete() {
- return startupComplete;
- }
-
- @Override
- public BrooklynStorage getStorage() {
- return storage;
- }
-
- @Override
- public RebindManager getRebindManager() {
- return rebindManager;
- }
-
- @Override
- public HighAvailabilityManager getHighAvailabilityManager() {
- return highAvailabilityManager;
- }
-
- @Override
- public long getTotalEffectorInvocations() {
- return totalEffectorInvocationCount.get();
- }
-
- @Override
- public ExecutionContext getExecutionContext(Entity e) {
- // BEC is a thin wrapper around EM so fine to create a new one here; but make sure it gets the real entity
- if (e instanceof AbstractEntity) {
- return new BasicExecutionContext(MutableMap.of("tag", BrooklynTaskTags.tagForContextEntity(e)), getExecutionManager());
- } else {
- return ((EntityInternal)e).getManagementSupport().getExecutionContext();
- }
- }
-
- @Override
- public ExecutionContext getServerExecutionContext() {
- // BEC is a thin wrapper around EM so fine to create a new one here
- return new BasicExecutionContext(MutableMap.of("tag", BrooklynTaskTags.BROOKLYN_SERVER_TASK_TAG), getExecutionManager());
- }
-
- @Override
- public SubscriptionContext getSubscriptionContext(Entity e) {
- // BSC is a thin wrapper around SM so fine to create a new one here
- return new BasicSubscriptionContext(getSubscriptionManager(), e);
- }
-
- @Override
- public EntityDriverManager getEntityDriverManager() {
- return entityDriverManager;
- }
-
- @Override
- public DownloadResolverManager getEntityDownloadsManager() {
- return downloadsManager;
- }
-
- @Override
- public EntitlementManager getEntitlementManager() {
- return entitlementManager;
- }
-
- protected abstract void manageIfNecessary(Entity entity, Object context);
-
- @Override
- public <T> Task<T> invokeEffector(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters) {
- return runAtEntity(entity, eff, parameters);
- }
-
- protected <T> T invokeEffectorMethodLocal(Entity entity, Effector<T> eff, Object args) {
- assert isManagedLocally(entity) : "cannot invoke effector method at "+this+" because it is not managed here";
- totalEffectorInvocationCount.incrementAndGet();
- Object[] transformedArgs = EffectorUtils.prepareArgsForEffector(eff, args);
- return GroovyJavaMethods.invokeMethodOnMetaClass(entity, eff.getName(), transformedArgs);
- }
-
- /**
- * Method for entity to make effector happen with correct semantics (right place, right task context),
- * when a method is called on that entity.
- * @throws ExecutionException
- */
- @Override
- public <T> T invokeEffectorMethodSync(final Entity entity, final Effector<T> eff, final Object args) throws ExecutionException {
- try {
- Task<?> current = Tasks.current();
- if (current == null || !entity.equals(BrooklynTaskTags.getContextEntity(current)) || !isManagedLocally(entity)) {
- manageIfNecessary(entity, eff.getName());
- // Wrap in a task if we aren't already in a task that is tagged with this entity
- Task<T> task = runAtEntity( EffectorUtils.getTaskFlagsForEffectorInvocation(entity, eff,
- ConfigBag.newInstance().configureStringKey("args", args)),
- entity,
- new Callable<T>() {
- public T call() {
- return invokeEffectorMethodLocal(entity, eff, args);
- }});
- return task.get();
- } else {
- return invokeEffectorMethodLocal(entity, eff, args);
- }
- } catch (Exception e) {
- // don't need to attach any message or warning because the Effector impl hierarchy does that (see calls to EffectorUtils.handleException)
- throw new ExecutionException(e);
- }
- }
-
- /**
- * Whether the master entity record is local, and sensors and effectors can be properly accessed locally.
- */
- public abstract boolean isManagedLocally(Entity e);
-
- /**
- * Causes the indicated runnable to be run at the right location for the given entity.
- *
- * Returns the actual task (if it is local) or a proxy task (if it is remote);
- * if management for the entity has not yet started this may start it.
- *
- * @deprecated since 0.6.0 use effectors (or support {@code runAtEntity(Entity, Effector, Map)} if something else is needed);
- * (Callable with Map flags is too open-ended, bothersome to support, and not used much)
- */
- @Deprecated
- public abstract <T> Task<T> runAtEntity(@SuppressWarnings("rawtypes") Map flags, Entity entity, Callable<T> c);
-
- /** Runs the given effector in the right place for the given entity.
- * The task is immediately submitted in the background, but also recorded in the queueing context (if present)
- * so it appears as a child, but marked inessential so it does not fail the parent task, who will ordinarily
- * call {@link Task#get()} on the object and may do their own failure handling.
- */
- protected abstract <T> Task<T> runAtEntity(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters);
-
- @Override
- public StringConfigMap getConfig() {
- return configMap;
- }
-
- @Override
- public BrooklynProperties getBrooklynProperties() {
- return configMap;
- }
-
- @Override
- public synchronized LocationRegistry getLocationRegistry() {
- if (locationRegistry==null) locationRegistry = new BasicLocationRegistry(this);
- return locationRegistry;
- }
-
- @Override
- public BrooklynCatalog getCatalog() {
- if (!getCatalogInitialization().hasRunAnyInitialization()) {
- // catalog init is needed; normally this will be done from start sequence,
- // but if accessed early -- and in tests -- we will load it here
- getCatalogInitialization().injectManagementContext(this);
- getCatalogInitialization().populateUnofficial(catalog);
- }
- return catalog;
- }
-
- @Override
- public ClassLoader getCatalogClassLoader() {
- // catalog does not have to be initialized
- return catalog.getRootClassLoader();
- }
-
- /**
- * Optional class-loader that this management context should use as its base,
- * as the first-resort in the catalog, and for scanning (if scanning the default in the catalog).
- * In most instances the default classloader (ManagementContext.class.getClassLoader(), assuming
- * this was in the JARs used at boot time) is fine, and in those cases this method normally returns null.
- * (Surefire does some weird stuff, but the default classloader is fine for loading;
- * however it requires a custom base classpath to be set for scanning.)
- */
- @Override
- public ClassLoader getBaseClassLoader() {
- return baseClassLoader;
- }
-
- /** See {@link #getBaseClassLoader()}. Only settable once and must be invoked before catalog is loaded. */
- public void setBaseClassLoader(ClassLoader cl) {
- if (baseClassLoader==cl) return;
- if (baseClassLoader!=null) throw new IllegalStateException("Cannot change base class loader (in "+this+")");
- if (catalog!=null) throw new IllegalStateException("Cannot set base class after catalog has been loaded (in "+this+")");
- this.baseClassLoader = cl;
- }
-
- /** Optional mechanism for setting the classpath which should be scanned by the catalog, if the catalog
- * is scanning the default classpath. Usually it infers the right thing, but some classloaders
- * (e.g. surefire) do funny things which the underlying org.reflections.Reflections library can't see in to.
- * <p>
- * This should normally be invoked early in the server startup. Setting it after the catalog is loaded will not
- * take effect without an explicit internal call to do so. Once set, it can be changed prior to catalog loading
- * but it cannot be <i>changed</i> once the catalog is loaded.
- * <p>
- * ClasspathHelper.forJavaClassPath() is often a good argument to pass, and is used internally in some places
- * when no items are found on the catalog. */
- @Override
- public void setBaseClassPathForScanning(Iterable<URL> urls) {
- if (Objects.equal(baseClassPathForScanning, urls)) return;
- if (baseClassPathForScanning != null) {
- if (catalog==null)
- log.warn("Changing scan classpath to "+urls+" from "+baseClassPathForScanning);
- else
- throw new IllegalStateException("Cannot change base class path for scanning (in "+this+")");
- }
- this.baseClassPathForScanning = urls;
- }
- /**
- * @see #setBaseClassPathForScanning(Iterable)
- */
- @Override
- public Iterable<URL> getBaseClassPathForScanning() {
- return baseClassPathForScanning;
- }
-
- public BrooklynGarbageCollector getGarbageCollector() {
- return gc;
- }
-
- @Override
- public void setManagementNodeUri(URI uri) {
- this.uri = Maybe.of(checkNotNull(uri, "uri"));
- }
-
- @Override
- public Maybe<URI> getManagementNodeUri() {
- return uri;
- }
-
- private Object catalogInitMutex = new Object();
- @Override
- public CatalogInitialization getCatalogInitialization() {
- synchronized (catalogInitMutex) {
- if (catalogInitialization!=null) return catalogInitialization;
- CatalogInitialization ci = new CatalogInitialization();
- setCatalogInitialization(ci);
- return ci;
- }
- }
-
- @Override
- public void setCatalogInitialization(CatalogInitialization catalogInitialization) {
- synchronized (catalogInitMutex) {
- Preconditions.checkNotNull(catalogInitialization, "initialization must not be null");
- if (this.catalogInitialization!=null && this.catalogInitialization != catalogInitialization)
- throw new IllegalStateException("Changing catalog init from "+this.catalogInitialization+" to "+catalogInitialization+"; changes not permitted");
- catalogInitialization.injectManagementContext(this);
- this.catalogInitialization = catalogInitialization;
- }
- }
-
- public BrooklynObject lookup(String id) {
- return lookup(id, BrooklynObject.class);
- }
-
- @SuppressWarnings("unchecked")
- public <T extends BrooklynObject> T lookup(String id, Class<T> type) {
- Object result;
- result = getEntityManager().getEntity(id);
- if (result!=null && type.isInstance(result)) return (T)result;
-
- result = getLocationManager().getLocation(id);
- if (result!=null && type.isInstance(result)) return (T)result;
-
- // TODO policies, enrichers, feeds
- return null;
- }
-
- @Override
- public List<Throwable> errors() {
- return errors;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/AbstractSubscriptionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AbstractSubscriptionManager.java b/core/src/main/java/brooklyn/management/internal/AbstractSubscriptionManager.java
deleted file mode 100644
index 7e8effc..0000000
--- a/core/src/main/java/brooklyn/management/internal/AbstractSubscriptionManager.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collections;
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.Group;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.api.event.SensorEvent;
-import org.apache.brooklyn.api.event.SensorEventListener;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-import org.apache.brooklyn.api.management.SubscriptionManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-
-public abstract class AbstractSubscriptionManager implements SubscriptionManager {
-
- // TODO Perhaps could use guava's SynchronizedSetMultimap? But need to check its synchronization guarantees.
- // That would replace the utils used for subscriptionsBySubscriber etc.
-
- @SuppressWarnings("unused")
- private static final Logger LOG = LoggerFactory.getLogger(AbstractSubscriptionManager.class);
-
- /** performs the actual subscription; should return the subscription parameter as the handle */
- protected abstract <T> SubscriptionHandle subscribe(Map<String, Object> flags, Subscription<T> s);
- /** performs the actual publishing -- ie distribution to subscriptions */
- public abstract <T> void publish(final SensorEvent<T> event);
-
- public static class EntitySensorToken {
- Entity e;
- Sensor<?> s;
- String sName;
- public EntitySensorToken(Entity e, Sensor<?> s) {
- this.e = e;
- this.s = s;
- this.sName = (s == null) ? null : checkNotNull(s.getName(), "sensor must have non-null name: %s", s);
- }
- @Override
- public int hashCode() {
- return Objects.hashCode(e, sName);
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (!(obj instanceof EntitySensorToken)) return false;
- if (!Objects.equal(e, ((EntitySensorToken)obj).e)) return false;
- if (!Objects.equal(sName, ((EntitySensorToken)obj).sName)) return false;
- return true;
- }
- @Override
- public String toString() {
- return (e != null ? e.getId() : "*")+":"+(s != null ? sName : "*");
- }
- }
- static Object makeEntitySensorToken(Entity e, Sensor<?> s) {
- return new EntitySensorToken(e, s);
- }
- static Object makeEntitySensorToken(SensorEvent<?> se) {
- return makeEntitySensorToken(se.getSource(), se.getSensor());
- }
-
- /** @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener) */
- public final <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- return subscribe(Collections.<String,Object>emptyMap(), producer, sensor, listener);
- }
-
- /**
- * This implementation handles the following flags, in addition to those described in the {@link SubscriptionManager}
- * interface:
- * <ul>
- * <li>subscriberExecutionManagerTag - a tag to pass to execution manager (without setting any execution semantics / TaskPreprocessor);
- * if not supplied and there is a subscriber, this will be inferred from the subscriber and set up with SingleThreadedScheduler
- * <li>eventFilter - a Predicate<SensorEvent> instance to filter what events are delivered
- * </ul>
- *
- * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
- */
- public final <T> SubscriptionHandle subscribe(Map<String, Object> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- return subscribe(flags, new Subscription<T>(producer, sensor, listener));
- }
-
- /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
- public final <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- return subscribeToChildren(Collections.<String,Object>emptyMap(), parent, sensor, listener);
- }
-
- /** @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener) */
- public final <T> SubscriptionHandle subscribeToChildren(Map<String, Object> flags, final Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- Predicate<SensorEvent<T>> eventFilter = new Predicate<SensorEvent<T>>() {
- public boolean apply(SensorEvent<T> input) {
- return parent != null && input.getSource() != null && parent.equals(input.getSource().getParent());
- }
- };
- flags.put("eventFilter", eventFilter);
- return subscribe(flags, null, sensor, listener);
- }
-
- /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
- public final <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- return subscribeToMembers(Collections.<String,Object>emptyMap(), parent, sensor, listener);
- }
-
- /** @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener) */
- public final <T> SubscriptionHandle subscribeToMembers(Map<String, Object> flags, final Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- Predicate<SensorEvent<T>> eventFilter = new Predicate<SensorEvent<T>>() {
- public boolean apply(SensorEvent<T> input) {
- return parent.getMembers().contains(input.getSource());
- }
- };
- flags.put("eventFilter", eventFilter);
- return subscribe(flags, null, sensor, listener);
- }
-
- protected <T> Object getSubscriber(Map<String, Object> flags, Subscription<T> s) {
- return s.subscriber!=null ? s.subscriber : flags.containsKey("subscriber") ? flags.remove("subscriber") : s.listener;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/AccessManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AccessManager.java b/core/src/main/java/brooklyn/management/internal/AccessManager.java
deleted file mode 100644
index baa805a..0000000
--- a/core/src/main/java/brooklyn/management/internal/AccessManager.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import org.apache.brooklyn.api.management.AccessController;
-
-import com.google.common.annotations.Beta;
-
-@Beta
-public interface AccessManager {
-
- AccessController getAccessController();
-
- boolean isLocationProvisioningAllowed();
-
- boolean isLocationManagementAllowed();
-
- boolean isEntityManagementAllowed();
-
- void setLocationProvisioningAllowed(boolean allowed);
-
- void setLocationManagementAllowed(boolean allowed);
-
- void setEntityManagementAllowed(boolean allowed);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/AsyncCollectionChangeAdapter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/AsyncCollectionChangeAdapter.java b/core/src/main/java/brooklyn/management/internal/AsyncCollectionChangeAdapter.java
deleted file mode 100644
index e3e5193..0000000
--- a/core/src/main/java/brooklyn/management/internal/AsyncCollectionChangeAdapter.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.SingleThreadedScheduler;
-
-public class AsyncCollectionChangeAdapter<Item> implements CollectionChangeListener<Item> {
-
- private static final Logger LOG = LoggerFactory.getLogger(AsyncCollectionChangeAdapter.class);
-
- private final ExecutionManager executor;
- private final CollectionChangeListener<Item> delegate;
-
- public AsyncCollectionChangeAdapter(ExecutionManager executor, CollectionChangeListener<Item> delegate) {
- this.executor = checkNotNull(executor, "executor");
- this.delegate = checkNotNull(delegate, "delegate");
- ((BasicExecutionManager) executor).setTaskSchedulerForTag(delegate, SingleThreadedScheduler.class);
- }
-
- @Override
- public void onItemAdded(final Item item) {
- executor.submit(MutableMap.of("tag", delegate), new Runnable() {
- public void run() {
- try {
- delegate.onItemAdded(item);
- } catch (Throwable t) {
- LOG.warn("Error notifying listener of itemAdded("+item+")", t);
- Exceptions.propagate(t);
- }
- }
- });
- }
-
- @Override
- public void onItemRemoved(final Item item) {
- executor.submit(MutableMap.of("tag", delegate), new Runnable() {
- public void run() {
- try {
- delegate.onItemRemoved(item);
- } catch (Throwable t) {
- LOG.warn("Error notifying listener of itemAdded("+item+")", t);
- Exceptions.propagate(t);
- }
- }
- });
- }
-
- @Override
- public int hashCode() {
- return delegate.hashCode();
- }
-
- @Override
- public boolean equals(Object other) {
- return (other instanceof AsyncCollectionChangeAdapter) &&
- delegate.equals(((AsyncCollectionChangeAdapter<?>) other).delegate);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/BasicSubscriptionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/BasicSubscriptionContext.java b/core/src/main/java/brooklyn/management/internal/BasicSubscriptionContext.java
deleted file mode 100644
index cb60545..0000000
--- a/core/src/main/java/brooklyn/management/internal/BasicSubscriptionContext.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static brooklyn.util.JavaGroovyEquivalents.mapOf;
-import groovy.lang.Closure;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.Group;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.api.event.SensorEvent;
-import org.apache.brooklyn.api.event.SensorEventListener;
-import org.apache.brooklyn.api.management.SubscriptionContext;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-import org.apache.brooklyn.api.management.SubscriptionManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-
-/**
- * A {@link SubscriptionContext} for an entity or other user of a {@link SubscriptionManager}.
- */
-public class BasicSubscriptionContext implements SubscriptionContext {
-
- private static final Logger LOG = LoggerFactory.getLogger(BasicSubscriptionContext.class);
-
- private final SubscriptionManager manager;
- private final Object subscriber;
- private final Map<String,Object> flags;
-
- public BasicSubscriptionContext(SubscriptionManager manager, Object subscriber) {
- this(Collections.<String,Object>emptyMap(), manager, subscriber);
- }
-
- public BasicSubscriptionContext(Map<String, ?> flags, SubscriptionManager manager, Object subscriber) {
- this.manager = manager;
- this.subscriber = subscriber;
- this.flags = mapOf("subscriber", subscriber);
- if (flags!=null) this.flags.putAll(flags);
- }
-
- @SuppressWarnings("rawtypes")
- public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, Closure c) {
- return subscribe(Collections.<String,Object>emptyMap(), producer, sensor, c);
- }
-
- @SuppressWarnings("rawtypes")
- public <T> SubscriptionHandle subscribe(Map<String, Object> newFlags, Entity producer, Sensor<T> sensor, Closure c) {
- return subscribe(newFlags, producer, sensor, toSensorEventListener(c));
- }
-
- @Override
- public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- return subscribe(Collections.<String,Object>emptyMap(), producer, sensor, listener);
- }
-
- @Override
- public <T> SubscriptionHandle subscribe(Map<String, Object> newFlags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- Map<String,Object> subscriptionFlags = Maps.newLinkedHashMap(flags);
- if (newFlags != null) subscriptionFlags.putAll(newFlags);
- return manager.subscribe(subscriptionFlags, producer, sensor, listener);
- }
-
- @SuppressWarnings("rawtypes")
- public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, Closure c) {
- return subscribeToChildren(Collections.<String,Object>emptyMap(), parent, sensor, c);
- }
-
- @SuppressWarnings("rawtypes")
- public <T> SubscriptionHandle subscribeToChildren(Map<String, Object> newFlags, Entity parent, Sensor<T> sensor, Closure c) {
- return subscribeToChildren(newFlags, parent, sensor, toSensorEventListener(c));
- }
-
- @Override
- public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- return subscribeToChildren(Collections.<String,Object>emptyMap(), parent, sensor, listener);
- }
-
- @Override
- public <T> SubscriptionHandle subscribeToChildren(Map<String, Object> newFlags, Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- Map<String,Object> subscriptionFlags = Maps.newLinkedHashMap(flags);
- if (newFlags != null) subscriptionFlags.putAll(newFlags);
- return manager.subscribeToChildren(subscriptionFlags, parent, sensor, listener);
- }
-
- @SuppressWarnings("rawtypes")
- public <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, Closure c) {
- return subscribeToMembers(Collections.<String,Object>emptyMap(), parent, sensor, c);
- }
-
- @SuppressWarnings("rawtypes")
- public <T> SubscriptionHandle subscribeToMembers(Map<String, Object> newFlags, Group parent, Sensor<T> sensor, Closure c) {
- return subscribeToMembers(newFlags, parent, sensor, toSensorEventListener(c));
- }
-
- @Override
- public <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- return subscribeToMembers(Collections.<String,Object>emptyMap(), parent, sensor, listener);
- }
-
- @Override
- public <T> SubscriptionHandle subscribeToMembers(Map<String, Object> newFlags, Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- Map<String,Object> subscriptionFlags = Maps.newLinkedHashMap(flags);
- if (newFlags != null) subscriptionFlags.putAll(newFlags);
- return manager.subscribeToMembers(subscriptionFlags, parent, sensor, listener);
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- public boolean unsubscribe(SubscriptionHandle subscriptionId) {
- Preconditions.checkNotNull(subscriptionId, "subscriptionId must not be null");
- Preconditions.checkArgument(Objects.equal(subscriber, ((Subscription) subscriptionId).subscriber), "The subscriptionId is for a different "+subscriber+"; expected "+((Subscription) subscriptionId).subscriber);
- return manager.unsubscribe(subscriptionId);
- }
-
- /** @see SubscriptionManager#publish(SensorEvent) */
- @Override
- public <T> void publish(SensorEvent<T> event) {
- manager.publish(event);
- }
-
- /** Return the subscriptions associated with this context */
- @Override
- public Set<SubscriptionHandle> getSubscriptions() {
- return manager.getSubscriptionsForSubscriber(subscriber);
- }
-
- @Override
- public int unsubscribeAll() {
- int count = 0;
-
- // To avoid ConcurrentModificationException when copying subscriptions, need to synchronize on it
- Set<SubscriptionHandle> subscriptions = getSubscriptions();
- Collection<SubscriptionHandle> subscriptionsCopy;
- synchronized (subscriptions) {
- subscriptionsCopy = ImmutableList.copyOf(subscriptions);
- }
-
- for (SubscriptionHandle s : subscriptionsCopy) {
- count++;
- boolean result = unsubscribe(s);
- if (!result) LOG.warn("When unsubscribing from all of {}, unsubscribe of {} return false", subscriber, s);
- }
- return count;
- }
-
- @SuppressWarnings("rawtypes")
- private <T> SensorEventListener<T> toSensorEventListener(final Closure c) {
- return new SensorEventListener<T>() {
- @Override public void onEvent(SensorEvent<T> event) {
- c.call(event);
- }
- };
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/BrooklynGarbageCollector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynGarbageCollector.java b/core/src/main/java/brooklyn/management/internal/BrooklynGarbageCollector.java
deleted file mode 100644
index 0c54909..0000000
--- a/core/src/main/java/brooklyn/management/internal/BrooklynGarbageCollector.java
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.ConcurrentModificationException;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.HasTaskChildren;
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.BrooklynTaskTags.WrappedEntity;
-import brooklyn.entity.basic.BrooklynTaskTags.WrappedStream;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Entities;
-import brooklyn.internal.storage.BrooklynStorage;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.javalang.MemoryUsageTracker;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.ExecutionListener;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Objects;
-import com.google.common.annotations.Beta;
-import com.google.common.collect.Iterables;
-
-/**
- * Deletes record of old tasks, to prevent space leaks and the eating up of more and more memory.
- *
- * The deletion policy is configurable:
- * <ul>
- * <li>Period - how frequently to look at the existing tasks to delete some, if required
- * <li>Max task age - the time after which a completed task will be automatically deleted
- * (i.e. any root task completed more than maxTaskAge ago will be deleted)
- * <li>Max tasks per <various categories> - the maximum number of tasks to be kept for a given tag,
- * split into categories based on what is seeming to be useful
- * </ul>
- *
- * The default is to check with a period of one minute, deleting tasks after 30 days,
- * and keeping at most 100000 tasks in the system,
- * max 1000 tasks per entity, 50 per effector within that entity, and 50 per other non-effector tag
- * within that entity (or global if not attached to an entity).
- *
- * @author aled
- */
-public class BrooklynGarbageCollector {
-
- private static final Logger LOG = LoggerFactory.getLogger(BrooklynGarbageCollector.class);
-
- public static final ConfigKey<Duration> GC_PERIOD = ConfigKeys.newDurationConfigKey(
- "brooklyn.gc.period", "the period for checking if any tasks need to be deleted",
- Duration.minutes(1));
-
- public static final ConfigKey<Boolean> DO_SYSTEM_GC = ConfigKeys.newBooleanConfigKey(
- "brooklyn.gc.doSystemGc", "whether to periodically call System.gc()", false);
-
- /**
- * should we check for tasks which are submitted by another but backgrounded, i.e. not a child of that task?
- * default to yes, despite it can be some extra loops, to make sure we GC them promptly.
- * @since 0.7.0 */
- // work offender is {@link DynamicSequentialTask} internal job tracker, but it is marked
- // transient so it is destroyed prompty; there may be others, however;
- // but OTOH it might be expensive to check for these all the time!
- // TODO probably we can set this false (remove this and related code),
- // and just rely on usual GC to pick up background tasks; the lifecycle of background task
- // should normally be independent of the submitter. (DST was the exception, and marking
- // transient there fixes the main problem, which is when the submitter is GC'd but the submitted is not,
- // and we don't want the submitted to show up at the root in the GUI, which it will if its
- // submitter has been GC'd)
- @Beta
- public static final ConfigKey<Boolean> CHECK_SUBTASK_SUBMITTERS = ConfigKeys.newBooleanConfigKey(
- "brooklyn.gc.checkSubtaskSubmitters", "whether for subtasks to check the submitters", true);
-
- public static final ConfigKey<Integer> MAX_TASKS_PER_TAG = ConfigKeys.newIntegerConfigKey(
- "brooklyn.gc.maxTasksPerTag",
- "the maximum number of tasks to be kept for a given tag "
- + "within an execution context (e.g. entity); "
- + "some broad-brush tags are excluded, and if an entity has multiple tags all tag counts must be full",
- 50);
-
- public static final ConfigKey<Integer> MAX_TASKS_PER_ENTITY = ConfigKeys.newIntegerConfigKey(
- "brooklyn.gc.maxTasksPerEntity",
- "the maximum number of tasks to be kept for a given entity",
- 1000);
-
- public static final ConfigKey<Integer> MAX_TASKS_GLOBAL = ConfigKeys.newIntegerConfigKey(
- "brooklyn.gc.maxTasksGlobal",
- "the maximum number of tasks to be kept across the entire system",
- 100000);
-
- public static final ConfigKey<Duration> MAX_TASK_AGE = ConfigKeys.newDurationConfigKey(
- "brooklyn.gc.maxTaskAge",
- "the duration after which a completed task will be automatically deleted",
- Duration.days(30));
-
- protected final static Comparator<Task<?>> TASKS_OLDEST_FIRST_COMPARATOR = new Comparator<Task<?>>() {
- @Override public int compare(Task<?> t1, Task<?> t2) {
- long end1 = t1.getEndTimeUtc();
- long end2 = t2.getEndTimeUtc();
- return (end1 < end2) ? -1 : ((end1 == end2) ? 0 : 1);
- }
- };
-
- private final BasicExecutionManager executionManager;
- private final BrooklynStorage storage;
- private final BrooklynProperties brooklynProperties;
- private final ScheduledExecutorService executor;
- private ScheduledFuture<?> activeCollector;
- private Map<Entity,Task<?>> unmanagedEntitiesNeedingGc = new LinkedHashMap<Entity, Task<?>>();
-
- private Duration gcPeriod;
- private final boolean doSystemGc;
- private volatile boolean running = true;
-
- public BrooklynGarbageCollector(BrooklynProperties brooklynProperties, BasicExecutionManager executionManager, BrooklynStorage storage) {
- this.executionManager = executionManager;
- this.storage = storage;
- this.brooklynProperties = brooklynProperties;
-
- doSystemGc = brooklynProperties.getConfig(DO_SYSTEM_GC);
-
- executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
- @Override public Thread newThread(Runnable r) {
- return new Thread(r, "brooklyn-gc");
- }});
-
- executionManager.addListener(new ExecutionListener() {
- @Override public void onTaskDone(Task<?> task) {
- BrooklynGarbageCollector.this.onTaskDone(task);
- }});
-
- scheduleCollector(true);
- }
-
- protected synchronized void scheduleCollector(boolean canInterruptCurrent) {
- if (activeCollector != null) activeCollector.cancel(canInterruptCurrent);
-
- gcPeriod = brooklynProperties.getConfig(GC_PERIOD);
- if (gcPeriod!=null) {
- activeCollector = executor.scheduleWithFixedDelay(
- new Runnable() {
- @Override public void run() {
- gcIteration();
- }
- },
- gcPeriod.toMillisecondsRoundingUp(),
- gcPeriod.toMillisecondsRoundingUp(),
- TimeUnit.MILLISECONDS);
- }
- }
-
- /** force a round of Brooklyn garbage collection */
- public void gcIteration() {
- try {
- logUsage("brooklyn gc (before)");
- gcTasks();
- logUsage("brooklyn gc (after)");
-
- if (doSystemGc) {
- // Can be very useful when tracking down OOMEs etc, where a lot of tasks are executing
- // Empirically observed that (on OS X jvm at least) calling twice blocks - logs a significant
- // amount of memory having been released, as though a full-gc had been run. But this is highly
- // dependent on the JVM implementation.
- System.gc(); System.gc();
- logUsage("brooklyn gc (after system gc)");
- }
- } catch (Throwable t) {
- Exceptions.propagateIfFatal(t);
- LOG.warn("Error during management-context GC: "+t, t);
- // previously we bailed on all errors, but I don't think we should do that -Alex
- }
- }
-
- public void logUsage(String prefix) {
- if (LOG.isDebugEnabled())
- LOG.debug(prefix+" - using "+getUsageString());
- }
-
- public static String makeBasicUsageString() {
- return Strings.makeSizeString(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())+" / "+
- Strings.makeSizeString(Runtime.getRuntime().totalMemory()) + " memory" +
- " ("+Strings.makeSizeString(MemoryUsageTracker.SOFT_REFERENCES.getBytesUsed()) + " soft); "+
- Thread.activeCount()+" threads";
- }
-
- public String getUsageString() {
- return makeBasicUsageString()+"; "+
- "storage: " + storage.getStorageMetrics() + "; " +
- "tasks: " +
- executionManager.getNumActiveTasks()+" active, "+
- executionManager.getNumIncompleteTasks()+" unfinished; "+
- executionManager.getNumInMemoryTasks()+" remembered, "+
- executionManager.getTotalTasksSubmitted()+" total submitted)";
- }
-
- public void shutdownNow() {
- running = false;
- if (activeCollector != null) activeCollector.cancel(true);
- if (executor != null) executor.shutdownNow();
- }
-
- public void onUnmanaged(Entity entity) {
- // defer task deletions until the entity is completely unmanaged
- // (this is usually invoked during the stop sequence)
- synchronized (unmanagedEntitiesNeedingGc) {
- unmanagedEntitiesNeedingGc.put(entity, Tasks.current());
- }
- }
-
- public void deleteTasksForEntity(Entity entity) {
- // remove all references to this entity from tasks
- executionManager.deleteTag(entity);
- executionManager.deleteTag(BrooklynTaskTags.tagForContextEntity(entity));
- executionManager.deleteTag(BrooklynTaskTags.tagForCallerEntity(entity));
- executionManager.deleteTag(BrooklynTaskTags.tagForTargetEntity(entity));
- }
-
- public void onUnmanaged(Location loc) {
- // No-op currently; no tasks are tracked through their location
- }
-
- public void onTaskDone(Task<?> task) {
- if (shouldDeleteTaskImmediately(task)) {
- executionManager.deleteTask(task);
- }
- }
-
- /** @deprecated since 0.7.0, method moved internal until semantics are clarified; see also {@link #shouldDeleteTaskImmediately(Task)} */
- @Deprecated
- public boolean shouldDeleteTask(Task<?> task) {
- return shouldDeleteTaskImmediately(task);
- }
- /** whether this task should be deleted on completion,
- * because it is transient, or because it is submitted background without much context information */
- protected boolean shouldDeleteTaskImmediately(Task<?> task) {
- if (!task.isDone()) return false;
-
- Set<Object> tags = task.getTags();
- if (tags.contains(ManagementContextInternal.TRANSIENT_TASK_TAG))
- return true;
- if (tags.contains(ManagementContextInternal.EFFECTOR_TAG) || tags.contains(ManagementContextInternal.NON_TRANSIENT_TASK_TAG))
- return false;
-
- if (task.getSubmittedByTask()!=null) {
- Task<?> parent = task.getSubmittedByTask();
- if (executionManager.getTask(parent.getId())==null) {
- // parent is already cleaned up
- return true;
- }
- if (parent instanceof HasTaskChildren && Iterables.contains(((HasTaskChildren)parent).getChildren(), task)) {
- // it is a child, let the parent manage this task's death
- return false;
- }
- Entity associatedEntity = BrooklynTaskTags.getTargetOrContextEntity(task);
- if (associatedEntity!=null) {
- // this is associated to an entity; destroy only if the entity is unmanaged
- return !Entities.isManaged(associatedEntity);
- }
- // if not associated to an entity, then delete immediately
- return true;
- }
-
- // e.g. scheduled tasks, sensor events, etc
- // TODO (in future may keep some of these with another limit, based on a new TagCategory)
- // there may also be a server association for server-side tasks which should be kept
- // (but be careful not to keep too many subscriptions!)
-
- return true;
- }
-
- /**
- * Deletes old tasks. The age/number of tasks to keep is controlled by fields like
- * {@link #maxTasksPerTag} and {@link #maxTaskAge}.
- */
- protected synchronized int gcTasks() {
- // TODO Must be careful with memory usage here: have seen OOME if we get crazy lots of tasks.
- // hopefully the use new limits, filters, and use of live lists in some places (added Sep 2014) will help.
- //
- // An option is for getTasksWithTag(tag) to return an ArrayList rather than a LinkedHashSet. That
- // is a far more memory efficient data structure (e.g. 4 bytes overhead per object rather than
- // 32 bytes overhead per object for HashSet).
- //
- // More notes on optimization is in the history of this file.
-
- if (!running) return 0;
-
- Duration newPeriod = brooklynProperties.getConfig(GC_PERIOD);
- if (!Objects.equal(gcPeriod, newPeriod)) {
- // caller has changed period, reschedule on next run
- scheduleCollector(false);
- }
-
- expireUnmanagedEntityTasks();
- expireAgedTasks();
- expireTransientTasks();
-
- // now look at overcapacity tags, non-entity tags first
-
- Set<Object> taskTags = executionManager.getTaskTags();
-
- int maxTasksPerEntity = brooklynProperties.getConfig(MAX_TASKS_PER_ENTITY);
- int maxTasksPerTag = brooklynProperties.getConfig(MAX_TASKS_PER_TAG);
-
- Map<Object,AtomicInteger> taskNonEntityTagsOverCapacity = MutableMap.of();
- Map<Object,AtomicInteger> taskEntityTagsOverCapacity = MutableMap.of();
-
- Map<Object,AtomicInteger> taskAllTagsOverCapacity = MutableMap.of();
-
- for (Object tag : taskTags) {
- if (isTagIgnoredForGc(tag)) continue;
-
- Set<Task<?>> tasksWithTag = executionManager.tasksWithTagLiveOrNull(tag);
- if (tasksWithTag==null) continue;
- AtomicInteger overA = null;
- if (tag instanceof WrappedEntity) {
- int over = tasksWithTag.size() - maxTasksPerEntity;
- if (over>0) {
- overA = new AtomicInteger(over);
- taskEntityTagsOverCapacity.put(tag, overA);
- }
- } else {
- int over = tasksWithTag.size() - maxTasksPerTag;
- if (over>0) {
- overA = new AtomicInteger(over);
- taskNonEntityTagsOverCapacity.put(tag, overA);
- }
- }
- if (overA!=null) {
- taskAllTagsOverCapacity.put(tag, overA);
- }
- }
-
- int deletedCount = 0;
- deletedCount += expireOverCapacityTagsInCategory(taskNonEntityTagsOverCapacity, taskAllTagsOverCapacity, TagCategory.NON_ENTITY_NORMAL, false);
- deletedCount += expireOverCapacityTagsInCategory(taskEntityTagsOverCapacity, taskAllTagsOverCapacity, TagCategory.ENTITY, true);
- deletedCount += expireSubTasksWhoseSubmitterIsExpired();
-
- int deletedGlobally = expireIfOverCapacityGlobally();
- deletedCount += deletedGlobally;
- if (deletedGlobally>0) deletedCount += expireSubTasksWhoseSubmitterIsExpired();
-
- return deletedCount;
- }
-
- protected static boolean isTagIgnoredForGc(Object tag) {
- if (tag == null) return true;
- if (tag.equals(ManagementContextInternal.EFFECTOR_TAG)) return true;
- if (tag.equals(ManagementContextInternal.SUB_TASK_TAG)) return true;
- if (tag.equals(ManagementContextInternal.NON_TRANSIENT_TASK_TAG)) return true;
- if (tag.equals(ManagementContextInternal.TRANSIENT_TASK_TAG)) return true;
- if (tag instanceof WrappedStream) {
- return true;
- }
-
- return false;
- }
-
- protected void expireUnmanagedEntityTasks() {
- Iterator<Entry<Entity, Task<?>>> ei;
- synchronized (unmanagedEntitiesNeedingGc) {
- ei = MutableSet.copyOf(unmanagedEntitiesNeedingGc.entrySet()).iterator();
- }
- while (ei.hasNext()) {
- Entry<Entity, Task<?>> ee = ei.next();
- if (Entities.isManaged(ee.getKey())) continue;
- if (ee.getValue()!=null && !ee.getValue().isDone()) continue;
- deleteTasksForEntity(ee.getKey());
- synchronized (unmanagedEntitiesNeedingGc) {
- unmanagedEntitiesNeedingGc.remove(ee.getKey());
- }
- }
- }
-
- protected void expireAgedTasks() {
- Duration maxTaskAge = brooklynProperties.getConfig(MAX_TASK_AGE);
-
- Collection<Task<?>> allTasks = executionManager.allTasksLive();
- Collection<Task<?>> tasksToDelete = MutableList.of();
-
- try {
- for (Task<?> task: allTasks) {
- if (!task.isDone()) continue;
- if (BrooklynTaskTags.isSubTask(task)) continue;
-
- if (maxTaskAge.isShorterThan(Duration.sinceUtc(task.getEndTimeUtc())))
- tasksToDelete.add(task);
- }
-
- } catch (ConcurrentModificationException e) {
- // delete what we've found so far
- LOG.debug("Got CME inspecting aged tasks, with "+tasksToDelete.size()+" found for deletion: "+e);
- }
-
- for (Task<?> task: tasksToDelete) {
- executionManager.deleteTask(task);
- }
- }
-
- protected void expireTransientTasks() {
- Set<Task<?>> transientTasks = executionManager.getTasksWithTag(BrooklynTaskTags.TRANSIENT_TASK_TAG);
- for (Task<?> t: transientTasks) {
- if (!t.isDone()) continue;
- executionManager.deleteTask(t);
- }
- }
-
- protected int expireSubTasksWhoseSubmitterIsExpired() {
- // ideally we wouldn't have this; see comments on CHECK_SUBTASK_SUBMITTERS
- if (!brooklynProperties.getConfig(CHECK_SUBTASK_SUBMITTERS))
- return 0;
-
- Collection<Task<?>> allTasks = executionManager.allTasksLive();
- Collection<Task<?>> tasksToDelete = MutableList.of();
- try {
- for (Task<?> task: allTasks) {
- if (!task.isDone()) continue;
- Task<?> submitter = task.getSubmittedByTask();
- // if we've leaked, ie a subtask which is not a child task,
- // and the submitter is GC'd, then delete this also
- if (submitter!=null && submitter.isDone() && executionManager.getTask(submitter.getId())==null) {
- tasksToDelete.add(task);
- }
- }
-
- } catch (ConcurrentModificationException e) {
- // delete what we've found so far
- LOG.debug("Got CME inspecting aged tasks, with "+tasksToDelete.size()+" found for deletion: "+e);
- }
-
- for (Task<?> task: tasksToDelete) {
- executionManager.deleteTask(task);
- }
- return tasksToDelete.size();
- }
-
- protected enum TagCategory {
- ENTITY, NON_ENTITY_NORMAL;
-
- public boolean acceptsTag(Object tag) {
- if (isTagIgnoredForGc(tag)) return false;
- if (tag instanceof WrappedEntity) return this==ENTITY;
- if (this==ENTITY) return false;
- return true;
- }
- }
-
-
- /** expires tasks which are over-capacity in all their non-entity tag categories, returned count */
- protected int expireOverCapacityTagsInCategory(Map<Object, AtomicInteger> taskTagsInCategoryOverCapacity, Map<Object, AtomicInteger> taskAllTagsOverCapacity, TagCategory category, boolean emptyFilterNeeded) {
- if (emptyFilterNeeded) {
- // previous run may have decremented counts
- MutableList<Object> nowOkayTags = MutableList.of();
- for (Map.Entry<Object,AtomicInteger> entry: taskTagsInCategoryOverCapacity.entrySet()) {
- if (entry.getValue().get()<=0) nowOkayTags.add(entry.getKey());
- }
- for (Object tag: nowOkayTags) taskTagsInCategoryOverCapacity.remove(tag);
- }
-
- if (taskTagsInCategoryOverCapacity.isEmpty())
- return 0;
-
- Collection<Task<?>> tasks = executionManager.allTasksLive();
- List<Task<?>> tasksToConsiderDeleting = MutableList.of();
- try {
- for (Task<?> task: tasks) {
- if (!task.isDone()) continue;
-
- Set<Object> tags = task.getTags();
-
- int categoryTags = 0, tooFullCategoryTags = 0;
- for (Object tag: tags) {
- if (category.acceptsTag(tag)) {
- categoryTags++;
- if (taskTagsInCategoryOverCapacity.containsKey(tag))
- tooFullCategoryTags++;
- }
- }
- if (tooFullCategoryTags>0) {
- if (categoryTags==tooFullCategoryTags) {
- // all buckets are full, delete this one
- tasksToConsiderDeleting.add(task);
- } else {
- // if any bucket is under capacity, then give grace to the other buckets in this category
- for (Object tag: tags) {
- if (category.acceptsTag(tag)) {
- AtomicInteger over = taskTagsInCategoryOverCapacity.get(tag);
- if (over!=null) {
- if (over.decrementAndGet()<=0) {
- // and remove it from over-capacity if so
- taskTagsInCategoryOverCapacity.remove(tag);
- if (taskTagsInCategoryOverCapacity.isEmpty())
- return 0;
- }
- }
- }
- }
- }
- }
- }
-
- } catch (ConcurrentModificationException e) {
- // do CME's happen with these data structures?
- // if so, let's just delete what we've found so far
- LOG.debug("Got CME inspecting tasks, with "+tasksToConsiderDeleting.size()+" found for deletion: "+e);
- }
-
- if (LOG.isDebugEnabled())
- LOG.debug("brooklyn-gc detected "+taskTagsInCategoryOverCapacity.size()+" "+category+" "
- + "tags over capacity, expiring old tasks; "
- + tasksToConsiderDeleting.size()+" tasks under consideration; categories are: "
- + taskTagsInCategoryOverCapacity);
-
- Collections.sort(tasksToConsiderDeleting, TASKS_OLDEST_FIRST_COMPARATOR);
- // now try deleting tasks which are overcapacity for each (non-entity) tag
- int deleted = 0;
- for (Task<?> task: tasksToConsiderDeleting) {
- boolean delete = true;
- for (Object tag: task.getTags()) {
- if (!category.acceptsTag(tag))
- continue;
- if (taskTagsInCategoryOverCapacity.get(tag)==null) {
- // no longer over capacity in this tag
- delete = false;
- break;
- }
- }
- if (delete) {
- // delete this and update overcapacity info
- deleted++;
- executionManager.deleteTask(task);
- for (Object tag: task.getTags()) {
- AtomicInteger counter = taskAllTagsOverCapacity.get(tag);
- if (counter!=null && counter.decrementAndGet()<=0)
- taskTagsInCategoryOverCapacity.remove(tag);
- }
- if (LOG.isTraceEnabled())
- LOG.trace("brooklyn-gc deleted "+task+", buckets now "+taskTagsInCategoryOverCapacity);
- if (taskTagsInCategoryOverCapacity.isEmpty())
- break;
- }
- }
-
- if (LOG.isDebugEnabled())
- LOG.debug("brooklyn-gc deleted "+deleted+" tasks in over-capacity " + category+" tag categories; "
- + "capacities now: " + taskTagsInCategoryOverCapacity);
- return deleted;
- }
-
- protected int expireIfOverCapacityGlobally() {
- Collection<Task<?>> tasksLive = executionManager.allTasksLive();
- if (tasksLive.size() <= brooklynProperties.getConfig(MAX_TASKS_GLOBAL))
- return 0;
- LOG.debug("brooklyn-gc detected "+tasksLive.size()+" tasks in memory, over global limit, looking at deleting some");
-
- try {
- tasksLive = MutableList.copyOf(tasksLive);
- } catch (ConcurrentModificationException e) {
- tasksLive = executionManager.getTasksWithAllTags(MutableList.of());
- }
-
- MutableList<Task<?>> tasks = MutableList.of();
- for (Task<?> task: tasksLive) {
- if (task.isDone()) {
- tasks.add(task);
- }
- }
-
- int numToDelete = tasks.size() - brooklynProperties.getConfig(MAX_TASKS_GLOBAL);
- if (numToDelete <= 0) {
- LOG.debug("brooklyn-gc detected only "+tasks.size()+" completed tasks in memory, not over global limit, so not deleting any");
- return 0;
- }
-
- Collections.sort(tasks, TASKS_OLDEST_FIRST_COMPARATOR);
-
- int numDeleted = 0;
- while (numDeleted < numToDelete && tasks.size()>numDeleted) {
- executionManager.deleteTask( tasks.get(numDeleted++) );
- }
- if (LOG.isDebugEnabled())
- LOG.debug("brooklyn-gc deleted "+numDeleted+" tasks as was over global limit, now have "+executionManager.allTasksLive().size());
- return numDeleted;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
deleted file mode 100644
index dd9d8bc..0000000
--- a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagementMode.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-/** Indicates how an entity/location/adjunct is treated at a given {@link ManagementContext} */
-public enum BrooklynObjectManagementMode {
- /** item does not exist, not in memory, nor persisted (e.g. creating for first time, or finally destroying) */
- NONEXISTENT,
- /** item exists or existed elsewhere, i.e. there is persisted state, but is not loaded here */
- UNMANAGED_PERSISTED,
- /** item is loaded but read-only (ie not actively managed here) */
- LOADED_READ_ONLY,
- /** item is actively managed here */
- MANAGED_PRIMARY
-}
\ No newline at end of file
[17/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
deleted file mode 100644
index e8d2cfa..0000000
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.net.URI;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.api.basic.BrooklynObject;
-import org.apache.brooklyn.api.catalog.BrooklynCatalog;
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Effector;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.drivers.EntityDriverManager;
-import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager;
-import org.apache.brooklyn.api.entity.rebind.ChangeListener;
-import org.apache.brooklyn.api.entity.rebind.PersistenceExceptionHandler;
-import org.apache.brooklyn.api.entity.rebind.RebindExceptionHandler;
-import org.apache.brooklyn.api.entity.rebind.RebindManager;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationRegistry;
-import org.apache.brooklyn.api.management.AccessController;
-import org.apache.brooklyn.api.management.EntityManager;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.apache.brooklyn.api.management.LocationManager;
-import org.apache.brooklyn.api.management.SubscriptionContext;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityManager;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
-import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
-import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
-
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.StringConfigMap;
-import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.entity.proxying.InternalLocationFactory;
-import brooklyn.entity.proxying.InternalPolicyFactory;
-import brooklyn.internal.storage.BrooklynStorage;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.ha.OsgiManager;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Objects;
-
-public class NonDeploymentManagementContext implements ManagementContextInternal {
-
- private static final Logger log = LoggerFactory.getLogger(NonDeploymentManagementContext.class);
-
- public enum NonDeploymentManagementContextMode {
- PRE_MANAGEMENT,
- MANAGEMENT_REBINDING,
- MANAGEMENT_STARTING,
- MANAGEMENT_STARTED,
- MANAGEMENT_STOPPING,
- MANAGEMENT_STOPPED;
-
- public boolean isPreManaged() {
- return this == PRE_MANAGEMENT || this == MANAGEMENT_REBINDING;
- }
- }
-
- private final AbstractEntity entity;
- private NonDeploymentManagementContextMode mode;
- private ManagementContextInternal initialManagementContext;
-
- private final QueueingSubscriptionManager qsm;
- private final BasicSubscriptionContext subscriptionContext;
- private NonDeploymentEntityManager entityManager;
- private NonDeploymentLocationManager locationManager;
- private NonDeploymentAccessManager accessManager;
- private NonDeploymentUsageManager usageManager;
- private EntitlementManager entitlementManager;;
-
- public NonDeploymentManagementContext(AbstractEntity entity, NonDeploymentManagementContextMode mode) {
- this.entity = checkNotNull(entity, "entity");
- this.mode = checkNotNull(mode, "mode");
- qsm = new QueueingSubscriptionManager();
- subscriptionContext = new BasicSubscriptionContext(qsm, entity);
- entityManager = new NonDeploymentEntityManager(null);
- locationManager = new NonDeploymentLocationManager(null);
- accessManager = new NonDeploymentAccessManager(null);
- usageManager = new NonDeploymentUsageManager(null);
-
- // TODO might need to be some kind of "system" which can see that the system is running at this point
- // though quite possibly we are entirely behind the auth-wall at this point
- entitlementManager = Entitlements.minimal();
- }
-
- @Override
- public String getManagementPlaneId() {
- return (initialManagementContext == null) ? null : initialManagementContext.getManagementPlaneId();
- }
-
- @Override
- public String getManagementNodeId() {
- return (initialManagementContext == null) ? null : initialManagementContext.getManagementNodeId();
- }
-
- @Override
- public Maybe<URI> getManagementNodeUri() {
- return (initialManagementContext == null) ? Maybe.<URI>absent() : initialManagementContext.getManagementNodeUri();
- }
-
- public void setManagementContext(ManagementContextInternal val) {
- this.initialManagementContext = checkNotNull(val, "initialManagementContext");
- this.entityManager = new NonDeploymentEntityManager(val);
- this.locationManager = new NonDeploymentLocationManager(val);
- this.accessManager = new NonDeploymentAccessManager(val);
- this.usageManager = new NonDeploymentUsageManager(val);
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this).add("entity", entity.getId()).add("mode", mode).toString();
- }
-
- public void setMode(NonDeploymentManagementContextMode mode) {
- this.mode = checkNotNull(mode, "mode");
- }
- public NonDeploymentManagementContextMode getMode() {
- return mode;
- }
-
- @Override
- public Collection<Application> getApplications() {
- return Collections.emptyList();
- }
-
- @Override
- public boolean isRunning() {
- // Assume that the real management context has not been terminated, so always true
- return true;
- }
-
- @Override
- public boolean isStartupComplete() {
- // This mgmt context is only used by items who are not yet fully started.
- // It's slightly misleading as this does not refer to the main mgmt context.
- // OTOH it probably won't be used. TBC. -Alex, Apr 2015
- return false;
- }
-
- @Override
- public InternalEntityFactory getEntityFactory() {
- checkInitialManagementContextReal();
- return initialManagementContext.getEntityFactory();
- }
-
- @Override
- public InternalLocationFactory getLocationFactory() {
- checkInitialManagementContextReal();
- return initialManagementContext.getLocationFactory();
- }
-
- @Override
- public InternalPolicyFactory getPolicyFactory() {
- checkInitialManagementContextReal();
- return initialManagementContext.getPolicyFactory();
- }
-
- @Override
- public EntityManager getEntityManager() {
- return entityManager;
- }
-
- @Override
- public LocationManager getLocationManager() {
- return locationManager;
- }
-
- @Override
- public AccessManager getAccessManager() {
- return accessManager;
- }
-
- @Override
- public UsageManager getUsageManager() {
- return usageManager;
- }
-
- @Override
- public Maybe<OsgiManager> getOsgiManager() {
- return Maybe.absent();
- }
-
- @Override
- public AccessController getAccessController() {
- return getAccessManager().getAccessController();
- }
-
- @Override
- public ExecutionManager getExecutionManager() {
- checkInitialManagementContextReal();
- return initialManagementContext.getExecutionManager();
- }
-
- @Override
- public QueueingSubscriptionManager getSubscriptionManager() {
- return qsm;
- }
-
- @Override
- public synchronized SubscriptionContext getSubscriptionContext(Entity entity) {
- if (!this.entity.equals(entity)) throw new IllegalStateException("Non-deployment context "+this+" can only use a single Entity: has "+this.entity+", but passed "+entity);
- if (mode==NonDeploymentManagementContextMode.MANAGEMENT_STOPPED)
- throw new IllegalStateException("Entity "+entity+" is no longer managed; subscription context not available");
- return subscriptionContext;
- }
-
- @Override
- public ExecutionContext getExecutionContext(Entity entity) {
- if (!this.entity.equals(entity)) throw new IllegalStateException("Non-deployment context "+this+" can only use a single Entity: has "+this.entity+", but passed "+entity);
- if (mode==NonDeploymentManagementContextMode.MANAGEMENT_STOPPED)
- throw new IllegalStateException("Entity "+entity+" is no longer managed; execution context not available");
- checkInitialManagementContextReal();
- return initialManagementContext.getExecutionContext(entity);
- }
-
- @Override
- public ExecutionContext getServerExecutionContext() {
- return initialManagementContext.getServerExecutionContext();
- }
-
- // TODO the methods below should delegate to the application?
- @Override
- public EntityDriverManager getEntityDriverManager() {
- checkInitialManagementContextReal();
- return initialManagementContext.getEntityDriverManager();
- }
-
- @Override
- public DownloadResolverManager getEntityDownloadsManager() {
- checkInitialManagementContextReal();
- return initialManagementContext.getEntityDownloadsManager();
- }
-
- @Override
- public StringConfigMap getConfig() {
- checkInitialManagementContextReal();
- return initialManagementContext.getConfig();
- }
-
- @Override
- public BrooklynProperties getBrooklynProperties() {
- checkInitialManagementContextReal();
- return initialManagementContext.getBrooklynProperties();
- }
-
- @Override
- public BrooklynStorage getStorage() {
- checkInitialManagementContextReal();
- return initialManagementContext.getStorage();
- }
-
- @Override
- public RebindManager getRebindManager() {
- // There was a race where EffectorUtils on invoking an effector calls:
- // mgmtSupport.getEntityChangeListener().onEffectorCompleted(eff);
- // but where the entity/app may be being unmanaged concurrently (e.g. calling app.stop()).
- // So now we allow the change-listener to be called.
-
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getRebindManager();
- } else {
- return new NonDeploymentRebindManager();
- }
- }
-
- @Override
- public HighAvailabilityManager getHighAvailabilityManager() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getHighAvailabilityManager();
- } else {
- return new NonDeploymentHighAvailabilityManager();
- }
- }
-
- @Override
- public LocationRegistry getLocationRegistry() {
- checkInitialManagementContextReal();
- return initialManagementContext.getLocationRegistry();
- }
-
- @Override
- public BrooklynCatalog getCatalog() {
- checkInitialManagementContextReal();
- return initialManagementContext.getCatalog();
- }
-
- @Override
- public ClassLoader getCatalogClassLoader() {
- checkInitialManagementContextReal();
- return initialManagementContext.getCatalogClassLoader();
- }
-
- @Override
- public EntitlementManager getEntitlementManager() {
- return entitlementManager;
- }
-
- @Override
- public <T> T invokeEffectorMethodSync(final Entity entity, final Effector<T> eff, final Object args) throws ExecutionException {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot invoke effector "+eff+" on entity "+entity);
- }
-
- @Override
- public <T> Task<T> invokeEffector(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters) {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot invoke effector "+eff+" on entity "+entity);
- }
-
- @Override
- public ClassLoader getBaseClassLoader() {
- checkInitialManagementContextReal();
- return initialManagementContext.getBaseClassLoader();
- }
-
- @Override
- public Iterable<URL> getBaseClassPathForScanning() {
- checkInitialManagementContextReal();
- return initialManagementContext.getBaseClassPathForScanning();
- }
-
- @Override
- public void addEntitySetListener(CollectionChangeListener<Entity> listener) {
- checkInitialManagementContextReal();
- initialManagementContext.addEntitySetListener(listener);
- }
-
- @Override
- public void removeEntitySetListener(CollectionChangeListener<Entity> listener) {
- checkInitialManagementContextReal();
- initialManagementContext.removeEntitySetListener(listener);
- }
-
- @Override
- public void terminate() {
- if (isInitialManagementContextReal()) {
- initialManagementContext.terminate();
- } else {
- // no-op; the non-deployment management context has nothing needing terminated
- }
- }
-
- @Override
- public long getTotalEffectorInvocations() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getTotalEffectorInvocations();
- } else {
- return 0;
- }
- }
-
- @Override
- public void setBaseClassPathForScanning(Iterable<URL> urls) {
- checkInitialManagementContextReal();
- initialManagementContext.setBaseClassPathForScanning(urls);
- }
-
- @Override
- public void setManagementNodeUri(URI uri) {
- checkInitialManagementContextReal();
- initialManagementContext.setManagementNodeUri(uri);
- }
-
- @Override
- public void prePreManage(Entity entity) {
- // should throw? but in 0.7.0-SNAPSHOT it was no-op
- log.warn("Ignoring call to prePreManage("+entity+") on "+this);
- }
-
- @Override
- public void prePreManage(Location location) {
- // should throw? but in 0.7.0-SNAPSHOT it was no-op
- log.warn("Ignoring call to prePreManage("+location+") on "+this);
- }
-
- private boolean isInitialManagementContextReal() {
- return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
- }
-
- private void checkInitialManagementContextReal() {
- if (!isInitialManagementContextReal()) {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation.");
- }
- }
-
- @Override
- public void reloadBrooklynProperties() {
- checkInitialManagementContextReal();
- initialManagementContext.reloadBrooklynProperties();
- }
-
- @Override
- public void addPropertiesReloadListener(PropertiesReloadListener listener) {
- checkInitialManagementContextReal();
- initialManagementContext.addPropertiesReloadListener(listener);
- }
-
- @Override
- public void removePropertiesReloadListener(PropertiesReloadListener listener) {
- checkInitialManagementContextReal();
- initialManagementContext.removePropertiesReloadListener(listener);
- }
-
- @Override
- public BrooklynObject lookup(String id) {
- checkInitialManagementContextReal();
- return initialManagementContext.lookup(id);
- }
-
- @Override
- public <T extends BrooklynObject> T lookup(String id, Class<T> type) {
- checkInitialManagementContextReal();
- return initialManagementContext.lookup(id, type);
- }
-
- @Override
- public List<Throwable> errors() {
- checkInitialManagementContextReal();
- return initialManagementContext.errors();
- }
-
- @Override
- public CatalogInitialization getCatalogInitialization() {
- checkInitialManagementContextReal();
- return initialManagementContext.getCatalogInitialization();
- }
-
- @Override
- public void setCatalogInitialization(CatalogInitialization catalogInitialization) {
- checkInitialManagementContextReal();
- initialManagementContext.setCatalogInitialization(catalogInitialization);
- }
-
- /**
- * For when the initial management context is not "real"; the changeListener is a no-op, but everything else forbidden.
- *
- * @author aled
- */
- private class NonDeploymentRebindManager implements RebindManager {
-
- @Override
- public ChangeListener getChangeListener() {
- return ChangeListener.NOOP;
- }
-
- @Override
- public void setPersister(BrooklynMementoPersister persister) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public void setPersister(BrooklynMementoPersister persister, PersistenceExceptionHandler exceptionHandler) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public BrooklynMementoPersister getPersister() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public List<Application> rebind() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public List<Application> rebind(ClassLoader classLoader) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public List<Application> rebind(ClassLoader classLoader, RebindExceptionHandler exceptionHandler) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public List<Application> rebind(ClassLoader classLoader, RebindExceptionHandler exceptionHandler, ManagementNodeState mode) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public void startPersistence() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public void stopPersistence() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public void startReadOnly(ManagementNodeState state) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public void stopReadOnly() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public void start() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public void stop() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public void waitForPendingComplete(Duration timeout, boolean canTrigger) throws InterruptedException, TimeoutException {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public void forcePersistNow() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public void forcePersistNow(boolean full, PersistenceExceptionHandler exceptionHandler) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public BrooklynMementoRawData retrieveMementoRawData() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public boolean isAwaitingInitialRebind() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
-
- @Override
- public Map<String, Object> getMetrics() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- }
-
- /**
- * For when the initial management context is not "real".
- *
- * @author aled
- */
- private class NonDeploymentHighAvailabilityManager implements HighAvailabilityManager {
- @Override
- public ManagementNodeState getNodeState() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public boolean isRunning() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public HighAvailabilityManager setPersister(ManagementPlaneSyncRecordPersister persister) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public void disabled() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public void start(HighAvailabilityMode startMode) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public void stop() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public ManagementPlaneSyncRecordPersister getPersister() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public ManagementPlaneSyncRecord getLastManagementPlaneSyncRecord() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public ManagementPlaneSyncRecord loadManagementPlaneSyncRecord(boolean x) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public void changeMode(HighAvailabilityMode startMode) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public void setPriority(long priority) {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public long getPriority() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public Map<String, Object> getMetrics() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public void publishClearNonMaster() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- @Override
- public long getLastStateChange() {
- throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/NonDeploymentUsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentUsageManager.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentUsageManager.java
deleted file mode 100644
index ec2cd10..0000000
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentUsageManager.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.location.Location;
-
-import brooklyn.entity.basic.Lifecycle;
-import brooklyn.management.usage.ApplicationUsage;
-import brooklyn.management.usage.LocationUsage;
-
-import com.google.common.base.Predicate;
-
-
-public class NonDeploymentUsageManager implements UsageManager {
-
- // TODO All the `isInitialManagementContextReal()` code-checks is a code-smell.
- // Expect we can delete a lot of this once we guarantee that all entities are
- // instantiated via EntitySpec / EntityManager. Until then, we'll live with this.
-
- private final ManagementContextInternal initialManagementContext;
-
- public NonDeploymentUsageManager(ManagementContextInternal initialManagementContext) {
- this.initialManagementContext = initialManagementContext;
- }
-
- private boolean isInitialManagementContextReal() {
- return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
- }
-
- @Override
- public void recordApplicationEvent(Application app, Lifecycle state) {
- if (isInitialManagementContextReal()) {
- initialManagementContext.getUsageManager().recordApplicationEvent(app, state);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public void recordLocationEvent(Location loc, Lifecycle state) {
- if (isInitialManagementContextReal()) {
- initialManagementContext.getUsageManager().recordLocationEvent(loc, state);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public LocationUsage getLocationUsage(String locationId) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getUsageManager().getLocationUsage(locationId);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public Set<LocationUsage> getLocationUsage(Predicate<? super LocationUsage> filter) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getUsageManager().getLocationUsage(filter);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public ApplicationUsage getApplicationUsage(String appId) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getUsageManager().getApplicationUsage(appId);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public Set<ApplicationUsage> getApplicationUsage(Predicate<? super ApplicationUsage> filter) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getUsageManager().getApplicationUsage(filter);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- @Deprecated
- public void addUsageListener(brooklyn.management.internal.UsageManager.UsageListener listener) {
- addUsageListener(new brooklyn.management.internal.UsageManager.UsageListener.UsageListenerAdapter(listener));
- }
-
- @Override
- @Deprecated
- public void removeUsageListener(brooklyn.management.internal.UsageManager.UsageListener listener) {
- removeUsageListener(new brooklyn.management.internal.UsageManager.UsageListener.UsageListenerAdapter(listener));
- }
-
- @Override
- public void addUsageListener(brooklyn.management.internal.UsageListener listener) {
- if (isInitialManagementContextReal()) {
- initialManagementContext.getUsageManager().addUsageListener(listener);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public void removeUsageListener(brooklyn.management.internal.UsageListener listener) {
- if (isInitialManagementContextReal()) {
- initialManagementContext.getUsageManager().removeUsageListener(listener);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/QueueingSubscriptionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/QueueingSubscriptionManager.java b/core/src/main/java/brooklyn/management/internal/QueueingSubscriptionManager.java
deleted file mode 100644
index fb232ad..0000000
--- a/core/src/main/java/brooklyn/management/internal/QueueingSubscriptionManager.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.api.event.SensorEvent;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-
-import com.google.common.base.Objects;
-
-@SuppressWarnings("rawtypes")
-public class QueueingSubscriptionManager extends AbstractSubscriptionManager {
-
- static class QueuedSubscription<T> {
- Map<String, Object> flags;
- Subscription<T> s;
- }
-
- public AbstractSubscriptionManager delegate = null;
- public boolean useDelegateForSubscribing = false;
- public boolean useDelegateForPublishing = false;
-
- List<QueuedSubscription> queuedSubscriptions = new ArrayList<QueuedSubscription>();
- List<SensorEvent> queuedSensorEvents = new ArrayList<SensorEvent>();
-
- @Override
- protected synchronized <T> SubscriptionHandle subscribe(Map<String, Object> flags, Subscription<T> s) {
- if (useDelegateForSubscribing)
- return delegate.subscribe(flags, s);
-
- QueuedSubscription<T> qs = new QueuedSubscription<T>();
- qs.flags = flags;
- s.subscriber = getSubscriber(flags, s);
- qs.s = s;
- queuedSubscriptions.add(qs);
- return s;
- }
-
- @Override
- public synchronized <T> void publish(SensorEvent<T> event) {
- if (useDelegateForPublishing) {
- delegate.publish(event);
- return;
- }
-
- queuedSensorEvents.add(event);
- }
-
- public void setDelegate(AbstractSubscriptionManager delegate) {
- this.delegate = delegate;
- }
-
- @SuppressWarnings("unchecked")
- public synchronized void startDelegatingForSubscribing() {
- assert delegate!=null;
- for (QueuedSubscription s: queuedSubscriptions) {
- delegate.subscribe(s.flags, s.s);
- }
- queuedSubscriptions.clear();
- useDelegateForSubscribing = true;
- }
-
- @SuppressWarnings("unchecked")
- public synchronized void startDelegatingForPublishing() {
- assert delegate!=null;
- for (SensorEvent evt: queuedSensorEvents) {
- delegate.publish(evt);
- }
- queuedSensorEvents.clear();
- useDelegateForPublishing = true;
- }
-
- public synchronized void stopDelegatingForSubscribing() {
- useDelegateForSubscribing = false;
- }
-
- public synchronized void stopDelegatingForPublishing() {
- useDelegateForPublishing = false;
- }
-
- @Override
- public synchronized boolean unsubscribe(SubscriptionHandle subscriptionId) {
- if (useDelegateForSubscribing)
- return delegate.unsubscribe(subscriptionId);
-
- Iterator<QueuedSubscription> qi = queuedSubscriptions.iterator();
- while (qi.hasNext()) {
- QueuedSubscription q = qi.next();
- if (Objects.equal(subscriptionId, q.s)) {
- qi.remove();
- return true;
- }
- }
- return false;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public synchronized Set<SubscriptionHandle> getSubscriptionsForSubscriber(Object subscriber) {
- if (useDelegateForSubscribing)
- return delegate.getSubscriptionsForSubscriber(subscriber);
-
- Set<SubscriptionHandle> result = new LinkedHashSet<SubscriptionHandle>();
- for (QueuedSubscription q: queuedSubscriptions) {
- if (Objects.equal(subscriber, getSubscriber(q.flags, q.s))) result.add(q.s);
- }
- return result;
- }
-
- @Override
- public synchronized Set<SubscriptionHandle> getSubscriptionsForEntitySensor(Entity source, Sensor<?> sensor) {
- if (useDelegateForSubscribing)
- return delegate.getSubscriptionsForEntitySensor(source, sensor);
-
- Set<SubscriptionHandle> result = new LinkedHashSet<SubscriptionHandle>();
- for (QueuedSubscription q: queuedSubscriptions) {
- if ((q.s.sensor==null || Objects.equal(q.s.sensor, sensor)) &&
- (q.s.producer==null || Objects.equal(q.s.producer, sensor)))
- result.add(q.s);
- }
- return result;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/Subscription.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/Subscription.java b/core/src/main/java/brooklyn/management/internal/Subscription.java
deleted file mode 100644
index f8409cb..0000000
--- a/core/src/main/java/brooklyn/management/internal/Subscription.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.api.event.SensorEvent;
-import org.apache.brooklyn.api.event.SensorEventListener;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-
-import brooklyn.util.text.Identifiers;
-
-import com.google.common.base.Predicate;
-
-class Subscription<T> implements SubscriptionHandle {
- public final String id = Identifiers.makeRandomId(8);
-
- public Object subscriber;
- public Object subscriberExecutionManagerTag;
- /** whether the tag was supplied by user, in which case we should not clear execution semantics */
- public boolean subscriberExecutionManagerTagSupplied;
- public final Entity producer;
- public final Sensor<T> sensor;
- public final SensorEventListener<? super T> listener;
- public Map<String,Object> flags;
- public Predicate<SensorEvent<T>> eventFilter;
-
- public Subscription(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- this.producer = producer;
- this.sensor = sensor;
- this.listener = listener;
- }
-
- @Override
- public boolean equals(Object other) {
- return (other instanceof Subscription && ((Subscription<?>)other).id==id);
- }
-
- @Override
- public int hashCode() {
- return id.hashCode();
- }
-
- @Override
- public String toString() {
- return "Subscription["+id+";"+subscriber+"@"+LocalSubscriptionManager.makeEntitySensorToken(producer,sensor)+"]";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/SubscriptionTracker.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/SubscriptionTracker.java b/core/src/main/java/brooklyn/management/internal/SubscriptionTracker.java
deleted file mode 100644
index ec86fae..0000000
--- a/core/src/main/java/brooklyn/management/internal/SubscriptionTracker.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.Collection;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.Group;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.api.event.SensorEventListener;
-import org.apache.brooklyn.api.management.SubscriptionContext;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.SetMultimap;
-
-/**
- * Tracks subscriptions associated that are registered with particular entities. Gives utilities for unsubscribing from all
- * subscriptions on a given entity, etc.
- */
-public class SubscriptionTracker {
-
- // This class is thread-safe. All modifications to subscriptions are synchronized on the
- // "subscriptions" field. However, calls to alien code (i.e. context.subscribe etc) is
- // done without holding the lock.
- //
- // If two threads do subscribe() and unsubscribeAll() concurrently, then it's non-derministic
- // whether the subscription will be in place at the end (but that's unavoidable). However, it
- // is guaranteed that the internal state of the SubscriptionTracker will be consistent: if
- // the "subscriptions" includes the new subscription then that subscription will really exist,
- // and vice versa.
-
- protected SubscriptionContext context;
-
- private final SetMultimap<Entity, SubscriptionHandle> subscriptions = HashMultimap.create();
-
- public SubscriptionTracker(SubscriptionContext subscriptionContext) {
- this.context = subscriptionContext;
- }
-
- /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
- public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- SubscriptionHandle handle = context.subscribe(producer, sensor, listener);
- synchronized (subscriptions) {
- subscriptions.put(producer, handle);
- }
- return handle;
- }
-
- /** @see SubscriptionContext#subscribeToChildren(Entity, Sensor, SensorEventListener) */
- public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- SubscriptionHandle handle = context.subscribeToChildren(parent, sensor, listener);
- synchronized (subscriptions) {
- subscriptions.put(parent, handle);
- }
- return handle;
- }
-
- /**
- * @see SubscriptionContext#subscribeToMembers(Group, Sensor, SensorEventListener)
- */
- public <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
- SubscriptionHandle handle = context.subscribeToMembers(parent, sensor, listener);
- synchronized (subscriptions) {
- subscriptions.put(parent, handle);
- }
- return handle;
- }
-
- /**
- * Unsubscribes the given producer.
- *
- * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
- */
- public boolean unsubscribe(Entity producer) {
- Collection<SubscriptionHandle> handles;
- synchronized (subscriptions) {
- handles = subscriptions.removeAll(producer);
- }
- if (handles != null) {
- for (SubscriptionHandle handle : handles) {
- context.unsubscribe(handle);
- }
- return true;
- }
- return false;
- }
-
- /**
- * Unsubscribes the given producer.
- *
- * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
- */
- public boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
- synchronized (subscriptions) {
- subscriptions.remove(producer, handle);
- }
- return context.unsubscribe(handle);
- }
-
- /**
- * @return an ordered list of all subscription handles
- */
- public Collection<SubscriptionHandle> getAllSubscriptions() {
- synchronized (subscriptions) {
- return ImmutableList.copyOf(subscriptions.values());
- }
- }
-
- public void unsubscribeAll() {
- Collection<SubscriptionHandle> subscriptionsSnapshot;
- synchronized (subscriptions) {
- subscriptionsSnapshot = ImmutableList.copyOf(subscriptions.values());
- subscriptions.clear();
- }
- for (SubscriptionHandle s: subscriptionsSnapshot) {
- context.unsubscribe(s);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/UsageListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/UsageListener.java b/core/src/main/java/brooklyn/management/internal/UsageListener.java
deleted file mode 100644
index 5a2af3a..0000000
--- a/core/src/main/java/brooklyn/management/internal/UsageListener.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.location.Location;
-
-import brooklyn.management.usage.ApplicationUsage.ApplicationEvent;
-import brooklyn.management.usage.LocationUsage.LocationEvent;
-
-import com.google.common.annotations.Beta;
-
-@Beta
-public interface UsageListener {
-
- /**
- * A no-op implementation of {@link UsageListener}, for users to extend.
- *
- * Users are encouraged to extend this class, which will shield the user
- * from the addition of other usage event methods being added. If additional
- * methods are added in a future release, a no-op implementation will be
- * added to this class.
- */
- @Beta
- public static class BasicUsageListener implements UsageListener {
- @Override
- public void onApplicationEvent(ApplicationMetadata app, ApplicationEvent event) {
- }
-
- @Override public void onLocationEvent(LocationMetadata loc, LocationEvent event) {
- }
- }
-
- /**
- * Users should never implement this interface directly; methods may be added in future releases
- * without notice.
- */
- @Beta
- public interface ApplicationMetadata {
- /**
- * Access the application directly with caution: by the time the listener fires,
- * the application may no longer be managed.
- */
- @Beta
- Application getApplication();
-
- String getApplicationId();
-
- String getApplicationName();
-
- String getEntityType();
-
- String getCatalogItemId();
-
- Map<String, String> getMetadata();
- }
-
- /**
- * Users should never implement this interface directly; methods may be added in future releases
- * without notice.
- */
- @Beta
- public interface LocationMetadata {
- /**
- * Access the location directly with caution: by the time the listener fires,
- * the location may no longer be managed.
- */
- @Beta
- Location getLocation();
-
- String getLocationId();
-
- Map<String, String> getMetadata();
- }
-
- public static final UsageListener NOOP = new UsageListener() {
- @Override public void onApplicationEvent(ApplicationMetadata app, ApplicationEvent event) {}
- @Override public void onLocationEvent(LocationMetadata loc, LocationEvent event) {}
- };
-
- @Beta
- void onApplicationEvent(ApplicationMetadata app, ApplicationEvent event);
-
- @Beta
- void onLocationEvent(LocationMetadata loc, LocationEvent event);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/UsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/UsageManager.java b/core/src/main/java/brooklyn/management/internal/UsageManager.java
deleted file mode 100644
index 5105faf..0000000
--- a/core/src/main/java/brooklyn/management/internal/UsageManager.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.location.Location;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Lifecycle;
-import brooklyn.management.usage.ApplicationUsage;
-import brooklyn.management.usage.ApplicationUsage.ApplicationEvent;
-import brooklyn.management.usage.LocationUsage;
-import brooklyn.management.usage.LocationUsage.LocationEvent;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.reflect.TypeToken;
-
-@Beta
-public interface UsageManager {
-
- @SuppressWarnings("serial")
- public static final ConfigKey<List<brooklyn.management.internal.UsageListener>> USAGE_LISTENERS = ConfigKeys.newConfigKey(
- new TypeToken<List<brooklyn.management.internal.UsageListener>>() {},
- "brooklyn.usageManager.listeners", "Optional usage listeners (i.e. for metering)",
- ImmutableList.<brooklyn.management.internal.UsageListener>of());
-
- public static final ConfigKey<Duration> USAGE_LISTENER_TERMINATION_TIMEOUT = ConfigKeys.newConfigKey(
- Duration.class,
- "brooklyn.usageManager.listeners.timeout",
- "Timeout on termination, to wait for queue of usage listener events to be processed",
- Duration.TEN_SECONDS);
-
- /**
- * @since 0.7.0
- * @deprecated since 0.7.0; use {@link brooklyn.management.internal.UsageListener}; see {@link UsageListenerAdapter}
- */
- public interface UsageListener {
- public static final UsageListener NOOP = new UsageListener() {
- @Override public void onApplicationEvent(String applicationId, String applicationName, String entityType,
- String catalogItemId, Map<String, String> metadata, ApplicationEvent event) {}
- @Override public void onLocationEvent(String locationId, Map<String, String> metadata, LocationEvent event) {}
- };
-
- public static class UsageListenerAdapter implements brooklyn.management.internal.UsageListener {
- private final UsageListener listener;
-
- public UsageListenerAdapter(UsageListener listener) {
- this.listener = checkNotNull(listener, "listener");
- }
-
- @Override
- public void onApplicationEvent(ApplicationMetadata app, ApplicationEvent event) {
- listener.onApplicationEvent(app.getApplicationId(), app.getApplicationName(), app.getEntityType(), app.getCatalogItemId(), app.getMetadata(), event);
- }
-
- @Override
- public void onLocationEvent(LocationMetadata loc, LocationEvent event) {
- listener.onLocationEvent(loc.getLocationId(), loc.getMetadata(), event);
- }
-
- @Override
- public boolean equals(Object obj) {
- return (obj instanceof UsageListenerAdapter) && listener.equals(((UsageListenerAdapter)obj).listener);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(listener);
- }
- }
-
- void onApplicationEvent(String applicationId, String applicationName, String entityType, String catalogItemId,
- Map<String, String> metadata, ApplicationEvent event);
-
- void onLocationEvent(String locationId, Map<String, String> metadata, LocationEvent event);
- }
-
- /**
- * Adds this application event to the usage record for the given app (creating the usage
- * record if one does not already exist).
- */
- void recordApplicationEvent(Application app, Lifecycle state);
-
- /**
- * Adds this location event to the usage record for the given location (creating the usage
- * record if one does not already exist).
- */
- void recordLocationEvent(Location loc, Lifecycle state);
-
- /**
- * Returns the usage info for the location with the given id, or null if unknown.
- */
- LocationUsage getLocationUsage(String locationId);
-
- /**
- * Returns the usage info that matches the given predicate.
- * For example, could be used to find locations used within a given time period.
- */
- Set<LocationUsage> getLocationUsage(Predicate<? super LocationUsage> filter);
-
- /**
- * Returns the usage info for the application with the given id, or null if unknown.
- */
- ApplicationUsage getApplicationUsage(String appId);
-
- /**
- * Returns the usage info that matches the given predicate.
- * For example, could be used to find applications used within a given time period.
- */
- Set<ApplicationUsage> getApplicationUsage(Predicate<? super ApplicationUsage> filter);
-
- /**
- * @since 0.7.0
- * @deprecated since 0.7.0; use {@link #removeUsageListener(brooklyn.management.internal.UsageListener)};
- * see {@link brooklyn.management.internal.UsageManager.UsageListener.UsageListenerAdapter}
- */
- void addUsageListener(brooklyn.management.internal.UsageManager.UsageListener listener);
-
- /**
- * @since 0.7.0
- * @deprecated since 0.7.0; use {@link #removeUsageListener(brooklyn.management.internal.UsageListener)}
- */
- @Deprecated
- void removeUsageListener(brooklyn.management.internal.UsageManager.UsageListener listener);
-
- /**
- * Adds the given listener, to be notified on recording of application/location events.
- * The listener notifications may be asynchronous.
- *
- * As of 0.7.0, the listener is not persisted so will be lost on restart/rebind. This
- * behaviour may change in a subsequent release.
- */
- void addUsageListener(brooklyn.management.internal.UsageListener listener);
-
- /**
- * Removes the given listener.
- */
- void removeUsageListener(brooklyn.management.internal.UsageListener listener);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/usage/ApplicationUsage.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/usage/ApplicationUsage.java b/core/src/main/java/brooklyn/management/usage/ApplicationUsage.java
deleted file mode 100644
index 7186783..0000000
--- a/core/src/main/java/brooklyn/management/usage/ApplicationUsage.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.usage;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.entity.basic.Lifecycle;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-
-/**
- */
-public class ApplicationUsage {
-
- public static class ApplicationEvent {
- private final Date date;
- private final Lifecycle state;
- private final String user;
-
- public ApplicationEvent(Lifecycle state, String user) {
- this(new Date(), state, user);
- }
-
- public ApplicationEvent(Date date, Lifecycle state) {
- this(date,state, null);
- }
-
- public ApplicationEvent(Date date, Lifecycle state, String user) {
- this.date = checkNotNull(date, "date");
- this.state = checkNotNull(state, "state");
- this.user = user;
- }
-
- public Date getDate() {
- return date;
- }
-
- public Lifecycle getState() {
- return state;
- }
-
- public String getUser() {
- return user;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof ApplicationEvent)) return false;
- ApplicationEvent o = (ApplicationEvent) other;
- return Objects.equal(date, o.date) && Objects.equal(state, o.state) && Objects.equal(user, o.user);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(date, state, user);
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this).add("date", date).add("state", state).add("entitlementContext", user).toString();
- }
- }
-
- private final String applicationId;
- private final String applicationName;
- private final String entityType;
- private final Map<String, String> metadata;
- private final List<ApplicationEvent> events = Collections.synchronizedList(Lists.<ApplicationEvent>newArrayList());
-
- public ApplicationUsage(String applicationId, String applicationName, String entityType, Map<String, String> metadata) {
- this.applicationId = checkNotNull(applicationId, "applicationId");
- // allow name to be null, happens in certain failed rebind cases
- this.applicationName = applicationName;
- this.entityType = checkNotNull(entityType, "entityType");
- this.metadata = checkNotNull(metadata, "metadata");
- }
-
- public String getApplicationId() {
- return applicationId;
- }
-
- public String getApplicationName() {
- return applicationName;
- }
-
- public String getEntityType() {
- return entityType;
- }
-
- public Map<String, String> getMetadata() {
- return metadata;
- }
-
- public List<ApplicationEvent> getEvents() {
- synchronized (events) {
- return ImmutableList.copyOf(events);
- }
- }
-
- public void addEvent(ApplicationEvent event) {
- events.add(checkNotNull(event, "event"));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/usage/LocationUsage.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/usage/LocationUsage.java b/core/src/main/java/brooklyn/management/usage/LocationUsage.java
deleted file mode 100644
index fbca540..0000000
--- a/core/src/main/java/brooklyn/management/usage/LocationUsage.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.usage;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import brooklyn.entity.basic.Lifecycle;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-
-/**
- */
-public class LocationUsage {
-
- public static class LocationEvent {
- private final Date date;
- private final Lifecycle state;
- private final String entityId;
- private final String entityType;
- private final String applicationId;
- private final String user;
-
- public LocationEvent(Lifecycle state, String entityId, String entityType, String applicationId, String user) {
- this(new Date(), state, entityId, entityType, applicationId, user);
- }
-
- public LocationEvent(Date date, Lifecycle state, String entityId, String entityType, String applicationId, String user) {
- this.date = checkNotNull(date, "date");
- this.state = checkNotNull(state, "state");
- this.entityId = checkNotNull(entityId, "entityId");
- this.entityType = checkNotNull(entityType, "entityType");
- this.applicationId = checkNotNull(applicationId, "applicationId (entity "+entityId+")");
- this.user = user;
- }
-
- public Date getDate() {
- return date;
- }
-
- public Lifecycle getState() {
- return state;
- }
-
- public String getEntityId() {
- return entityId;
- }
-
- public String getEntityType() {
- return entityType;
- }
-
- public String getApplicationId() {
- return applicationId;
- }
-
- public String getUser() {
- return user;
- }
-
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof LocationEvent)) return false;
- LocationEvent o = (LocationEvent) other;
- return Objects.equal(date, o.date) && Objects.equal(state, o.state)
- && Objects.equal(entityId, o.entityId) && Objects.equal(entityType, o.entityType)
- && Objects.equal(applicationId, o.applicationId) && Objects.equal(user, o.user);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(date, state, entityId, entityType, applicationId, user);
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this)
- .add("date", date)
- .add("state", state)
- .add("entityId", entityId)
- .add("appId", applicationId)
- .add("user", user)
- .toString();
- }
- }
-
- private final String locationId;
- private final Map<String, String> metadata;
- private final List<LocationEvent> events = Collections.synchronizedList(Lists.<LocationEvent>newArrayList());
-
- public LocationUsage(String locationId, Map<String, String> metadata) {
- this.locationId = checkNotNull(locationId, "locationId");
- this.metadata = checkNotNull(metadata, "metadata");
- }
-
- public String getLocationId() {
- return locationId;
- }
-
- public Map<String, String> getMetadata() {
- return metadata;
- }
-
- public List<LocationEvent> getEvents() {
- synchronized (events) {
- return ImmutableList.copyOf(events);
- }
- }
-
- public void addEvent(LocationEvent event) {
- events.add(checkNotNull(event, "event"));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
index 0c2314c..ab303a0 100644
--- a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
+++ b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.api.management.SubscriptionContext;
import org.apache.brooklyn.api.management.SubscriptionHandle;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.EntityAdjunct;
+import org.apache.brooklyn.core.management.internal.SubscriptionTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,7 +53,6 @@ import brooklyn.enricher.basic.AbstractEnricher;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.management.internal.SubscriptionTracker;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.flags.FlagUtils;
import brooklyn.util.flags.SetFromFlag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/util/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/ResourceUtils.java b/core/src/main/java/brooklyn/util/ResourceUtils.java
index cb350af..53264e3 100644
--- a/core/src/main/java/brooklyn/util/ResourceUtils.java
+++ b/core/src/main/java/brooklyn/util/ResourceUtils.java
@@ -40,6 +40,7 @@ import java.util.regex.Pattern;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.Credentials;
@@ -53,8 +54,9 @@ import org.slf4j.LoggerFactory;
import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.internal.BrooklynInitialization;
+
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
+
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.http.HttpTool;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java b/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java
index 3a41fb2..8942a18 100644
--- a/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java
+++ b/core/src/main/java/brooklyn/util/task/BasicExecutionContext.java
@@ -36,13 +36,13 @@ import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.BrooklynTaskTags.WrappedEntity;
import brooklyn.entity.basic.EntityInternal;
-import brooklyn.management.entitlement.Entitlements;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/util/task/CompoundTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/CompoundTask.java b/core/src/main/java/brooklyn/util/task/CompoundTask.java
index 81f865d..e33120c 100644
--- a/core/src/main/java/brooklyn/util/task/CompoundTask.java
+++ b/core/src/main/java/brooklyn/util/task/CompoundTask.java
@@ -31,11 +31,11 @@ import java.util.concurrent.ExecutionException;
import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java b/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java
index a58a05a..455a889 100644
--- a/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java
+++ b/core/src/main/java/brooklyn/util/task/DynamicSequentialTask.java
@@ -31,11 +31,11 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskQueueingContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.time.CountdownTimer;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/util/text/TemplateProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/text/TemplateProcessor.java b/core/src/main/java/brooklyn/util/text/TemplateProcessor.java
index b5d8b2d..eb0c2ad 100644
--- a/core/src/main/java/brooklyn/util/text/TemplateProcessor.java
+++ b/core/src/main/java/brooklyn/util/text/TemplateProcessor.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.entity.drivers.EntityDriver;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,7 +39,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.event.basic.DependentConfiguration;
import brooklyn.event.basic.Sensors;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/ManagementContextInjectable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ManagementContextInjectable.java b/core/src/main/java/org/apache/brooklyn/core/management/ManagementContextInjectable.java
new file mode 100644
index 0000000..c92639e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ManagementContextInjectable.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+
+/**
+ * Provides a way for the {@link ManagementContext} to be injected directly.
+ */
+public interface ManagementContextInjectable {
+
+ /**
+ * Sets the {@link ManagementContext} reference.
+ */
+ public void injectManagementContext(ManagementContext managementContext);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/classloading/AbstractBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/classloading/AbstractBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/management/classloading/AbstractBrooklynClassLoadingContext.java
new file mode 100644
index 0000000..a8366df
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/classloading/AbstractBrooklynClassLoadingContext.java
@@ -0,0 +1,82 @@
+package org.apache.brooklyn.core.management.classloading;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Objects;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+public abstract class AbstractBrooklynClassLoadingContext implements BrooklynClassLoadingContext {
+
+ protected final ManagementContext mgmt;
+
+ public AbstractBrooklynClassLoadingContext(ManagementContext mgmt) {
+ this.mgmt = mgmt;
+ }
+
+ @Override
+ public ManagementContext getManagementContext() {
+ return mgmt;
+ }
+
+ @Override
+ public Class<?> loadClass(String className) {
+ return tryLoadClass(className).get();
+ }
+
+ @Override
+ // this is the only one left for subclasses
+ public abstract Maybe<Class<?>> tryLoadClass(String className);
+
+ @Override
+ public <T> Class<? extends T> loadClass(String className, @Nullable Class<T> supertype) {
+ return tryLoadClass(className, supertype).get();
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public <T> Maybe<Class<? extends T>> tryLoadClass(String className, @Nullable Class<T> supertype) {
+ Maybe<Class<?>> result = tryLoadClass(className);
+ if (result.isAbsent()) return (Maybe)result;
+ Class<?> clazz = result.get();
+ if (supertype==null || supertype.isAssignableFrom(clazz)) return (Maybe)result;
+ throw new ClassCastException(className+" is not an instance of "+supertype);
+ }
+
+ @Override
+ public abstract String toString();
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(mgmt);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof BrooklynClassLoadingContext)) return false;
+ if (!Objects.equal(mgmt, ((BrooklynClassLoadingContext)obj).getManagementContext())) return false;
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/classloading/BrooklynClassLoadingContextSequential.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/classloading/BrooklynClassLoadingContextSequential.java b/core/src/main/java/org/apache/brooklyn/core/management/classloading/BrooklynClassLoadingContextSequential.java
new file mode 100644
index 0000000..afc2232
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/classloading/BrooklynClassLoadingContextSequential.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.classloading;
+
+import java.net.URL;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public final class BrooklynClassLoadingContextSequential extends AbstractBrooklynClassLoadingContext {
+
+ private static final Logger log = LoggerFactory.getLogger(BrooklynClassLoadingContextSequential.class);
+
+ private final List<BrooklynClassLoadingContext> primaries = MutableList.<BrooklynClassLoadingContext>of();
+ // secondaries used to put java classloader last
+ private final Set<BrooklynClassLoadingContext> secondaries = MutableSet.<BrooklynClassLoadingContext>of();
+
+ public BrooklynClassLoadingContextSequential(ManagementContext mgmt, BrooklynClassLoadingContext ...targets) {
+ super(mgmt);
+ for (BrooklynClassLoadingContext target: targets)
+ add(target);
+ }
+
+ public void add(BrooklynClassLoadingContext target) {
+ if (target instanceof BrooklynClassLoadingContextSequential) {
+ for (BrooklynClassLoadingContext targetN: ((BrooklynClassLoadingContextSequential)target).primaries )
+ add(targetN);
+ for (BrooklynClassLoadingContext targetN: ((BrooklynClassLoadingContextSequential)target).secondaries )
+ addSecondary(targetN);
+ } else {
+ this.primaries.add( target );
+ }
+ }
+
+ public void addSecondary(BrooklynClassLoadingContext target) {
+ if (!(target instanceof JavaBrooklynClassLoadingContext)) {
+ // support for legacy catalog classloader only
+ log.warn("Only Java classloaders should be secondary");
+ }
+ this.secondaries.add( target );
+ }
+
+ public Maybe<Class<?>> tryLoadClass(String className) {
+ List<Throwable> errors = MutableList.of();
+ for (BrooklynClassLoadingContext target: primaries) {
+ Maybe<Class<?>> clazz = target.tryLoadClass(className);
+ if (clazz.isPresent())
+ return clazz;
+ errors.add( ((Maybe.Absent<?>)clazz).getException() );
+ }
+ boolean noPrimaryErrors = errors.isEmpty();
+ for (BrooklynClassLoadingContext target: secondaries) {
+ Maybe<Class<?>> clazz = target.tryLoadClass(className);
+ if (clazz.isPresent())
+ return clazz;
+ if (noPrimaryErrors)
+ errors.add( ((Maybe.Absent<?>)clazz).getException() );
+ }
+
+ return Maybe.absent(Exceptions.create("Unable to load "+className+" from "+primaries, errors));
+ }
+
+ @Override
+ public URL getResource(String resourceInThatDir) {
+ for (BrooklynClassLoadingContext target: primaries) {
+ URL result = target.getResource(resourceInThatDir);
+ if (result!=null) return result;
+ }
+ for (BrooklynClassLoadingContext target: secondaries) {
+ URL result = target.getResource(resourceInThatDir);
+ if (result!=null) return result;
+ }
+ return null;
+ }
+
+ @Override
+ public Iterable<URL> getResources(String name) {
+ List<Iterable<URL>> resources = Lists.newArrayList();
+ for (BrooklynClassLoadingContext target : primaries) {
+ resources.add(target.getResources(name));
+ }
+ for (BrooklynClassLoadingContext target : secondaries) {
+ resources.add(target.getResources(name));
+ }
+ return Iterables.concat(resources);
+ }
+
+ @Override
+ public String toString() {
+ return "classload:"+primaries+";"+secondaries;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), primaries, secondaries);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.equals(obj)) return false;
+ if (!(obj instanceof BrooklynClassLoadingContextSequential)) return false;
+ if (!Objects.equal(primaries, ((BrooklynClassLoadingContextSequential)obj).primaries)) return false;
+ if (!Objects.equal(secondaries, ((BrooklynClassLoadingContextSequential)obj).secondaries)) return false;
+ return true;
+ }
+
+}
[30/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/catalog
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
new file mode 100644
index 0000000..0e8ec80
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -0,0 +1,1315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+import io.brooklyn.camp.spi.pdp.DeploymentPlan;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+
+import brooklyn.basic.BrooklynObjectInternal.ConfigurationSupportInternal;
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+
+import org.apache.brooklyn.api.basic.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
+import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
+import brooklyn.config.BrooklynServerConfig;
+
+import org.apache.brooklyn.location.basic.BasicLocationRegistry;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.javalang.AggregateClassLoader;
+import brooklyn.util.javalang.LoadedClassLoader;
+import brooklyn.util.javalang.Reflections;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+import brooklyn.util.yaml.Yamls;
+import brooklyn.util.yaml.Yamls.YamlExtract;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Iterables;
+
+/* TODO the complex tree-structured catalogs are only useful when we are relying on those separate catalog classloaders
+ * to isolate classpaths. with osgi everything is just put into the "manual additions" catalog. */
+public class BasicBrooklynCatalog implements BrooklynCatalog {
+ private static final String POLICIES_KEY = "brooklyn.policies";
+ private static final String LOCATIONS_KEY = "brooklyn.locations";
+ public static final String NO_VERSION = "0.0.0.SNAPSHOT";
+
+ private static final Logger log = LoggerFactory.getLogger(BasicBrooklynCatalog.class);
+
+ public static class BrooklynLoaderTracker {
+ public static final ThreadLocal<BrooklynClassLoadingContext> loader = new ThreadLocal<BrooklynClassLoadingContext>();
+
+ public static void setLoader(BrooklynClassLoadingContext val) {
+ loader.set(val);
+ }
+
+ // TODO Stack, for recursive calls?
+ public static void unsetLoader(BrooklynClassLoadingContext val) {
+ loader.set(null);
+ }
+
+ public static BrooklynClassLoadingContext getLoader() {
+ return loader.get();
+ }
+ }
+
+ private final ManagementContext mgmt;
+ private CatalogDo catalog;
+ private volatile CatalogDo manualAdditionsCatalog;
+ private volatile LoadedClassLoader manualAdditionsClasses;
+ private final AggregateClassLoader rootClassLoader = AggregateClassLoader.newInstanceWithNoLoaders();
+
+ public BasicBrooklynCatalog(ManagementContext mgmt) {
+ this(mgmt, CatalogDto.newNamedInstance("empty catalog", "empty catalog", "empty catalog, expected to be reset later"));
+ }
+
+ public BasicBrooklynCatalog(ManagementContext mgmt, CatalogDto dto) {
+ this.mgmt = checkNotNull(mgmt, "managementContext");
+ this.catalog = new CatalogDo(mgmt, dto);
+ }
+
+ public boolean blockIfNotLoaded(Duration timeout) {
+ try {
+ return getCatalog().blockIfNotLoaded(timeout);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public void reset(CatalogDto dto) {
+ reset(dto, true);
+ }
+
+ public void reset(CatalogDto dto, boolean failOnLoadError) {
+ // Unregister all existing persisted items.
+ for (CatalogItem<?, ?> toRemove : getCatalogItems()) {
+ if (log.isTraceEnabled()) {
+ log.trace("Scheduling item for persistence removal: {}", toRemove.getId());
+ }
+ mgmt.getRebindManager().getChangeListener().onUnmanaged(toRemove);
+ }
+ CatalogDo catalog = new CatalogDo(mgmt, dto);
+ CatalogUtils.logDebugOrTraceIfRebinding(log, "Resetting "+this+" catalog to "+dto);
+ catalog.load(mgmt, null, failOnLoadError);
+ CatalogUtils.logDebugOrTraceIfRebinding(log, "Reloaded catalog for "+this+", now switching");
+ this.catalog = catalog;
+ resetRootClassLoader();
+ this.manualAdditionsCatalog = null;
+
+ // Inject management context into and persist all the new entries.
+ for (CatalogItem<?, ?> entry : getCatalogItems()) {
+ boolean setManagementContext = false;
+ if (entry instanceof CatalogItemDo) {
+ CatalogItemDo<?, ?> cid = CatalogItemDo.class.cast(entry);
+ if (cid.getDto() instanceof CatalogItemDtoAbstract) {
+ CatalogItemDtoAbstract<?, ?> cdto = CatalogItemDtoAbstract.class.cast(cid.getDto());
+ if (cdto.getManagementContext() == null) {
+ cdto.setManagementContext((ManagementContextInternal) mgmt);
+ }
+ setManagementContext = true;
+ }
+ }
+ if (!setManagementContext) {
+ log.warn("Can't set management context on entry with unexpected type in catalog. type={}, " +
+ "expected={}", entry, CatalogItemDo.class);
+ }
+ if (log.isTraceEnabled()) {
+ log.trace("Scheduling item for persistence addition: {}", entry.getId());
+ }
+ mgmt.getRebindManager().getChangeListener().onManaged(entry);
+ }
+
+ }
+
+ /**
+ * Resets the catalog to the given entries
+ */
+ @Override
+ public void reset(Collection<CatalogItem<?, ?>> entries) {
+ CatalogDto newDto = CatalogDto.newDtoFromCatalogItems(entries, "explicit-catalog-reset");
+ reset(newDto);
+ }
+
+ public CatalogDo getCatalog() {
+ return catalog;
+ }
+
+ protected CatalogItemDo<?,?> getCatalogItemDo(String symbolicName, String version) {
+ String fixedVersionId = getFixedVersionId(symbolicName, version);
+ if (fixedVersionId == null) {
+ //no items with symbolicName exist
+ return null;
+ }
+
+ return catalog.getIdCache().get( CatalogUtils.getVersionedId(symbolicName, fixedVersionId) );
+ }
+
+ private String getFixedVersionId(String symbolicName, String version) {
+ if (!DEFAULT_VERSION.equals(version)) {
+ return version;
+ } else {
+ return getDefaultVersion(symbolicName);
+ }
+ }
+
+ private String getDefaultVersion(String symbolicName) {
+ Iterable<CatalogItem<Object, Object>> versions = getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName)));
+ Collection<CatalogItem<Object, Object>> orderedVersions = sortVersionsDesc(versions);
+ if (!orderedVersions.isEmpty()) {
+ return orderedVersions.iterator().next().getVersion();
+ } else {
+ return null;
+ }
+ }
+
+ private <T,SpecT> Collection<CatalogItem<T,SpecT>> sortVersionsDesc(Iterable<CatalogItem<T,SpecT>> versions) {
+ return ImmutableSortedSet.orderedBy(CatalogItemComparator.<T,SpecT>getInstance()).addAll(versions).build();
+ }
+
+ @Override
+ @Deprecated
+ public CatalogItem<?,?> getCatalogItem(String symbolicName) {
+ return getCatalogItem(symbolicName, DEFAULT_VERSION);
+ }
+
+ @Override
+ public CatalogItem<?,?> getCatalogItem(String symbolicName, String version) {
+ if (symbolicName == null) return null;
+ checkNotNull(version, "version");
+ CatalogItemDo<?, ?> itemDo = getCatalogItemDo(symbolicName, version);
+ if (itemDo == null) return null;
+ return itemDo.getDto();
+ }
+
+ @Override
+ @Deprecated
+ public void deleteCatalogItem(String id) {
+ //Delete only if installed through the
+ //deprecated methods. Don't support DEFAULT_VERSION for delete.
+ deleteCatalogItem(id, NO_VERSION);
+ }
+
+ @Override
+ public void deleteCatalogItem(String symbolicName, String version) {
+ log.debug("Deleting manual catalog item from "+mgmt+": "+symbolicName + ":" + version);
+ checkNotNull(symbolicName, "id");
+ checkNotNull(version, "version");
+ if (DEFAULT_VERSION.equals(version)) {
+ throw new IllegalStateException("Deleting items with unspecified version (argument DEFAULT_VERSION) not supported.");
+ }
+ CatalogItem<?, ?> item = getCatalogItem(symbolicName, version);
+ CatalogItemDtoAbstract<?,?> itemDto = getAbstractCatalogItem(item);
+ if (itemDto == null) {
+ throw new NoSuchElementException("No catalog item found with id "+symbolicName);
+ }
+ if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
+ manualAdditionsCatalog.deleteEntry(itemDto);
+
+ // Ensure the cache is de-populated
+ getCatalog().deleteEntry(itemDto);
+
+ // And indicate to the management context that it should be removed.
+ if (log.isTraceEnabled()) {
+ log.trace("Scheduling item for persistence removal: {}", itemDto.getId());
+ }
+ if (itemDto.getCatalogItemType() == CatalogItemType.LOCATION) {
+ @SuppressWarnings("unchecked")
+ CatalogItem<Location,LocationSpec<?>> locationItem = (CatalogItem<Location, LocationSpec<?>>) itemDto;
+ ((BasicLocationRegistry)mgmt.getLocationRegistry()).removeDefinedLocation(locationItem);
+ }
+ mgmt.getRebindManager().getChangeListener().onUnmanaged(itemDto);
+
+ }
+
+ @Override
+ @Deprecated
+ public <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id) {
+ return getCatalogItem(type, id, DEFAULT_VERSION);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id, String version) {
+ if (id==null || version==null) return null;
+ CatalogItem<?,?> result = getCatalogItem(id, version);
+ if (result==null) return null;
+ if (type==null || type.isAssignableFrom(result.getCatalogItemJavaType()))
+ return (CatalogItem<T,SpecT>)result;
+ return null;
+ }
+
+ @Override
+ public void persist(CatalogItem<?, ?> catalogItem) {
+ checkArgument(getCatalogItem(catalogItem.getSymbolicName(), catalogItem.getVersion()) != null, "Unknown catalog item %s", catalogItem);
+ mgmt.getRebindManager().getChangeListener().onChanged(catalogItem);
+ }
+
+ @Override
+ public ClassLoader getRootClassLoader() {
+ if (rootClassLoader.isEmpty() && catalog!=null) {
+ resetRootClassLoader();
+ }
+ return rootClassLoader;
+ }
+
+ private void resetRootClassLoader() {
+ rootClassLoader.reset(ImmutableList.of(catalog.getRootClassLoader()));
+ }
+
+ /**
+ * Loads this catalog. No effect if already loaded.
+ */
+ public void load() {
+ log.debug("Loading catalog for " + mgmt);
+ getCatalog().load(mgmt, null);
+ if (log.isDebugEnabled()) {
+ log.debug("Loaded catalog for " + mgmt + ": " + catalog + "; search classpath is " + catalog.getRootClassLoader());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
+ if (item == null) return null;
+ CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getSymbolicName(), item.getVersion());
+ if (loadedItem == null) throw new RuntimeException(item+" not in catalog; cannot create spec");
+ Class<SpecT> specType = loadedItem.getSpecType();
+ if (specType==null) return null;
+
+ String yaml = loadedItem.getPlanYaml();
+
+ if (yaml!=null) {
+ // preferred way is to parse the yaml, to resolve references late;
+ // the parsing on load is to populate some fields, but it is optional.
+ // TODO messy for location and policy that we need brooklyn.{locations,policies} root of the yaml, but it works;
+ // see related comment when the yaml is set, in addAbstractCatalogItems
+ // (not sure if anywhere else relies on that syntax; if not, it should be easy to fix!)
+ DeploymentPlan plan = makePlanFromYaml(yaml);
+ BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item);
+ SpecT spec;
+ switch (item.getCatalogItemType()) {
+ case TEMPLATE:
+ case ENTITY:
+ spec = createEntitySpec(loadedItem.getSymbolicName(), plan, loader);
+ break;
+ case POLICY:
+ spec = createPolicySpec(loadedItem.getSymbolicName(), plan, loader);
+ break;
+ case LOCATION:
+ spec = createLocationSpec(plan, loader);
+ break;
+ default: throw new RuntimeException("Only entity, policy & location catalog items are supported. Unsupported catalog item type " + item.getCatalogItemType());
+ }
+ ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId());
+
+ if (Strings.isBlank( ((AbstractBrooklynObjectSpec<?, ?>)spec).getDisplayName() ))
+ ((AbstractBrooklynObjectSpec<?, ?>)spec).displayName(item.getDisplayName());
+
+ return spec;
+ }
+
+ // revert to legacy mechanism
+ SpecT spec = null;
+ Method method;
+ try {
+ method = Reflections.findMethod(specType, "create", Class.class);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalStateException("Unsupported creation of spec type "+specType+"; it must have a public static create(Class) method", e);
+ }
+ try {
+ if (loadedItem.getJavaType()!=null) {
+ SpecT specT = (SpecT) method.invoke(null, loadedItem.loadJavaClass(mgmt));
+ spec = specT;
+ }
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalStateException("Error creating "+specType+" "+loadedItem.getJavaType()+": "+e, e);
+ }
+
+ if (spec==null)
+ throw new IllegalStateException("Unknown how to create instance of "+this);
+
+ return spec;
+ }
+
+ private <T, SpecT> SpecT createSpec(String optionalId, CatalogItemType ciType, DeploymentPlan plan, BrooklynClassLoadingContext loader) {
+ Preconditions.checkNotNull(ciType, "catalog item type for "+plan);
+ switch (ciType) {
+ case TEMPLATE:
+ case ENTITY:
+ return createEntitySpec(optionalId, plan, loader);
+ case LOCATION: return createLocationSpec(plan, loader);
+ case POLICY: return createPolicySpec(optionalId, plan, loader);
+ }
+ throw new IllegalStateException("Unknown CI Type "+ciType+" for "+plan);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T, SpecT> SpecT createEntitySpec(String symbolicName, DeploymentPlan plan, BrooklynClassLoadingContext loader) {
+ CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+
+ // TODO should not register new AT each time we instantiate from the same plan; use some kind of cache
+ AssemblyTemplate at;
+ BrooklynLoaderTracker.setLoader(loader);
+ try {
+ at = camp.pdp().registerDeploymentPlan(plan);
+ } finally {
+ BrooklynLoaderTracker.unsetLoader(loader);
+ }
+
+ try {
+ AssemblyTemplateInstantiator instantiator = at.getInstantiator().newInstance();
+ if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+ return (SpecT) ((AssemblyTemplateSpecInstantiator)instantiator).createNestedSpec(at, camp, loader,
+ getInitialEncounteredSymbol(symbolicName));
+ }
+ throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ private MutableSet<String> getInitialEncounteredSymbol(String symbolicName) {
+ return symbolicName==null ? MutableSet.<String>of() : MutableSet.of(symbolicName);
+ }
+
+ private <T, SpecT> SpecT createPolicySpec(String symbolicName, DeploymentPlan plan, BrooklynClassLoadingContext loader) {
+ return createPolicySpec(plan, loader, getInitialEncounteredSymbol(symbolicName));
+ }
+
+ private <T, SpecT> SpecT createPolicySpec(DeploymentPlan plan, BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) {
+ //Would ideally re-use io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityDecorationResolver.PolicySpecResolver
+ //but it is CAMP specific and there is no easy way to get hold of it.
+ Object policies = checkNotNull(plan.getCustomAttributes().get(POLICIES_KEY), "policy config");
+ if (!(policies instanceof Iterable<?>)) {
+ throw new IllegalStateException("The value of " + POLICIES_KEY + " must be an Iterable.");
+ }
+
+ Object policy = Iterables.getOnlyElement((Iterable<?>)policies);
+
+ return createPolicySpec(loader, policy, encounteredCatalogTypes);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T, SpecT> SpecT createPolicySpec(BrooklynClassLoadingContext loader, Object policy, Set<String> encounteredCatalogTypes) {
+ Map<String, Object> itemMap;
+ if (policy instanceof String) {
+ itemMap = ImmutableMap.<String, Object>of("type", policy);
+ } else if (policy instanceof Map) {
+ itemMap = (Map<String, Object>) policy;
+ } else {
+ throw new IllegalStateException("Policy expected to be string or map. Unsupported object type " + policy.getClass().getName() + " (" + policy.toString() + ")");
+ }
+
+ String versionedId = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "policy_type", "policyType", "type"), "policy type");
+ PolicySpec<? extends Policy> spec;
+ CatalogItem<?, ?> policyItem = CatalogUtils.getCatalogItemOptionalVersion(mgmt, versionedId);
+ if (policyItem != null && !encounteredCatalogTypes.contains(policyItem.getSymbolicName())) {
+ if (policyItem.getCatalogItemType() != CatalogItemType.POLICY) {
+ throw new IllegalStateException("Non-policy catalog item in policy context: " + policyItem);
+ }
+ //TODO re-use createSpec
+ BrooklynClassLoadingContext itemLoader = CatalogUtils.newClassLoadingContext(mgmt, policyItem);
+ if (policyItem.getPlanYaml() != null) {
+ DeploymentPlan plan = makePlanFromYaml(policyItem.getPlanYaml());
+ encounteredCatalogTypes.add(policyItem.getSymbolicName());
+ return createPolicySpec(plan, itemLoader, encounteredCatalogTypes);
+ } else if (policyItem.getJavaType() != null) {
+ spec = PolicySpec.create((Class<Policy>)itemLoader.loadClass(policyItem.getJavaType()));
+ } else {
+ throw new IllegalStateException("Invalid policy item - neither yaml nor javaType: " + policyItem);
+ }
+ } else {
+ spec = PolicySpec.create(loader.loadClass(versionedId, Policy.class));
+ }
+ Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config");
+ if (brooklynConfig != null) {
+ spec.configure(brooklynConfig);
+ }
+ return (SpecT) spec;
+ }
+
+ private <T, SpecT> SpecT createLocationSpec(DeploymentPlan plan, BrooklynClassLoadingContext loader) {
+ // See #createPolicySpec; this impl is modeled on that.
+ // spec.catalogItemId is set by caller
+ Object locations = checkNotNull(plan.getCustomAttributes().get(LOCATIONS_KEY), "location config");
+ if (!(locations instanceof Iterable<?>)) {
+ throw new IllegalStateException("The value of " + LOCATIONS_KEY + " must be an Iterable.");
+ }
+
+ Object location = Iterables.getOnlyElement((Iterable<?>)locations);
+
+ return createLocationSpec(loader, location);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T, SpecT> SpecT createLocationSpec(BrooklynClassLoadingContext loader, Object location) {
+ Map<String, Object> itemMap;
+ if (location instanceof String) {
+ itemMap = ImmutableMap.<String, Object>of("type", location);
+ } else if (location instanceof Map) {
+ itemMap = (Map<String, Object>) location;
+ } else {
+ throw new IllegalStateException("Location expected to be string or map. Unsupported object type " + location.getClass().getName() + " (" + location.toString() + ")");
+ }
+
+ String type = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "location_type", "locationType", "type"), "location type");
+ Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config");
+ Maybe<Class<? extends Location>> javaClass = loader.tryLoadClass(type, Location.class);
+ if (javaClass.isPresent()) {
+ LocationSpec<?> spec = LocationSpec.create(javaClass.get());
+ if (brooklynConfig != null) {
+ spec.configure(brooklynConfig);
+ }
+ return (SpecT) spec;
+ } else {
+ Maybe<Location> loc = mgmt.getLocationRegistry().resolve(type, false, brooklynConfig);
+ if (loc.isPresent()) {
+ // TODO extensions?
+ Map<String, Object> locConfig = ((ConfigurationSupportInternal)loc.get().config()).getBag().getAllConfig();
+ Class<? extends Location> locType = loc.get().getClass();
+ Set<Object> locTags = loc.get().tags().getTags();
+ String locDisplayName = loc.get().getDisplayName();
+ return (SpecT) LocationSpec.create(locType)
+ .configure(locConfig)
+ .displayName(locDisplayName)
+ .tags(locTags);
+ } else {
+ throw new IllegalStateException("No class or resolver found for location type "+type);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
+ @Deprecated
+ public <T,SpecT> Class<? extends T> loadClass(CatalogItem<T,SpecT> item) {
+ if (log.isDebugEnabled())
+ log.debug("Loading class for catalog item " + item);
+ checkNotNull(item);
+ CatalogItemDo<?,?> loadedItem = getCatalogItemDo(item.getSymbolicName(), item.getVersion());
+ if (loadedItem==null) throw new NoSuchElementException("Unable to load '"+item.getId()+"' to instantiate it");
+ return (Class<? extends T>) loadedItem.getJavaClass();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
+ @Deprecated
+ public <T> Class<? extends T> loadClassByType(String typeName, Class<T> typeClass) {
+ final CatalogItem<?,?> resultI = getCatalogItemForType(typeName);
+
+ if (resultI == null) {
+ throw new NoSuchElementException("Unable to find catalog item for type "+typeName);
+ }
+
+ return (Class<? extends T>) loadClass(resultI);
+ }
+
+ @Deprecated /** @deprecated since 0.7.0 only used by other deprecated items */
+ private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(CatalogItem<T,SpecT> item) {
+ while (item instanceof CatalogItemDo) item = ((CatalogItemDo<T,SpecT>)item).itemDto;
+ if (item==null) return null;
+ if (item instanceof CatalogItemDtoAbstract) return (CatalogItemDtoAbstract<T,SpecT>) item;
+ throw new IllegalStateException("Cannot unwrap catalog item '"+item+"' (type "+item.getClass()+") to restore DTO");
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> Maybe<T> getFirstAs(Map<?,?> map, Class<T> type, String firstKey, String ...otherKeys) {
+ if (map==null) return Maybe.absent("No map available");
+ String foundKey = null;
+ Object value = null;
+ if (map.containsKey(firstKey)) foundKey = firstKey;
+ else for (String key: otherKeys) {
+ if (map.containsKey(key)) {
+ foundKey = key;
+ break;
+ }
+ }
+ if (foundKey==null) return Maybe.absent("Missing entry '"+firstKey+"'");
+ value = map.get(foundKey);
+ if (type.equals(String.class) && Number.class.isInstance(value)) value = value.toString();
+ if (!type.isInstance(value))
+ throw new IllegalArgumentException("Entry for '"+firstKey+"' should be of type "+type+", not "+value.getClass());
+ return Maybe.of((T)value);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private Maybe<Map<?,?>> getFirstAsMap(Map<?,?> map, String firstKey, String ...otherKeys) {
+ return (Maybe<Map<?,?>>)(Maybe) getFirstAs(map, Map.class, firstKey, otherKeys);
+ }
+
+ private List<CatalogItemDtoAbstract<?,?>> collectCatalogItems(String yaml) {
+ Map<?,?> itemDef = Yamls.getAs(Yamls.parseAll(yaml), Map.class);
+ Map<?,?> catalogMetadata = getFirstAsMap(itemDef, "brooklyn.catalog").orNull();
+ if (catalogMetadata==null)
+ log.warn("No `brooklyn.catalog` supplied in catalog request; using legacy mode for "+itemDef);
+ catalogMetadata = MutableMap.copyOf(catalogMetadata);
+
+ List<CatalogItemDtoAbstract<?, ?>> result = MutableList.of();
+
+ collectCatalogItems(Yamls.getTextOfYamlAtPath(yaml, "brooklyn.catalog").getMatchedYamlTextOrWarn(),
+ catalogMetadata, result, null);
+
+ itemDef.remove("brooklyn.catalog");
+ catalogMetadata.remove("item");
+ catalogMetadata.remove("items");
+ if (!itemDef.isEmpty()) {
+ log.debug("Reading brooklyn.catalog peer keys as item ('top-level syntax')");
+ Map<String,?> rootItem = MutableMap.of("item", itemDef);
+ String rootItemYaml = yaml;
+ YamlExtract yamlExtract = Yamls.getTextOfYamlAtPath(rootItemYaml, "brooklyn.catalog");
+ String match = yamlExtract.withOriginalIndentation(true).withKeyIncluded(true).getMatchedYamlTextOrWarn();
+ if (match!=null) {
+ if (rootItemYaml.startsWith(match)) rootItemYaml = Strings.removeFromStart(rootItemYaml, match);
+ else rootItemYaml = Strings.replaceAllNonRegex(rootItemYaml, "\n"+match, "");
+ }
+ collectCatalogItems("item:\n"+makeAsIndentedObject(rootItemYaml), rootItem, result, catalogMetadata);
+ }
+
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void collectCatalogItems(String sourceYaml, Map<?,?> itemMetadata, List<CatalogItemDtoAbstract<?, ?>> result, Map<?,?> parentMetadata) {
+
+ if (sourceYaml==null) sourceYaml = new Yaml().dump(itemMetadata);
+
+ Map<Object,Object> catalogMetadata = MutableMap.builder().putAll(parentMetadata).putAll(itemMetadata).build();
+
+ // brooklyn.libraries we treat specially, to append the list, with the child's list preferred in classloading order
+ // `libraries` is supported in some places as a legacy syntax; it should always be `brooklyn.libraries` for new apps
+ // TODO in 0.8.0 require brooklyn.libraries, don't allow "libraries" on its own
+ List<?> librariesNew = MutableList.copyOf(getFirstAs(itemMetadata, List.class, "brooklyn.libraries", "libraries").orNull());
+ Collection<CatalogBundle> libraryBundlesNew = CatalogItemDtoAbstract.parseLibraries(librariesNew);
+
+ List<?> librariesCombined = MutableList.copyOf(librariesNew)
+ .appendAll(getFirstAs(parentMetadata, List.class, "brooklyn.libraries", "libraries").orNull());
+ if (!librariesCombined.isEmpty())
+ catalogMetadata.put("brooklyn.libraries", librariesCombined);
+ Collection<CatalogBundle> libraryBundles = CatalogItemDtoAbstract.parseLibraries(librariesCombined);
+
+ // TODO as this may take a while if downloading, the REST call should be async
+ // (this load is required for the scan below and I think also for yaml resolution)
+ CatalogUtils.installLibraries(mgmt, libraryBundlesNew);
+
+ Boolean scanJavaAnnotations = getFirstAs(itemMetadata, Boolean.class, "scanJavaAnnotations", "scan_java_annotations").orNull();
+ if (scanJavaAnnotations==null || !scanJavaAnnotations) {
+ // don't scan
+ } else {
+ // scan for annotations: if libraries here, scan them; if inherited libraries error; else scan classpath
+ if (!libraryBundlesNew.isEmpty()) {
+ result.addAll(scanAnnotationsFromBundles(mgmt, libraryBundlesNew, catalogMetadata));
+ } else if (libraryBundles.isEmpty()) {
+ result.addAll(scanAnnotationsFromLocal(mgmt, catalogMetadata));
+ } else {
+ throw new IllegalStateException("Cannot scan catalog node no local bundles, and with inherited bundles we will not scan the classpath");
+ }
+ }
+
+ Object items = catalogMetadata.remove("items");
+ Object item = catalogMetadata.remove("item");
+
+ if (items!=null) {
+ int count = 0;
+ for (Map<?,?> i: ((List<Map<?,?>>)items)) {
+ collectCatalogItems(Yamls.getTextOfYamlAtPath(sourceYaml, "items", count).getMatchedYamlTextOrWarn(),
+ i, result, catalogMetadata);
+ count++;
+ }
+ }
+
+ if (item==null) return;
+
+ // now look at the actual item, first correcting the sourceYaml and interpreting the catalog metadata
+ String itemYaml = Yamls.getTextOfYamlAtPath(sourceYaml, "item").getMatchedYamlTextOrWarn();
+ if (itemYaml!=null) sourceYaml = itemYaml;
+ else sourceYaml = new Yaml().dump(item);
+
+ CatalogItemType itemType = TypeCoercions.coerce(getFirstAs(catalogMetadata, Object.class, "itemType", "item_type").orNull(), CatalogItemType.class);
+ BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, "<load>:0", libraryBundles);
+
+ String id = getFirstAs(catalogMetadata, String.class, "id").orNull();
+ String version = getFirstAs(catalogMetadata, String.class, "version").orNull();
+ String symbolicName = getFirstAs(catalogMetadata, String.class, "symbolicName").orNull();
+ String displayName = getFirstAs(catalogMetadata, String.class, "displayName").orNull();
+ String name = getFirstAs(catalogMetadata, String.class, "name").orNull();
+
+ if ((Strings.isNonBlank(id) || Strings.isNonBlank(symbolicName)) &&
+ Strings.isNonBlank(displayName) &&
+ Strings.isNonBlank(name) && !name.equals(displayName)) {
+ log.warn("Name property will be ignored due to the existence of displayName and at least one of id, symbolicName");
+ }
+
+ PlanInterpreterGuessingType planInterpreter = new PlanInterpreterGuessingType(null, item, sourceYaml, itemType, loader, result).reconstruct();
+ if (!planInterpreter.isResolved()) {
+ throw Exceptions.create("Could not resolve item "
+ + (Strings.isNonBlank(id) ? id : Strings.isNonBlank(symbolicName) ? symbolicName : Strings.isNonBlank(name) ? name : "<no-name>")
+ + ":\n"+sourceYaml, planInterpreter.getErrors());
+ }
+ itemType = planInterpreter.getCatalogItemType();
+ Map<?, ?> itemAsMap = planInterpreter.getItem();
+ // the "plan yaml" includes the services: ... or brooklyn.policies: ... outer key,
+ // as opposed to the rawer { type: xxx } map without that outer key which is valid as item input
+ // TODO this plan yaml is needed for subsequent reconstruction; would be nicer if it weren't!
+
+ // if symname not set, infer from: id, then name, then item id, then item name
+ if (Strings.isBlank(symbolicName)) {
+ if (Strings.isNonBlank(id)) {
+ if (CatalogUtils.looksLikeVersionedId(id)) {
+ symbolicName = CatalogUtils.getIdFromVersionedId(id);
+ } else {
+ symbolicName = id;
+ }
+ } else if (Strings.isNonBlank(name)) {
+ if (CatalogUtils.looksLikeVersionedId(name)) {
+ symbolicName = CatalogUtils.getIdFromVersionedId(name);
+ } else {
+ symbolicName = name;
+ }
+ } else {
+ symbolicName = setFromItemIfUnset(symbolicName, itemAsMap, "id");
+ symbolicName = setFromItemIfUnset(symbolicName, itemAsMap, "name");
+ if (Strings.isBlank(symbolicName)) {
+ log.error("Can't infer catalog item symbolicName from the following plan:\n" + sourceYaml);
+ throw new IllegalStateException("Can't infer catalog item symbolicName from catalog item metadata");
+ }
+ }
+ }
+
+ // if version not set, infer from: id, then from name, then item version
+ if (CatalogUtils.looksLikeVersionedId(id)) {
+ String versionFromId = CatalogUtils.getVersionFromVersionedId(id);
+ if (versionFromId != null && Strings.isNonBlank(version) && !versionFromId.equals(version)) {
+ throw new IllegalArgumentException("Discrepency between version set in id " + versionFromId + " and version property " + version);
+ }
+ version = versionFromId;
+ }
+ if (Strings.isBlank(version)) {
+ if (CatalogUtils.looksLikeVersionedId(name)) {
+ version = CatalogUtils.getVersionFromVersionedId(name);
+ } else if (Strings.isBlank(version)) {
+ version = setFromItemIfUnset(version, itemAsMap, "version");
+ if (version==null) {
+ log.warn("No version specified for catalog item " + symbolicName + ". Using default value.");
+ version = null;
+ }
+ }
+ }
+
+ // if not set, ID can come from symname:version, failing that, from the plan.id, failing that from the sym name
+ if (Strings.isBlank(id)) {
+ // let ID be inferred, especially from name, to support style where only "name" is specified, with inline version
+ if (Strings.isNonBlank(symbolicName) && Strings.isNonBlank(version)) {
+ id = symbolicName + ":" + version;
+ }
+ id = setFromItemIfUnset(id, itemAsMap, "id");
+ if (Strings.isBlank(id)) {
+ if (Strings.isNonBlank(symbolicName)) {
+ id = symbolicName;
+ } else {
+ log.error("Can't infer catalog item id from the following plan:\n" + sourceYaml);
+ throw new IllegalStateException("Can't infer catalog item id from catalog item metadata");
+ }
+ }
+ }
+
+ if (Strings.isBlank(displayName)) {
+ if (Strings.isNonBlank(name)) displayName = name;
+ displayName = setFromItemIfUnset(displayName, itemAsMap, "name");
+ }
+
+ String description = getFirstAs(catalogMetadata, String.class, "description").orNull();
+ description = setFromItemIfUnset(description, itemAsMap, "description");
+
+ // icon.url is discouraged, but kept for legacy compatibility; should deprecate this
+ final String catalogIconUrl = getFirstAs(catalogMetadata, String.class, "iconUrl", "icon_url", "icon.url").orNull();
+
+ final String deprecated = getFirstAs(catalogMetadata, String.class, "deprecated").orNull();
+ final Boolean catalogDeprecated = Boolean.valueOf(deprecated);
+
+ // run again now that we know the ID
+ planInterpreter = new PlanInterpreterGuessingType(id, item, sourceYaml, itemType, loader, result).reconstruct();
+ if (!planInterpreter.isResolved()) {
+ throw new IllegalStateException("Could not resolve plan once id and itemType are known (recursive reference?): "+sourceYaml);
+ }
+ String sourcePlanYaml = planInterpreter.getPlanYaml();
+
+ CatalogItemDtoAbstract<?, ?> dto = createItemBuilder(itemType, symbolicName, version)
+ .libraries(libraryBundles)
+ .displayName(displayName)
+ .description(description)
+ .deprecated(catalogDeprecated)
+ .iconUrl(catalogIconUrl)
+ .plan(sourcePlanYaml)
+ .build();
+
+ dto.setManagementContext((ManagementContextInternal) mgmt);
+ result.add(dto);
+ }
+
+ private String setFromItemIfUnset(String oldValue, Map<?,?> item, String fieldAttr) {
+ if (Strings.isNonBlank(oldValue)) return oldValue;
+ if (item!=null) {
+ Object newValue = item.get(fieldAttr);
+ if (newValue instanceof String && Strings.isNonBlank((String)newValue))
+ return (String)newValue;
+ }
+ return oldValue;
+ }
+
+ private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsFromLocal(ManagementContext mgmt, Map<Object, Object> catalogMetadata) {
+ CatalogDto dto = CatalogDto.newNamedInstance("Local Scanned Catalog", "All annotated Brooklyn entities detected in the classpath", "scanning-local-classpath");
+ return scanAnnotationsInternal(mgmt, new CatalogDo(dto), catalogMetadata);
+ }
+
+ private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsFromBundles(ManagementContext mgmt, Collection<CatalogBundle> libraries, Map<Object, Object> catalogMetadata) {
+ CatalogDto dto = CatalogDto.newNamedInstance("Bundles Scanned Catalog", "All annotated Brooklyn entities detected in bundles", "scanning-bundles-classpath-"+libraries.hashCode());
+ List<String> urls = MutableList.of();
+ for (CatalogBundle b: libraries) {
+ // TODO currently does not support pre-installed bundles identified by name:version
+ // (ie where URL not supplied)
+ if (Strings.isNonBlank(b.getUrl())) {
+ urls.add(b.getUrl());
+ }
+ }
+
+ if (urls.isEmpty()) {
+ log.warn("No bundles to scan: scanJavaAnnotations currently only applies to OSGi bundles provided by URL");
+ return MutableList.of();
+ }
+
+ CatalogDo subCatalog = new CatalogDo(dto);
+ subCatalog.addToClasspath(urls.toArray(new String[0]));
+ return scanAnnotationsInternal(mgmt, subCatalog, catalogMetadata);
+ }
+
+ private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsInternal(ManagementContext mgmt, CatalogDo subCatalog, Map<Object, Object> catalogMetadata) {
+ // TODO this does java-scanning only;
+ // the call when scanning bundles should use the CatalogItem instead and use OSGi when loading for scanning
+ // (or another scanning mechanism). see comments on CatalogClasspathDo.load
+ subCatalog.mgmt = mgmt;
+ subCatalog.setClasspathScanForEntities(CatalogScanningModes.ANNOTATIONS);
+ subCatalog.load();
+ // TODO apply metadata? (extract YAML from the items returned)
+ // also see doc .../catalog/index.md which says we might not apply metadata
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Collection<CatalogItemDtoAbstract<?, ?>> result = (Collection<CatalogItemDtoAbstract<?, ?>>)(Collection)Collections2.transform(
+ (Collection<CatalogItemDo<Object,Object>>)(Collection)subCatalog.getIdCache().values(),
+ itemDoToDtoAddingSelectedMetadataDuringScan(catalogMetadata));
+ return result;
+ }
+
+ private class PlanInterpreterGuessingType {
+
+ final String id;
+ final Map<?,?> item;
+ final String itemYaml;
+ final BrooklynClassLoadingContext loader;
+ final List<CatalogItemDtoAbstract<?, ?>> itemsDefinedSoFar;
+
+ CatalogItemType catalogItemType;
+ String planYaml;
+ @SuppressWarnings("unused")
+ DeploymentPlan plan;
+ AbstractBrooklynObjectSpec<?,?> spec;
+ boolean resolved = false;
+ List<Exception> errors = MutableList.of();
+
+ public PlanInterpreterGuessingType(@Nullable String id, Object item, String itemYaml, @Nullable CatalogItemType optionalCiType,
+ BrooklynClassLoadingContext loader, List<CatalogItemDtoAbstract<?,?>> itemsDefinedSoFar) {
+ // ID is useful to prevent recursive references (currently for entities only)
+ this.id = id;
+
+ if (item instanceof String) {
+ // if just a string supplied, wrap as map
+ this.item = MutableMap.of("type", item);
+ this.itemYaml = "type:\n"+makeAsIndentedObject(itemYaml);
+ } else {
+ this.item = (Map<?,?>)item;
+ this.itemYaml = itemYaml;
+ }
+ this.catalogItemType = optionalCiType;
+ this.loader = loader;
+ this.itemsDefinedSoFar = itemsDefinedSoFar;
+ }
+
+ public PlanInterpreterGuessingType reconstruct() {
+ if (catalogItemType==CatalogItemType.TEMPLATE) {
+ // template *must* be explicitly defined, and if so, none of the other calls apply
+ attemptType(null, CatalogItemType.TEMPLATE);
+
+ } else {
+ attemptType(null, CatalogItemType.ENTITY);
+
+ attemptType("services", CatalogItemType.ENTITY);
+ attemptType(POLICIES_KEY, CatalogItemType.POLICY);
+ attemptType(LOCATIONS_KEY, CatalogItemType.LOCATION);
+ }
+
+ if (!resolved && catalogItemType==CatalogItemType.TEMPLATE) {
+ // anything goes, for an explicit template, because we can't easily recurse into the types
+ planYaml = itemYaml;
+ resolved = true;
+ }
+
+ return this;
+ }
+
+ public boolean isResolved() { return resolved; }
+
+ /** Returns potentially useful errors encountered while guessing types.
+ * May only be available where the type is known. */
+ public List<Exception> getErrors() {
+ return errors;
+ }
+
+ public CatalogItemType getCatalogItemType() {
+ return catalogItemType;
+ }
+
+ public String getPlanYaml() {
+ return planYaml;
+ }
+
+ private boolean attemptType(String key, CatalogItemType candidateCiType) {
+ if (resolved) return false;
+ if (catalogItemType!=null && catalogItemType!=candidateCiType) return false;
+
+ final String candidateYaml;
+ if (key==null) candidateYaml = itemYaml;
+ else {
+ if (item.containsKey(key))
+ candidateYaml = itemYaml;
+ else
+ candidateYaml = key + ":\n" + makeAsIndentedList(itemYaml);
+ }
+ // first look in collected items, if a key is given
+ String type = (String) item.get("type");
+ String version = null;
+ if (CatalogUtils.looksLikeVersionedId(type)) {
+ version = CatalogUtils.getVersionFromVersionedId(type);
+ type = CatalogUtils.getIdFromVersionedId(type);
+ }
+ if (type!=null && key!=null) {
+ for (CatalogItemDtoAbstract<?,?> candidate: itemsDefinedSoFar) {
+ if (candidateCiType == candidate.getCatalogItemType() &&
+ (type.equals(candidate.getSymbolicName()) || type.equals(candidate.getId()))) {
+ if (version==null || version.equals(candidate.getVersion())) {
+ // matched - exit
+ catalogItemType = candidateCiType;
+ planYaml = candidateYaml;
+ resolved = true;
+ return true;
+ }
+ }
+ }
+ }
+
+ // then try parsing plan - this will use loader
+ try {
+ DeploymentPlan candidatePlan = makePlanFromYaml(candidateYaml);
+ spec = createSpec(id, candidateCiType, candidatePlan, loader);
+ if (spec!=null) {
+ catalogItemType = candidateCiType;
+ plan = candidatePlan;
+ planYaml = candidateYaml;
+ resolved = true;
+ }
+ return true;
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ // record the error if we have reason to expect this guess to succeed
+ if (item.containsKey("services") && (candidateCiType==CatalogItemType.ENTITY || candidateCiType==CatalogItemType.TEMPLATE)) {
+ // explicit services supplied, so plan should have been parseable for an entity or a a service
+ errors.add(e);
+ } else if (catalogItemType!=null && key!=null) {
+ // explicit itemType supplied, so plan should be parseable in the cases where we're given a key
+ // (when we're not given a key, the previous block should apply)
+ errors.add(e);
+ } else {
+ // all other cases, the error is probably due to us not getting the type right, ignore it
+ if (log.isTraceEnabled())
+ log.trace("Guessing type of plan, it looks like it isn't "+candidateCiType+"/"+key+": "+e);
+ }
+ }
+
+ // finally try parsing a cut-down plan, in case there is a nested reference to a newly defined catalog item
+ if (type!=null && key!=null) {
+ try {
+ String cutDownYaml = key + ":\n" + makeAsIndentedList("type: "+type);
+ DeploymentPlan candidatePlan = makePlanFromYaml(cutDownYaml);
+ Object cutdownSpec = createSpec(id, candidateCiType, candidatePlan, loader);
+ if (cutdownSpec!=null) {
+ catalogItemType = candidateCiType;
+ planYaml = candidateYaml;
+ resolved = true;
+ }
+ return true;
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ }
+ }
+
+ return false;
+ }
+ public Map<?,?> getItem() {
+ return item;
+ }
+ }
+
+ private String makeAsIndentedList(String yaml) {
+ String[] lines = yaml.split("\n");
+ lines[0] = "- "+lines[0];
+ for (int i=1; i<lines.length; i++)
+ lines[i] = " " + lines[i];
+ return Strings.join(lines, "\n");
+ }
+
+ private String makeAsIndentedObject(String yaml) {
+ String[] lines = yaml.split("\n");
+ for (int i=0; i<lines.length; i++)
+ lines[i] = " " + lines[i];
+ return Strings.join(lines, "\n");
+ }
+
+ private CatalogItemBuilder<?> createItemBuilder(CatalogItemType itemType, String itemId, String version) {
+ Preconditions.checkNotNull(itemType, "itemType required");
+ switch (itemType) {
+ case ENTITY: return CatalogItemBuilder.newEntity(itemId, version);
+ case TEMPLATE: return CatalogItemBuilder.newTemplate(itemId, version);
+ case POLICY: return CatalogItemBuilder.newPolicy(itemId, version);
+ case LOCATION: return CatalogItemBuilder.newLocation(itemId, version);
+ }
+ throw new IllegalStateException("Unexpected itemType: "+itemType);
+ }
+
+ // these kept as their logic may prove useful; Apr 2015
+// private boolean isApplicationSpec(EntitySpec<?> spec) {
+// return !Boolean.TRUE.equals(spec.getConfig().get(EntityManagementUtils.WRAPPER_APP_MARKER));
+// }
+//
+// private boolean isEntityPlan(DeploymentPlan plan) {
+// return plan!=null && !plan.getServices().isEmpty() || !plan.getArtifacts().isEmpty();
+// }
+//
+// private boolean isPolicyPlan(DeploymentPlan plan) {
+// return !isEntityPlan(plan) && plan.getCustomAttributes().containsKey(POLICIES_KEY);
+// }
+//
+// private boolean isLocationPlan(DeploymentPlan plan) {
+// return !isEntityPlan(plan) && plan.getCustomAttributes().containsKey(LOCATIONS_KEY);
+// }
+
+ private DeploymentPlan makePlanFromYaml(String yaml) {
+ CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+ return camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
+ }
+
+ //------------------------
+
+ @Override
+ public CatalogItem<?,?> addItem(String yaml) {
+ return addItem(yaml, false);
+ }
+
+ @Override
+ public List<? extends CatalogItem<?,?>> addItems(String yaml) {
+ return addItems(yaml, false);
+ }
+
+ @Override
+ public CatalogItem<?,?> addItem(String yaml, boolean forceUpdate) {
+ return Iterables.getOnlyElement(addItems(yaml, forceUpdate));
+ }
+
+ @Override
+ public List<? extends CatalogItem<?,?>> addItems(String yaml, boolean forceUpdate) {
+ log.debug("Adding manual catalog item to "+mgmt+": "+yaml);
+ checkNotNull(yaml, "yaml");
+ List<CatalogItemDtoAbstract<?, ?>> result = collectCatalogItems(yaml);
+ // do this at the end for atomic updates; if there are intra-yaml references, we handle them specially
+ for (CatalogItemDtoAbstract<?, ?> item: result) {
+ addItemDto(item, forceUpdate);
+ }
+ return result;
+ }
+
+ private CatalogItem<?,?> addItemDto(CatalogItemDtoAbstract<?, ?> itemDto, boolean forceUpdate) {
+ CatalogItem<?, ?> existingDto = checkItemAllowedAndIfSoReturnAnyDuplicate(itemDto, true, forceUpdate);
+ if (existingDto!=null) {
+ // it's a duplicate, and not forced, just return it
+ log.trace("Using existing duplicate for catalog item {}", itemDto.getId());
+ return existingDto;
+ }
+
+ if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
+ manualAdditionsCatalog.addEntry(itemDto);
+
+ // Ensure the cache is populated and it is persisted by the management context
+ getCatalog().addEntry(itemDto);
+
+ // Request that the management context persist the item.
+ if (log.isTraceEnabled()) {
+ log.trace("Scheduling item for persistence addition: {}", itemDto.getId());
+ }
+ if (itemDto.getCatalogItemType() == CatalogItemType.LOCATION) {
+ @SuppressWarnings("unchecked")
+ CatalogItem<Location,LocationSpec<?>> locationItem = (CatalogItem<Location, LocationSpec<?>>) itemDto;
+ ((BasicLocationRegistry)mgmt.getLocationRegistry()).updateDefinedLocation(locationItem);
+ }
+ mgmt.getRebindManager().getChangeListener().onManaged(itemDto);
+
+ return itemDto;
+ }
+
+ /** returns item DTO if item is an allowed duplicate, or null if it should be added (there is no duplicate),
+ * throwing if item cannot be added */
+ private CatalogItem<?, ?> checkItemAllowedAndIfSoReturnAnyDuplicate(CatalogItem<?,?> itemDto, boolean allowDuplicates, boolean forceUpdate) {
+ if (forceUpdate) return null;
+ CatalogItemDo<?, ?> existingItem = getCatalogItemDo(itemDto.getSymbolicName(), itemDto.getVersion());
+ if (existingItem == null) return null;
+ // check if they are equal
+ CatalogItem<?, ?> existingDto = existingItem.getDto();
+ if (existingDto.equals(itemDto)) {
+ if (allowDuplicates) return existingItem;
+ throw new IllegalStateException("Updating existing catalog entries, even with the same content, is forbidden: " +
+ itemDto.getSymbolicName() + ":" + itemDto.getVersion() + ". Use forceUpdate argument to override.");
+ } else {
+ throw new IllegalStateException("Updating existing catalog entries is forbidden: " +
+ itemDto.getSymbolicName() + ":" + itemDto.getVersion() + ". Use forceUpdate argument to override.");
+ }
+ }
+
+ @Override @Deprecated /** @deprecated see super */
+ public void addItem(CatalogItem<?,?> item) {
+ //assume forceUpdate for backwards compatibility
+ log.debug("Adding manual catalog item to "+mgmt+": "+item);
+ checkNotNull(item, "item");
+ CatalogUtils.installLibraries(mgmt, item.getLibraries());
+ if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
+ manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item));
+ }
+
+ @Override @Deprecated /** @deprecated see super */
+ public CatalogItem<?,?> addItem(Class<?> type) {
+ //assume forceUpdate for backwards compatibility
+ log.debug("Adding manual catalog item to "+mgmt+": "+type);
+ checkNotNull(type, "type");
+ if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
+ manualAdditionsClasses.addClass(type);
+ return manualAdditionsCatalog.classpath.addCatalogEntry(type);
+ }
+
+ private synchronized void loadManualAdditionsCatalog() {
+ if (manualAdditionsCatalog!=null) return;
+ CatalogDto manualAdditionsCatalogDto = CatalogDto.newNamedInstance(
+ "Manual Catalog Additions", "User-additions to the catalog while Brooklyn is running, " +
+ "created "+Time.makeDateString(),
+ "manual-additions");
+ CatalogDo manualAdditionsCatalog = catalog.addCatalog(manualAdditionsCatalogDto);
+ if (manualAdditionsCatalog==null) {
+ // not hard to support, but slightly messy -- probably have to use ID's to retrieve the loaded instance
+ // for now block once, then retry
+ log.warn("Blocking until catalog is loaded before changing it");
+ boolean loaded = blockIfNotLoaded(Duration.TEN_SECONDS);
+ if (!loaded)
+ log.warn("Catalog still not loaded after delay; subsequent operations may fail");
+ manualAdditionsCatalog = catalog.addCatalog(manualAdditionsCatalogDto);
+ if (manualAdditionsCatalog==null) {
+ throw new UnsupportedOperationException("Catalogs cannot be added until the base catalog is loaded, and catalog is taking a while to load!");
+ }
+ }
+
+ log.debug("Creating manual additions catalog for "+mgmt+": "+manualAdditionsCatalog);
+ manualAdditionsClasses = new LoadedClassLoader();
+ ((AggregateClassLoader)manualAdditionsCatalog.classpath.getLocalClassLoader()).addFirst(manualAdditionsClasses);
+
+ // expose when we're all done
+ this.manualAdditionsCatalog = manualAdditionsCatalog;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems() {
+ if (!getCatalog().isLoaded()) {
+ // some callers use this to force the catalog to load (maybe when starting as hot_backup without a catalog ?)
+ log.debug("Forcing catalog load on access of catalog items");
+ load();
+ }
+ return ImmutableList.copyOf((Iterable)catalog.getIdCache().values());
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems(Predicate<? super CatalogItem<T,SpecT>> filter) {
+ Iterable<CatalogItemDo<T,SpecT>> filtered = Iterables.filter((Iterable)catalog.getIdCache().values(), (Predicate<CatalogItem<T,SpecT>>)(Predicate) filter);
+ return Iterables.transform(filtered, BasicBrooklynCatalog.<T,SpecT>itemDoToDto());
+ }
+
+ private static <T,SpecT> Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>> itemDoToDto() {
+ return new Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>>() {
+ @Override
+ public CatalogItem<T,SpecT> apply(@Nullable CatalogItemDo<T,SpecT> item) {
+ if (item==null) return null;
+ return item.getDto();
+ }
+ };
+ }
+
+ private static <T,SpecT> Function<CatalogItemDo<T, SpecT>, CatalogItem<T,SpecT>> itemDoToDtoAddingSelectedMetadataDuringScan(final Map<Object, Object> catalogMetadata) {
+ return new Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>>() {
+ @Override
+ public CatalogItem<T,SpecT> apply(@Nullable CatalogItemDo<T,SpecT> item) {
+ if (item==null) return null;
+ CatalogItemDtoAbstract<T, SpecT> dto = (CatalogItemDtoAbstract<T, SpecT>) item.getDto();
+
+ // when scanning we only allow version and libraries to be overwritten
+
+ String version = getFirstAs(catalogMetadata, String.class, "version").orNull();
+ if (Strings.isNonBlank(version)) dto.setVersion(version);
+
+ Object librariesCombined = catalogMetadata.get("brooklyn.libraries");
+ if (librariesCombined instanceof Collection) {
+ // will be set by scan -- slightly longwinded way to retrieve, but scanning for osgi needs an overhaul in any case
+ Collection<CatalogBundle> libraryBundles = CatalogItemDtoAbstract.parseLibraries((Collection<?>) librariesCombined);
+ dto.setLibraries(libraryBundles);
+ }
+ // replace java type with plan yaml -- needed for libraries / catalog item to be picked up,
+ // but probably useful to transition away from javaType altogether
+ dto.setSymbolicName(dto.getJavaType());
+ switch (dto.getCatalogItemType()) {
+ case TEMPLATE:
+ case ENTITY:
+ dto.setPlanYaml("services: [{ type: "+dto.getJavaType()+" }]");
+ break;
+ case POLICY:
+ dto.setPlanYaml(POLICIES_KEY + ": [{ type: "+dto.getJavaType()+" }]");
+ break;
+ case LOCATION:
+ dto.setPlanYaml(LOCATIONS_KEY + ": [{ type: "+dto.getJavaType()+" }]");
+ break;
+ }
+ dto.setJavaType(null);
+
+ return dto;
+ }
+ };
+ }
+
+ transient CatalogXmlSerializer serializer;
+
+ public String toXmlString() {
+ if (serializer==null) loadSerializer();
+ return serializer.toString(catalog.dto);
+ }
+
+ private synchronized void loadSerializer() {
+ if (serializer==null)
+ serializer = new CatalogXmlSerializer();
+ }
+
+ @Deprecated
+ public CatalogItem<?,?> getCatalogItemForType(String typeName) {
+ final CatalogItem<?,?> resultI;
+ final BrooklynCatalog catalog = mgmt.getCatalog();
+ if (CatalogUtils.looksLikeVersionedId(typeName)) {
+ //All catalog identifiers of the form xxxx:yyyy are composed of symbolicName+version.
+ //No javaType is allowed as part of the identifier.
+ resultI = CatalogUtils.getCatalogItemOptionalVersion(mgmt, typeName);
+ } else {
+ //Usually for catalog items with javaType (that is items from catalog.xml)
+ //the symbolicName and javaType match because symbolicName (was ID)
+ //is not specified explicitly. But could be the case that there is an item
+ //whose symbolicName is explicitly set to be different from the javaType.
+ //Note that in the XML the attribute is called registeredTypeName.
+ Iterable<CatalogItem<Object,Object>> resultL = catalog.getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(typeName)));
+ if (!Iterables.isEmpty(resultL)) {
+ //Push newer versions in front of the list (not that there should
+ //be more than one considering the items are coming from catalog.xml).
+ resultI = sortVersionsDesc(resultL).iterator().next();
+ if (log.isDebugEnabled() && Iterables.size(resultL)>1) {
+ log.debug("Found "+Iterables.size(resultL)+" matches in catalog for type "+typeName+"; returning the result with preferred version, "+resultI);
+ }
+ } else {
+ //As a last resort try searching for items with the same symbolicName supposedly
+ //different from the javaType.
+ resultI = catalog.getCatalogItem(typeName, BrooklynCatalog.DEFAULT_VERSION);
+ if (resultI != null) {
+ if (resultI.getJavaType() == null) {
+ //Catalog items scanned from the classpath (using reflection and annotations) now
+ //get yaml spec rather than a java type. Can't use those when creating apps from
+ //the legacy app spec format.
+ log.warn("Unable to find catalog item for type "+typeName +
+ ". There is an existing catalog item with ID " + resultI.getId() +
+ " but it doesn't define a class type.");
+ return null;
+ }
+ }
+ }
+ }
+ return resultI;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleConverter.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleConverter.java
new file mode 100644
index 0000000..79b39c3
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleConverter.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
+import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
+
+
+/**
+ * Convert old-style catalog.xml file formats to the latest version.
+ * The code is needed only during transition to the new version, can be removed after a while.
+ */
+@Deprecated
+public class CatalogBundleConverter implements Converter {
+
+ private ReflectionConverter delegateConverter;
+
+ public CatalogBundleConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
+ this.delegateConverter = new ReflectionConverter(mapper, reflectionProvider);
+ }
+
+ @Override
+ public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
+ return type == CatalogBundleDto.class;
+ }
+
+ @Override
+ public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
+ context.convertAnother(source, delegateConverter);
+ }
+
+ @Override
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ if (reader.hasMoreChildren()) {
+ return context.convertAnother(context.currentObject(), CatalogBundleDto.class, delegateConverter);
+ } else {
+ return new CatalogBundleDto(null, null, reader.getValue());
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleDto.java
new file mode 100644
index 0000000..60472ae
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleDto.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+
+public class CatalogBundleDto implements CatalogBundle {
+ private String symbolicName;
+ private String version;
+ private String url;
+
+ public CatalogBundleDto() {}
+
+ public CatalogBundleDto(String name, String version, String url) {
+ if (name == null && version == null) {
+ Preconditions.checkNotNull(url, "url to an OSGi bundle is required");
+ } else {
+ Preconditions.checkNotNull(name, "both name and version are required");
+ Preconditions.checkNotNull(version, "both name and version are required");
+ }
+
+ this.symbolicName = name;
+ this.version = version;
+ this.url = url;
+ }
+
+ @Override
+ public boolean isNamed() {
+ return symbolicName != null && version != null;
+ }
+
+ @Override
+ public String getSymbolicName() {
+ return symbolicName;
+ }
+
+ @Override
+ public String getVersion() {
+ return version;
+ }
+
+ @Override
+ public String getUrl() {
+ return url;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("symbolicName", symbolicName)
+ .add("version", version)
+ .add("url", url)
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(symbolicName, version, url);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ CatalogBundleDto other = (CatalogBundleDto) obj;
+ if (!Objects.equal(symbolicName, other.symbolicName)) return false;
+ if (!Objects.equal(version, other.version)) return false;
+ if (!Objects.equal(url, other.url)) return false;
+ return true;
+ }
+
+
+}
[27/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/catalog
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java
deleted file mode 100644
index 78c11ea..0000000
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.apache.brooklyn.api.catalog.BrooklynCatalog;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.core.management.internal.LocalManagementContext;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-
-import brooklyn.catalog.CatalogPredicates;
-import brooklyn.entity.basic.Entities;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
-
-public class CatalogVersioningTest {
- private LocalManagementContext managementContext;
- private BrooklynCatalog catalog;
-
- @BeforeMethod(alwaysRun = true)
- public void setUp() throws Exception {
- managementContext = LocalManagementContextForTests.newInstance();
- catalog = managementContext.getCatalog();
- }
-
- @AfterMethod(alwaysRun = true)
- public void tearDown() throws Exception {
- if (managementContext != null) Entities.destroyAll(managementContext);
- }
-
- @Test
- public void testParsingVersion() {
- assertVersionParsesAs("foo:1", "foo", "1");
- assertVersionParsesAs("foo", null, null);
- assertVersionParsesAs("foo:1.1", "foo", "1.1");
- assertVersionParsesAs("foo:1_SNAPSHOT", "foo", "1_SNAPSHOT");
- assertVersionParsesAs("foo:10.9.8_SNAPSHOT", "foo", "10.9.8_SNAPSHOT");
- assertVersionParsesAs("foo:bar", null, null);
- assertVersionParsesAs("chef:cookbook", null, null);
- assertVersionParsesAs("http://foo:8080", null, null);
- }
-
- private static void assertVersionParsesAs(String versionedId, String id, String version) {
- if (version==null) {
- Assert.assertFalse(CatalogUtils.looksLikeVersionedId(versionedId));
- } else {
- Assert.assertTrue(CatalogUtils.looksLikeVersionedId(versionedId));
- Assert.assertEquals(CatalogUtils.getIdFromVersionedId(versionedId), id);
- Assert.assertEquals(CatalogUtils.getVersionFromVersionedId(versionedId), version);
- }
- }
-
- @Test
- public void testAddVersioned() {
- String symbolicName = "sampleId";
- String version = "0.1.0";
- createCatalogItem(symbolicName, version);
- assertSingleCatalogItem(symbolicName, version);
- }
-
- @Test
- public void testAddSameVersionFails() {
- String symbolicName = "sampleId";
- String version = "0.1.0";
- createCatalogItem(symbolicName, version);
- createCatalogItem(symbolicName, version);
- //forced update assumed in the above call
- assertSingleCatalogItem(symbolicName, version);
- }
-
- @Test
- public void testGetLatest() {
- String symbolicName = "sampleId";
- String v1 = "0.1.0";
- String v2 = "0.2.0";
- createCatalogItem(symbolicName, v1);
- createCatalogItem(symbolicName, v2);
- CatalogItem<?, ?> item = catalog.getCatalogItem(symbolicName, BasicBrooklynCatalog.DEFAULT_VERSION);
- assertEquals(item.getSymbolicName(), symbolicName);
- assertEquals(item.getVersion(), v2);
- }
-
- @Test
- public void testGetLatestStable() {
- String symbolicName = "sampleId";
- String v1 = "0.1.0";
- String v2 = "0.2.0-SNAPSHOT";
- createCatalogItem(symbolicName, v1);
- createCatalogItem(symbolicName, v2);
- CatalogItem<?, ?> item = catalog.getCatalogItem(symbolicName, BasicBrooklynCatalog.DEFAULT_VERSION);
- assertEquals(item.getSymbolicName(), symbolicName);
- assertEquals(item.getVersion(), v1);
- }
-
- @Test
- public void testDelete() {
- String symbolicName = "sampleId";
- String version = "0.1.0";
- createCatalogItem(symbolicName, version);
- assertSingleCatalogItem(symbolicName, version);
- assertTrue(catalog.getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName))).iterator().hasNext());
- catalog.deleteCatalogItem(symbolicName, version);
- assertFalse(catalog.getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName))).iterator().hasNext());
- }
-
- @Test
- public void testList() {
- String symbolicName = "sampleId";
- String v1 = "0.1.0";
- String v2 = "0.2.0-SNAPSHOT";
- createCatalogItem(symbolicName, v1);
- createCatalogItem(symbolicName, v2);
- Iterable<CatalogItem<Object, Object>> items = catalog.getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName)));
- assertEquals(Iterables.size(items), 2);
- }
-
- @SuppressWarnings("deprecation")
- private void createCatalogItem(String symbolicName, String version) {
- catalog.addItem(CatalogItemBuilder.newEntity(symbolicName, version).
- plan("services:\n- type: brooklyn.entity.basic.BasicEntity")
- .build());
- }
-
- private void assertSingleCatalogItem(String symbolicName, String version) {
- Iterable<CatalogItem<Object, Object>> items = catalog.getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName)));
- CatalogItem<Object, Object> item = Iterables.getOnlyElement(items);
- assertEquals(item.getSymbolicName(), symbolicName);
- assertEquals(item.getVersion(), version);
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/catalog/internal/MyCatalogItems.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/MyCatalogItems.java b/core/src/test/java/brooklyn/catalog/internal/MyCatalogItems.java
deleted file mode 100644
index 44067ed..0000000
--- a/core/src/test/java/brooklyn/catalog/internal/MyCatalogItems.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import org.apache.brooklyn.api.catalog.Catalog;
-
-import brooklyn.entity.basic.AbstractApplication;
-import brooklyn.entity.basic.ApplicationBuilder;
-
-public class MyCatalogItems {
-
- @Catalog(description="Some silly app test")
- public static class MySillyAppTemplate extends AbstractApplication {
- }
-
- @Catalog(description="Some silly app builder test")
- public static class MySillyAppBuilderTemplate extends ApplicationBuilder {
- @Override protected void doBuild() {
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
index 41917d4..dc9d8fe 100644
--- a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
@@ -25,10 +25,10 @@ import org.testng.annotations.Test;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.catalog.internal.CatalogTestUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.osgi.OsgiVersionMoreEntityTest;
-import brooklyn.catalog.internal.CatalogTestUtils;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.entity.rebind.transformer.CompoundTransformer;
import brooklyn.util.collections.MutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
index 2b5cebf..3debe30 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
@@ -31,7 +31,6 @@ import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.catalog.internal.CatalogInitialization;
import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.ConfigKeys;
@@ -44,6 +43,7 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.TestResourceUnavailableException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
index f46df75..92383fc 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
@@ -40,12 +40,12 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogDto;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestEntity;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.internal.CatalogDto;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
@@ -88,7 +88,7 @@ public class RebindCatalogItemTest extends RebindTestFixtureWithApp {
protected LocalManagementContext createOrigManagementContext() {
BrooklynProperties properties = BrooklynProperties.Factory.newDefault();
properties.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL, "classpath://brooklyn/entity/rebind/rebind-catalog-item-test-catalog.xml");
- properties.put(BrooklynServerConfig.CATALOG_LOAD_MODE, brooklyn.catalog.CatalogLoadMode.LOAD_BROOKLYN_CATALOG_URL);
+ properties.put(BrooklynServerConfig.CATALOG_LOAD_MODE, org.apache.brooklyn.core.catalog.CatalogLoadMode.LOAD_BROOKLYN_CATALOG_URL);
return RebindTestUtils.managementContextBuilder(mementoDir, classLoader)
.properties(properties)
.persistPeriodMillis(getPersistPeriodMillis())
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
index d563bea..5c39216 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
@@ -40,10 +40,10 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.mementos.BrooklynMementoManifest;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityFunctions;
import brooklyn.entity.basic.StartableApplication;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
index 3dcef6a..c0bab54 100644
--- a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
@@ -52,12 +52,12 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister.LookupContext;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
+import org.apache.brooklyn.core.catalog.internal.CatalogTestUtils;
import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
import org.apache.brooklyn.core.management.osgi.OsgiVersionMoreEntityTest;
-import brooklyn.catalog.internal.CatalogItemBuilder;
-import brooklyn.catalog.internal.CatalogItemDtoAbstract;
-import brooklyn.catalog.internal.CatalogTestUtils;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.util.collections.MutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
new file mode 100644
index 0000000..90e039d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoTest.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogBundleDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogDo;
+import org.apache.brooklyn.core.catalog.internal.CatalogDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogEntityItemDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemDo;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.CatalogXmlSerializer;
+import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestEntity;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.util.BrooklynMavenArtifacts;
+import brooklyn.util.maven.MavenRetriever;
+
+import com.google.common.collect.ImmutableList;
+
+public class CatalogDtoTest {
+
+ private static final Logger log = LoggerFactory.getLogger(CatalogDtoTest.class);
+
+ private LocalManagementContext managementContext;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception {
+ managementContext = LocalManagementContextForTests.newInstanceWithOsgi();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() throws Exception {
+ if (managementContext != null) Entities.destroyAll(managementContext);
+ }
+
+ @Test(groups="Integration")
+ public void testCatalogLookup() {
+ CatalogDto root = buildExampleCatalog();
+ checkCatalogHealthy(root);
+ }
+
+ @Test(groups="Integration")
+ public void testCatalogSerializeAndLookup() {
+ CatalogDto root = buildExampleCatalog();
+ CatalogXmlSerializer serializer = new CatalogXmlSerializer();
+
+ String xml = serializer.toString(root);
+ log.info("Example catalog serialized as:\n"+xml);
+
+ CatalogDto root2 = (CatalogDto) serializer.fromString(xml);
+ checkCatalogHealthy(root2);
+ }
+
+ protected void checkCatalogHealthy(CatalogDto root) {
+ assertEquals(root.catalogs.size(), 4);
+ CatalogDo loader = new CatalogDo(managementContext, root).load();
+
+ // test app comes from jar, by default
+ CatalogItemDo<?,?> worker = loader.getIdCache().get(CatalogUtils.getVersionedId(TestApplication.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION));
+ assertNotNull(worker);
+ assertEquals(worker.getDisplayName(), "Test App from JAR");
+
+ // TODO can test scanned elements, links to other catalogs, etc
+ }
+
+ public CatalogDto buildExampleCatalog() {
+ CatalogDo root = new CatalogDo(
+ managementContext,
+ CatalogDto.newNamedInstance("My Local Catalog",
+ "My favourite local settings, including remote catalogs -- intended partly as a teaching " +
+ "example for what can be expressed, and how", "contents-built-in-test"));
+ root.setClasspathScanForEntities(CatalogScanningModes.NONE);
+
+ String bundleUrl = MavenRetriever.localUrl(BrooklynMavenArtifacts.artifact("", "brooklyn-core", "jar", "tests"));
+ CatalogDo testEntitiesJavaCatalog = new CatalogDo(
+ managementContext,
+ CatalogDto.newNamedInstance("Test Entities from Java", null, "test-java"));
+ testEntitiesJavaCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
+ testEntitiesJavaCatalog.addToClasspath(bundleUrl);
+ testEntitiesJavaCatalog.addEntry(CatalogItemBuilder.newTemplate(TestApplication.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION)
+ .displayName("Test App from JAR")
+ .javaType(TestApplication.class.getCanonicalName())
+ .build());
+ testEntitiesJavaCatalog.addEntry(CatalogItemBuilder.newEntity(TestEntity.class.getCanonicalName(), BasicBrooklynCatalog.NO_VERSION)
+ .displayName("Test Entity from JAR")
+ .javaType(TestEntity.class.getCanonicalName())
+ .build());
+ root.addCatalog(testEntitiesJavaCatalog.dto);
+
+ CatalogDo testEntitiesJavaCatalogScanning = new CatalogDo(
+ managementContext,
+ CatalogDto.newNamedInstance("Test Entities from Java Scanning", null, "test-java-scan"));
+ testEntitiesJavaCatalogScanning.addToClasspath(bundleUrl);
+ testEntitiesJavaCatalogScanning.setClasspathScanForEntities(CatalogScanningModes.ANNOTATIONS);
+ root.addCatalog(testEntitiesJavaCatalogScanning.dto);
+
+ CatalogDo osgiCatalog = new CatalogDo(
+ managementContext,
+ CatalogDto.newNamedInstance("Test Entities from OSGi",
+ "A catalog whose entries define their libraries as a list of OSGi bundles", "test-osgi-defined"));
+ osgiCatalog.setClasspathScanForEntities(CatalogScanningModes.NONE);
+ CatalogEntityItemDto osgiEntity = CatalogItemBuilder.newEntity(TestEntity.class.getCanonicalName(), "Test Entity from OSGi")
+ // NB: this is not actually an OSGi bundle, but it's okay as we don't instantiate the bundles ahead of time (currently)
+ .libraries(ImmutableList.<CatalogBundle>of(new CatalogBundleDto(null, null, bundleUrl)))
+ .build();
+ testEntitiesJavaCatalog.addEntry(osgiEntity);
+ root.addCatalog(osgiCatalog.dto);
+
+ root.addCatalog(CatalogDto.newLinkedInstance("classpath://brooklyn-catalog-empty.xml"));
+ return root.dto;
+ }
+
+ @Test
+ public void testVersionedIdSplitter() {
+ String id = "simple.id";
+ String version = "0.1.2";
+ String versionedId = CatalogUtils.getVersionedId(id, version);
+
+ Assert.assertNull(CatalogUtils.getIdFromVersionedId(null));
+ Assert.assertNull(CatalogUtils.getVersionFromVersionedId(null));
+ Assert.assertNull(CatalogUtils.getIdFromVersionedId(id));
+ Assert.assertNull(CatalogUtils.getVersionFromVersionedId(version));
+ Assert.assertEquals(CatalogUtils.getIdFromVersionedId(versionedId), id);
+ Assert.assertEquals(CatalogUtils.getVersionFromVersionedId(versionedId), version);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogItemComparatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogItemComparatorTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogItemComparatorTest.java
new file mode 100644
index 0000000..e7d43cd
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogItemComparatorTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.Test;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
+
+public class CatalogItemComparatorTest {
+ private static final String RC2 = "10.5.8-rc2";
+ private static final String STABLE = "10.5.8";
+
+ @Test
+ public void testComparison() {
+ compare("0.0.1", "0.0.2", 1);
+ compare("0.0.2", "0.0.1", -1);
+ compare("0.0.1-qual", "0.0.2", 1);
+ compare("0.0.1.qual", "0.0.2", 1);
+ compare("0.0.1-qual", "0.0.1_qual", 0);
+ compare("0.0.1.qual", "0.0.1.qual", 0);
+ compare("0.0.1", "0.0.2-SNAPSHOT", -1);
+ compare("0.0.1", "0.0.2.SNAPSHOT", -1);
+ compare("0.0.0_SNAPSHOT", "0.0.1-SNAPSHOT-20141111114709760", 1);
+ compare("0.0.0.SNAPSHOT", "0.0.1.SNAPSHOT-20141111114709760", 1);
+ compare("2.0", "2.0.1-BUILD", 1);
+ compare("2.0", "2.0.1.BUILD", 1);
+ compare("2.0.1", "2.0-BUILD", -1);
+ compare("2.0.1", "2.0.0.BUILD", -1);
+ compare("2.0", "2.0-BUILD", -1);
+ // Note not true for .qualifier: compare("2.0", "2.0.0.BUILD", -1);
+ compare("2.1", "2.0-BUILD", -1);
+ compare("2.1", "2.0.0.BUILD", -1);
+ compare("1", "1.3", 1);
+ compare("1-beta", "1-rc2", 1);
+ // Note not true for .qualifier: compare("1.0.0.beta", "1.0.0.rc2", 1);
+ compare("1-beta1", "1-beta10", 1);
+
+ compare(STABLE, "10.5", -1);
+ compare(STABLE, STABLE, 0);
+
+ compare(STABLE, "10.6", 1);
+ compare(STABLE, "10.5.8.1", 1);
+
+ compare("10.5.8-rc2", "10.5.8-rc3", 1) ;
+ compare("10.5.8-rc2", "10.5.8-rc1", -1);
+
+ compare(STABLE, RC2, -1);
+
+ CatalogItemComparator cmp = CatalogItemComparator.INSTANCE;
+ assertTrue(cmp.compare(v(RC2), v("10.5.8-beta1")) == cmp.compare(v(RC2), v("10.5.8-beta3")));
+ }
+
+ private void compare(String v1, String v2, int expected) {
+ CatalogItemComparator cmp = CatalogItemComparator.INSTANCE;
+ assertEquals(cmp.compare(v(v1), v(v2)), expected);
+ assertEquals(cmp.compare(v(v2), v(v1)), -expected);
+ }
+
+ private CatalogItem<?, ?> v(String version) {
+ return CatalogItemBuilder.newEntity("xxx", version).build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java
new file mode 100644
index 0000000..eea4933
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogLoadTest.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.core.catalog.internal.CatalogDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
+import org.apache.brooklyn.core.catalog.internal.CatalogXmlSerializer;
+
+import brooklyn.util.ResourceUtils;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
+
+public class CatalogLoadTest {
+
+ CatalogXmlSerializer serializer;
+
+ @BeforeMethod
+ public void setUp() {
+ serializer = new CatalogXmlSerializer();
+ }
+
+ private String loadFile(String file) {
+ return ResourceUtils.create(this).getResourceAsString(file);
+ }
+
+ // CAMP YAML parsing not available in core, so YAML catalog tests are in camp, e.g. CatalogYamlEntitiesTest
+
+ @Test
+ public void testLoadXmlCatalog() {
+ CatalogDto catalog = (CatalogDto) serializer.fromString(
+ loadFile("classpath://brooklyn/catalog/internal/osgi-catalog.xml"));
+ assertNotNull(catalog);
+ assertEquals(catalog.name, "OSGi catalogue");
+ assertEquals(Iterables.size(catalog.getUniqueEntries()), 1, "Catalog entries = " + Joiner.on(", ").join(catalog.getUniqueEntries()));
+
+ CatalogItemDtoAbstract<?,?> template = Iterables.getOnlyElement(catalog.getUniqueEntries());
+ assertEquals(template.getDisplayName(), "Entity name");
+ assertEquals(template.getVersion(), "9.1.3");
+ assertEquals(template.getJavaType(), "com.example.ExampleApp");
+ assertEquals(template.getLibraries().size(), 2,
+ "Template bundles=" + Joiner.on(", ").join(template.getLibraries()));
+
+ boolean foundBundle1 = false, foundBundle2 = false;
+ for (CatalogBundle bundle : template.getLibraries()) {
+ if (bundle.getUrl().equals("file://path/to/bundle.jar")) {
+ foundBundle1 = true;
+ }
+ if (bundle.getUrl().equals("http://www.url.com/for/bundle.jar")) {
+ foundBundle2 = true;
+ }
+ }
+ assertTrue(foundBundle1);
+ assertTrue(foundBundle2);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
new file mode 100644
index 0000000..2d5abad
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogScanTest.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.net.URLEncoder;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.MyCatalogItems.MySillyAppTemplate;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.entity.basic.Entities;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.net.Urls;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class CatalogScanTest {
+
+ private static final Logger log = LoggerFactory.getLogger(CatalogScanTest.class);
+
+ private BrooklynCatalog defaultCatalog, annotsCatalog, fullCatalog;
+
+ private List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList();
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown(){
+ for (LocalManagementContext managementContext : managementContexts) {
+ Entities.destroyAll(managementContext);
+ }
+ managementContexts.clear();
+ }
+
+ private LocalManagementContext newManagementContext(BrooklynProperties props) {
+ LocalManagementContext result = new LocalManagementContext(props);
+ managementContexts.add(result);
+ return result;
+ }
+
+ private synchronized void loadFullCatalog() {
+ if (fullCatalog!=null) return;
+ BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
+ props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(),
+ "data:,"+Urls.encode("<catalog><classpath scan=\"types\"/></catalog>"));
+ fullCatalog = newManagementContext(props).getCatalog();
+ log.info("ENTITIES loaded for FULL: "+fullCatalog.getCatalogItems(Predicates.alwaysTrue()));
+ }
+
+ private synchronized void loadTheDefaultCatalog(boolean lookOnDiskForDefaultCatalog) {
+ if (defaultCatalog!=null) return;
+ BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
+ props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(),
+ // if default catalog is picked up from the system, we might get random stuff from ~/.brooklyn/ instead of the default;
+ // useful as an integration check that we default correctly, but irritating for people to use if they have such a catalog installed
+ (lookOnDiskForDefaultCatalog ? "" :
+ "data:,"+Urls.encode(new ResourceUtils(this).getResourceAsString("classpath:/brooklyn/default.catalog.bom"))));
+ LocalManagementContext managementContext = newManagementContext(props);
+ defaultCatalog = managementContext.getCatalog();
+ log.info("ENTITIES loaded for DEFAULT: "+defaultCatalog.getCatalogItems(Predicates.alwaysTrue()));
+ }
+
+ @SuppressWarnings("deprecation")
+ private synchronized void loadAnnotationsOnlyCatalog() {
+ if (annotsCatalog!=null) return;
+ BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
+ props.put(BrooklynServerConfig.BROOKLYN_CATALOG_URL.getName(),
+ "data:,"+URLEncoder.encode("<catalog><classpath scan=\"annotations\"/></catalog>"));
+ LocalManagementContext managementContext = newManagementContext(props);
+ annotsCatalog = managementContext.getCatalog();
+ log.info("ENTITIES loaded with annotation: "+annotsCatalog.getCatalogItems(Predicates.alwaysTrue()));
+ }
+
+ @Test
+ public void testLoadAnnotations() {
+ loadAnnotationsOnlyCatalog();
+ BrooklynCatalog c = annotsCatalog;
+
+ Iterable<CatalogItem<Object,Object>> bases = c.getCatalogItems(CatalogPredicates.displayName(Predicates.containsPattern("MyBaseEntity")));
+ Assert.assertEquals(Iterables.size(bases), 0, "should have been empty: "+bases);
+
+ Iterable<CatalogItem<Object,Object>> asdfjkls = c.getCatalogItems(CatalogPredicates.displayName(Predicates.containsPattern("__asdfjkls__shouldnotbefound")));
+ Assert.assertEquals(Iterables.size(asdfjkls), 0);
+
+ Iterable<CatalogItem<Object,Object>> silly1 = c.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppTemplate")));
+ Iterable<CatalogItem<Object,Object>> silly2 = c.getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(MySillyAppTemplate.class.getName())));
+ CatalogItem<Object, Object> silly1El = Iterables.getOnlyElement(silly1);
+ Assert.assertEquals(silly1El, Iterables.getOnlyElement(silly2));
+
+ CatalogItem<Application,EntitySpec<? extends Application>> s1 = c.getCatalogItem(Application.class, silly1El.getSymbolicName(), silly1El.getVersion());
+ Assert.assertEquals(s1, silly1El);
+
+ Assert.assertEquals(s1.getDescription(), "Some silly app test");
+
+ Class<? extends Application> app = c.loadClass(s1);
+ Assert.assertEquals(MySillyAppTemplate.class, app);
+
+ String xml = ((BasicBrooklynCatalog)c).toXmlString();
+ log.info("Catalog is:\n"+xml);
+ Assert.assertTrue(xml.indexOf("Some silly app test") >= 0);
+ }
+
+ @Test
+ public void testAnnotationLoadsSomeApps() {
+ loadAnnotationsOnlyCatalog();
+ Iterable<CatalogItem<Object,Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppTemplate")));
+ Assert.assertEquals(Iterables.getOnlyElement(silly1).getDescription(), "Some silly app test");
+ }
+
+ @Test
+ public void testAnnotationLoadsSomeAppBuilders() {
+ loadAnnotationsOnlyCatalog();
+ Iterable<CatalogItem<Object,Object>> silly1 = annotsCatalog.getCatalogItems(CatalogPredicates.displayName(Predicates.equalTo("MySillyAppBuilderTemplate")));
+ Assert.assertEquals(Iterables.getOnlyElement(silly1).getDescription(), "Some silly app builder test");
+ }
+
+ @Test
+ public void testMoreTypesThanAnnotations() {
+ loadAnnotationsOnlyCatalog();
+ loadFullCatalog();
+
+ int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(Predicates.alwaysTrue()));
+ int numFromTypes = Iterables.size(fullCatalog.getCatalogItems(Predicates.alwaysTrue()));
+
+ Assert.assertTrue(numFromAnnots < numFromTypes, "full="+numFromTypes+" annots="+numFromAnnots);
+ }
+
+ @Test
+ public void testMoreTypesThanAnnotationsForApps() {
+ loadAnnotationsOnlyCatalog();
+ loadFullCatalog();
+
+ int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(CatalogPredicates.IS_TEMPLATE));
+ int numFromTypes = Iterables.size(fullCatalog.getCatalogItems(CatalogPredicates.IS_TEMPLATE));
+
+ Assert.assertTrue(numFromAnnots < numFromTypes, "full="+numFromTypes+" annots="+numFromAnnots);
+ }
+
+ @Test
+ public void testAnnotationIsDefault() {
+ doTestAnnotationIsDefault(false);
+ }
+
+ // see comment in load method; likely fails if a custom catalog is installed in ~/.brooklyn/
+ @Test(groups="Integration", enabled=false)
+ public void testAnnotationIsDefaultOnDisk() {
+ doTestAnnotationIsDefault(true);
+ }
+
+ private void doTestAnnotationIsDefault(boolean lookOnDiskForDefaultCatalog) {
+ loadTheDefaultCatalog(false);
+ int numInDefault = Iterables.size(defaultCatalog.getCatalogItems(Predicates.alwaysTrue()));
+
+ loadAnnotationsOnlyCatalog();
+ int numFromAnnots = Iterables.size(annotsCatalog.getCatalogItems(Predicates.alwaysTrue()));
+
+ Assert.assertEquals(numInDefault, numFromAnnots);
+ Assert.assertTrue(numInDefault>0, "Expected more than 0 entries");
+ }
+
+ // a simple test asserting no errors when listing the real catalog, and listing them for reference
+ // also useful to test variants in a stored catalog to assert they all load
+ // TODO integration tests which build up catalogs assuming other things are installed
+ @Test
+ public void testListCurrentCatalogItems() {
+ LocalManagementContext mgmt = newManagementContext(BrooklynProperties.Factory.newDefault());
+ log.info("ITEMS\n"+Strings.join(mgmt.getCatalog().getCatalogItems(), "\n"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogTestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogTestUtils.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogTestUtils.java
new file mode 100644
index 0000000..510fdf8
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogTestUtils.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+
+import com.google.common.annotations.Beta;
+
+public class CatalogTestUtils {
+
+ /** creates entity spec with the java type of a catalog item;
+ * would be nice to have this in {@link CatalogUtils},
+ * but the logic for parsing the yaml is buried in camp code,
+ * so it's a little bit hard to make this a first class method.
+ * <p>
+ * (this impl ignores many things, including config and location.)
+ */
+ @Beta
+ public static EntitySpec<?> createEssentialEntitySpec(ManagementContext mgmt, CatalogItem<?, ?> catalogItem) {
+ BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, catalogItem);
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ EntitySpec<?> spec = EntitySpec.create( (Class)loader.loadClass(catalogItem.getJavaType()) );
+ spec.catalogItemId(catalogItem.getId());
+ return spec;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java
new file mode 100644
index 0000000..f8a75cc
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/CatalogVersioningTest.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+
+import brooklyn.entity.basic.Entities;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+
+public class CatalogVersioningTest {
+ private LocalManagementContext managementContext;
+ private BrooklynCatalog catalog;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception {
+ managementContext = LocalManagementContextForTests.newInstance();
+ catalog = managementContext.getCatalog();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() throws Exception {
+ if (managementContext != null) Entities.destroyAll(managementContext);
+ }
+
+ @Test
+ public void testParsingVersion() {
+ assertVersionParsesAs("foo:1", "foo", "1");
+ assertVersionParsesAs("foo", null, null);
+ assertVersionParsesAs("foo:1.1", "foo", "1.1");
+ assertVersionParsesAs("foo:1_SNAPSHOT", "foo", "1_SNAPSHOT");
+ assertVersionParsesAs("foo:10.9.8_SNAPSHOT", "foo", "10.9.8_SNAPSHOT");
+ assertVersionParsesAs("foo:bar", null, null);
+ assertVersionParsesAs("chef:cookbook", null, null);
+ assertVersionParsesAs("http://foo:8080", null, null);
+ }
+
+ private static void assertVersionParsesAs(String versionedId, String id, String version) {
+ if (version==null) {
+ Assert.assertFalse(CatalogUtils.looksLikeVersionedId(versionedId));
+ } else {
+ Assert.assertTrue(CatalogUtils.looksLikeVersionedId(versionedId));
+ Assert.assertEquals(CatalogUtils.getIdFromVersionedId(versionedId), id);
+ Assert.assertEquals(CatalogUtils.getVersionFromVersionedId(versionedId), version);
+ }
+ }
+
+ @Test
+ public void testAddVersioned() {
+ String symbolicName = "sampleId";
+ String version = "0.1.0";
+ createCatalogItem(symbolicName, version);
+ assertSingleCatalogItem(symbolicName, version);
+ }
+
+ @Test
+ public void testAddSameVersionFails() {
+ String symbolicName = "sampleId";
+ String version = "0.1.0";
+ createCatalogItem(symbolicName, version);
+ createCatalogItem(symbolicName, version);
+ //forced update assumed in the above call
+ assertSingleCatalogItem(symbolicName, version);
+ }
+
+ @Test
+ public void testGetLatest() {
+ String symbolicName = "sampleId";
+ String v1 = "0.1.0";
+ String v2 = "0.2.0";
+ createCatalogItem(symbolicName, v1);
+ createCatalogItem(symbolicName, v2);
+ CatalogItem<?, ?> item = catalog.getCatalogItem(symbolicName, BasicBrooklynCatalog.DEFAULT_VERSION);
+ assertEquals(item.getSymbolicName(), symbolicName);
+ assertEquals(item.getVersion(), v2);
+ }
+
+ @Test
+ public void testGetLatestStable() {
+ String symbolicName = "sampleId";
+ String v1 = "0.1.0";
+ String v2 = "0.2.0-SNAPSHOT";
+ createCatalogItem(symbolicName, v1);
+ createCatalogItem(symbolicName, v2);
+ CatalogItem<?, ?> item = catalog.getCatalogItem(symbolicName, BasicBrooklynCatalog.DEFAULT_VERSION);
+ assertEquals(item.getSymbolicName(), symbolicName);
+ assertEquals(item.getVersion(), v1);
+ }
+
+ @Test
+ public void testDelete() {
+ String symbolicName = "sampleId";
+ String version = "0.1.0";
+ createCatalogItem(symbolicName, version);
+ assertSingleCatalogItem(symbolicName, version);
+ assertTrue(catalog.getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName))).iterator().hasNext());
+ catalog.deleteCatalogItem(symbolicName, version);
+ assertFalse(catalog.getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName))).iterator().hasNext());
+ }
+
+ @Test
+ public void testList() {
+ String symbolicName = "sampleId";
+ String v1 = "0.1.0";
+ String v2 = "0.2.0-SNAPSHOT";
+ createCatalogItem(symbolicName, v1);
+ createCatalogItem(symbolicName, v2);
+ Iterable<CatalogItem<Object, Object>> items = catalog.getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName)));
+ assertEquals(Iterables.size(items), 2);
+ }
+
+ @SuppressWarnings("deprecation")
+ private void createCatalogItem(String symbolicName, String version) {
+ catalog.addItem(CatalogItemBuilder.newEntity(symbolicName, version).
+ plan("services:\n- type: brooklyn.entity.basic.BasicEntity")
+ .build());
+ }
+
+ private void assertSingleCatalogItem(String symbolicName, String version) {
+ Iterable<CatalogItem<Object, Object>> items = catalog.getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName)));
+ CatalogItem<Object, Object> item = Iterables.getOnlyElement(items);
+ assertEquals(item.getSymbolicName(), symbolicName);
+ assertEquals(item.getVersion(), version);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java
new file mode 100644
index 0000000..1fc0de9
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/catalog/internal/MyCatalogItems.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import org.apache.brooklyn.api.catalog.Catalog;
+
+import brooklyn.entity.basic.AbstractApplication;
+import brooklyn.entity.basic.ApplicationBuilder;
+
+public class MyCatalogItems {
+
+ @Catalog(description="Some silly app test")
+ public static class MySillyAppTemplate extends AbstractApplication {
+ }
+
+ @Catalog(description="Some silly app builder test")
+ public static class MySillyAppBuilderTemplate extends ApplicationBuilder {
+ @Override protected void doBuild() {
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
index 8a555ed..7220e47 100644
--- a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiVersionMoreEntityTest.java
@@ -38,14 +38,14 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.catalog.internal.CatalogEntityItemDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
+import org.apache.brooklyn.core.catalog.internal.CatalogTestUtils;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import brooklyn.catalog.internal.CatalogEntityItemDto;
-import brooklyn.catalog.internal.CatalogItemBuilder;
-import brooklyn.catalog.internal.CatalogItemDtoAbstract;
-import brooklyn.catalog.internal.CatalogTestUtils;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.proxying.InternalEntityFactory;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 7def6cf..9241a73 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -47,11 +47,11 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
-import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.entity.basic.BasicApplicationImpl;
import brooklyn.util.ResourceUtils;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 57d53da..33bb6a1 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -46,11 +46,11 @@ import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
import org.apache.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver;
import org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.ManagementContextInjectable;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.basic.BrooklynTags;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
index ff60237..527a44c 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
@@ -32,8 +32,8 @@ import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.InstantiatorFromKey;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.config.ConfigBag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
index be18cc2..409ca1c 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
@@ -31,11 +31,11 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Urls;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
index 7b6328a..1f12663 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
@@ -29,8 +29,8 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityDecorationResolver;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.util.text.Strings;
/**
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
index 49cbb6e..63ac989 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
@@ -28,8 +28,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
-
-import brooklyn.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
public abstract class AbstractTemplateBrooklynLookup<T extends AbstractResource> extends AbstractBrooklynResourceLookup<T> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
index 5158550..a41ee05 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
@@ -31,8 +31,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynAssemblyTemplateInstantiator;
-
-import brooklyn.catalog.CatalogPredicates;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
public class AssemblyTemplateBrooklynLookup extends AbstractTemplateBrooklynLookup<AssemblyTemplate> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
index 02a0cb6..a7089e8 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
@@ -29,8 +29,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
-
-import brooklyn.catalog.CatalogPredicates;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
public class PlatformComponentTemplateBrooklynLookup extends AbstractTemplateBrooklynLookup<PlatformComponentTemplate> {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
index d2ada07..c0b77f4 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
@@ -30,13 +30,13 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.StartableApplication;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
index df4b41b..d96b132 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
@@ -37,7 +38,6 @@ import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.util.ResourceUtils;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index 1bf481d..66fee85 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -37,10 +37,8 @@ import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.osgi.OsgiVersionMoreEntityTest;
-
-import brooklyn.catalog.internal.CatalogUtils;
-
import org.apache.brooklyn.test.TestResourceUnavailableException;
import brooklyn.util.ResourceUtils;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
index c4579ff..3aa9b74 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
@@ -32,10 +32,10 @@ import org.apache.brooklyn.api.catalog.BrooklynCatalog;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.BasicEntity;
import org.apache.brooklyn.test.TestResourceUnavailableException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
index 70076f9..7d283a9 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
@@ -33,9 +33,9 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
-import brooklyn.catalog.CatalogPredicates;
import brooklyn.event.basic.BasicConfigKey;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
index 6a44df3..e6f9d3d 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
@@ -25,9 +25,9 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
-import brooklyn.catalog.CatalogPredicates;
import brooklyn.event.basic.BasicConfigKey;
import org.apache.brooklyn.test.TestResourceUnavailableException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
index 3081243..e33f739 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
@@ -24,10 +24,10 @@ import static org.testng.Assert.assertFalse;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlRebindTest;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.testng.annotations.Test;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.StartableApplication;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java
index a250c37..b98cb94 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlVersioningTest.java
@@ -30,9 +30,9 @@ import org.apache.brooklyn.api.catalog.BrooklynCatalog;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.CatalogPredicates;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
import brooklyn.entity.basic.BasicApplication;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.entity.basic.ConfigKeys;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
index 09cba24..8d3ed07 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
@@ -66,9 +66,6 @@ import org.apache.brooklyn.cli.CloudExplorer.ComputeListImagesCommand;
import org.apache.brooklyn.cli.CloudExplorer.ComputeListInstancesCommand;
import org.apache.brooklyn.cli.CloudExplorer.ComputeTerminateInstancesCommand;
import org.apache.brooklyn.cli.ItemLister.ListAllCommand;
-
-import brooklyn.catalog.internal.CatalogInitialization;
-
import org.apache.brooklyn.cli.CloudExplorer.BlobstoreGetBlobCommand;
import org.apache.brooklyn.cli.CloudExplorer.BlobstoreListContainerCommand;
import org.apache.brooklyn.cli.CloudExplorer.BlobstoreListContainersCommand;
@@ -79,6 +76,7 @@ import org.apache.brooklyn.cli.CloudExplorer.ComputeListImagesCommand;
import org.apache.brooklyn.cli.CloudExplorer.ComputeListInstancesCommand;
import org.apache.brooklyn.cli.CloudExplorer.ComputeTerminateInstancesCommand;
import org.apache.brooklyn.cli.ItemLister.ListAllCommand;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.ha.OsgiManager;
import brooklyn.entity.basic.AbstractApplication;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
index 8267ca3..504363a 100644
--- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
@@ -49,6 +49,7 @@ import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynAssemblyTemplateInstantiator;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
@@ -64,7 +65,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import brooklyn.catalog.internal.CatalogInitialization;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.BrooklynServerPaths;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
index 0e56483..49596d6 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
@@ -36,9 +36,9 @@ import com.google.common.io.Files;
import org.apache.brooklyn.api.catalog.BrooklynCatalog;
import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.catalog.internal.CatalogInitialization;
import brooklyn.entity.rebind.persister.PersistMode;
import brooklyn.util.ResourceUtils;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
index b0796db..02521e5 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
@@ -22,6 +22,7 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.catalog.internal.CatalogInitialization;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.launcher.BrooklynLauncher;
@@ -49,7 +50,6 @@ import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
-import brooklyn.catalog.internal.CatalogInitialization;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.entity.basic.ApplicationBuilder;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index 8a54607..98d5648 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -46,7 +46,6 @@ import org.codehaus.jackson.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.AbstractGroup;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.Lifecycle;
@@ -60,6 +59,7 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.entitlement.EntitlementPredicates;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index e841b27..80dc2a3 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -44,15 +44,13 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.catalog.CatalogPredicates;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.CatalogDto;
+import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
-
-import brooklyn.catalog.CatalogPredicates;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.internal.CatalogDto;
-import brooklyn.catalog.internal.CatalogItemComparator;
-import brooklyn.catalog.internal.CatalogUtils;
-
import org.apache.brooklyn.rest.api.CatalogApi;
import org.apache.brooklyn.rest.domain.ApiError;
import org.apache.brooklyn.rest.domain.CatalogEntitySummary;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/LocationResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/LocationResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/LocationResource.java
index 83fa84d..1dc0bf2 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/LocationResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/LocationResource.java
@@ -32,9 +32,7 @@ import org.slf4j.LoggerFactory;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
-
-import brooklyn.catalog.internal.CatalogUtils;
-
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.location.basic.LocationConfigKeys;
import org.apache.brooklyn.rest.api.LocationApi;
import org.apache.brooklyn.rest.domain.LocationSpec;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
index bfe82ba..d09d05b 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -50,10 +50,10 @@ import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
-import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.ConfigKey;
import brooklyn.enricher.Enrichers;
import brooklyn.entity.basic.AbstractEntity;
[19/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java b/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
deleted file mode 100644
index a54c1b1..0000000
--- a/core/src/main/java/brooklyn/management/internal/LocalEntityManager.java
+++ /dev/null
@@ -1,818 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import groovy.util.ObservableList;
-
-import java.lang.reflect.Proxy;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.Group;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.entity.proxying.EntityTypeRegistry;
-import org.apache.brooklyn.api.management.AccessController;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.policy.Enricher;
-import org.apache.brooklyn.api.policy.EnricherSpec;
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.api.policy.PolicySpec;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.BrooklynLogging;
-import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.basic.EntityPredicates;
-import brooklyn.entity.proxying.BasicEntityTypeRegistry;
-import brooklyn.entity.proxying.EntityProxy;
-import brooklyn.entity.proxying.EntityProxyImpl;
-import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.entity.proxying.InternalPolicyFactory;
-import brooklyn.entity.trait.Startable;
-import brooklyn.internal.storage.BrooklynStorage;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.collections.SetFromLiveMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.time.CountdownTimer;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-public class LocalEntityManager implements EntityManagerInternal {
-
- private static final Logger log = LoggerFactory.getLogger(LocalEntityManager.class);
-
- private final LocalManagementContext managementContext;
- private final BasicEntityTypeRegistry entityTypeRegistry;
- private final InternalEntityFactory entityFactory;
- private final InternalPolicyFactory policyFactory;
-
- /** Entities that have been created, but have not yet begun to be managed */
- protected final Map<String,Entity> preRegisteredEntitiesById = Collections.synchronizedMap(new WeakHashMap<String, Entity>());
-
- /** Entities that are in the process of being managed, but where management is not yet complete */
- protected final Map<String,Entity> preManagedEntitiesById = Collections.synchronizedMap(new WeakHashMap<String, Entity>());
-
- /** Proxies of the managed entities */
- protected final ConcurrentMap<String,Entity> entityProxiesById = Maps.newConcurrentMap();
-
- /** Real managed entities */
- protected final Map<String,Entity> entitiesById = Maps.newLinkedHashMap();
-
- /** Management mode for each entity */
- protected final Map<String,ManagementTransitionMode> entityModesById = Collections.synchronizedMap(Maps.<String,ManagementTransitionMode>newLinkedHashMap());
-
- /** Proxies of the managed entities */
- protected final ObservableList entities = new ObservableList();
-
- /** Proxies of the managed entities that are applications */
- protected final Set<Application> applications = Sets.newConcurrentHashSet();
-
- private final BrooklynStorage storage;
- private final Map<String,String> entityTypes;
- private final Set<String> applicationIds;
-
- public LocalEntityManager(LocalManagementContext managementContext) {
- this.managementContext = checkNotNull(managementContext, "managementContext");
- this.storage = managementContext.getStorage();
- this.entityTypeRegistry = new BasicEntityTypeRegistry();
- this.policyFactory = new InternalPolicyFactory(managementContext);
- this.entityFactory = new InternalEntityFactory(managementContext, entityTypeRegistry, policyFactory);
-
- entityTypes = storage.getMap("entities");
- applicationIds = SetFromLiveMap.create(storage.<String,Boolean>getMap("applications"));
- }
-
- public InternalEntityFactory getEntityFactory() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
- return entityFactory;
- }
-
- public InternalPolicyFactory getPolicyFactory() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
- return policyFactory;
- }
-
- @Override
- public EntityTypeRegistry getEntityTypeRegistry() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
- return entityTypeRegistry;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T extends Entity> T createEntity(EntitySpec<T> spec) {
- try {
- T entity = entityFactory.createEntity(spec);
- Entity proxy = ((AbstractEntity)entity).getProxy();
- return (T) checkNotNull(proxy, "proxy for entity %s, spec %s", entity, spec);
- } catch (Throwable e) {
- log.warn("Failed to create entity using spec "+spec+" (rethrowing)", e);
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- public <T extends Entity> T createEntity(Map<?,?> config, Class<T> type) {
- return createEntity(EntitySpec.create(config, type));
- }
-
- @Override
- public <T extends Policy> T createPolicy(PolicySpec<T> spec) {
- try {
- return policyFactory.createPolicy(spec);
- } catch (Throwable e) {
- log.warn("Failed to create policy using spec "+spec+" (rethrowing)", e);
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- public <T extends Enricher> T createEnricher(EnricherSpec<T> spec) {
- try {
- return policyFactory.createEnricher(spec);
- } catch (Throwable e) {
- log.warn("Failed to create enricher using spec "+spec+" (rethrowing)", e);
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- public Collection<Entity> getEntities() {
- return ImmutableList.copyOf(entityProxiesById.values());
- }
-
- @Override
- public Collection<String> getEntityIds() {
- return ImmutableList.copyOf(entityProxiesById.keySet());
- }
-
- @Override
- public Collection<Entity> getEntitiesInApplication(Application application) {
- Predicate<Entity> predicate = EntityPredicates.applicationIdEqualTo(application.getId());
- return ImmutableList.copyOf(Iterables.filter(entityProxiesById.values(), predicate));
- }
-
- @Override
- public Collection<Entity> findEntities(Predicate<? super Entity> filter) {
- return ImmutableList.copyOf(Iterables.filter(entityProxiesById.values(), filter));
- }
-
- @Override
- public Collection<Entity> findEntitiesInApplication(Application application, Predicate<? super Entity> filter) {
- Predicate<Entity> predicate = Predicates.and(EntityPredicates.applicationIdEqualTo(application.getId()), filter);
- return ImmutableList.copyOf(Iterables.filter(entityProxiesById.values(), predicate));
- }
-
- @Override
- public Iterable<Entity> getAllEntitiesInApplication(Application application) {
- Predicate<Entity> predicate = EntityPredicates.applicationIdEqualTo(application.getId());
- Iterable<Entity> allentities = Iterables.concat(preRegisteredEntitiesById.values(), preManagedEntitiesById.values(), entityProxiesById.values());
- Iterable<Entity> result = Iterables.filter(allentities, predicate);
- return ImmutableSet.copyOf(Iterables.transform(result, new Function<Entity, Entity>() {
- @Override public Entity apply(Entity input) {
- return Entities.proxy(input);
- }}));
- }
-
- @Override
- public Entity getEntity(String id) {
- return entityProxiesById.get(id);
- }
-
- Collection<Application> getApplications() {
- return ImmutableList.copyOf(applications);
- }
-
- @Override
- public boolean isManaged(Entity e) {
- return (isRunning() && getEntity(e.getId()) != null);
- }
-
- boolean isPreRegistered(Entity e) {
- return preRegisteredEntitiesById.containsKey(e.getId());
- }
-
- void prePreManage(Entity entity) {
- if (isPreRegistered(entity)) {
- log.warn(""+this+" redundant call to pre-pre-manage entity "+entity+"; skipping",
- new Exception("source of duplicate pre-pre-manage of "+entity));
- return;
- }
- preRegisteredEntitiesById.put(entity.getId(), entity);
- }
-
- @Override
- public ManagementTransitionMode getLastManagementTransitionMode(String itemId) {
- return entityModesById.get(itemId);
- }
-
- @Override
- public void setManagementTransitionMode(Entity item, ManagementTransitionMode mode) {
- entityModesById.put(item.getId(), mode);
- }
-
- // TODO synchronization issues here. We guard with isManaged(), but if another thread executing
- // concurrently then the managed'ness could be set after our check but before we do
- // onManagementStarting etc. However, we can't just synchronize because we're calling alien code
- // (the user might override entity.onManagementStarting etc).
- //
- // TODO We need to do some check about isPreManaged - i.e. is there another thread (or is this a
- // re-entrant call) where the entity is not yet full managed (i.e. isManaged==false) but we're in
- // the middle of managing it.
- //
- // TODO Also see LocalLocationManager.manage(Entity), if fixing things here
- @Override
- public void manage(Entity e) {
- if (isManaged(e)) {
- log.warn(""+this+" redundant call to start management of entity (and descendants of) "+e+"; skipping",
- new Exception("source of duplicate management of "+e));
- return;
- }
- manageRecursive(e, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.NONEXISTENT, BrooklynObjectManagementMode.MANAGED_PRIMARY));
- }
-
- @Override
- public void manageRebindedRoot(Entity item) {
- ManagementTransitionMode mode = getLastManagementTransitionMode(item.getId());
- Preconditions.checkNotNull(mode, "Mode not set for rebinding %s", item);
- manageRecursive(item, mode);
- }
-
- protected void checkManagementAllowed(Entity item) {
- AccessController.Response access = managementContext.getAccessController().canManageEntity(item);
- if (!access.isAllowed()) {
- throw new IllegalStateException("Access controller forbids management of "+item+": "+access.getMsg());
- }
- }
-
- /* TODO we sloppily use "recursive" to ensure ordering of parent-first in many places
- * (which may not be necessary but seems like a good idea),
- * and also to collect many entities when doing a big rebind,
- * ensuring all have #manageNonRecursive called before calling #onManagementStarted.
- *
- * it would be better to have a manageAll(Map<Entity,ManagementTransitionMode> items)
- * method which did that in two phases, allowing us to selectively rebind,
- * esp when we come to want supporting different modes and different brooklyn nodes.
- *
- * the impl of manageAll could sort them with parents before children,
- * (and manageRecursive could simply populate a map and delegate to manageAll).
- *
- * manageRebindRoot would then go, and the (few) callers would construct the map.
- *
- * similarly we might want an unmanageAll(),
- * although possibly all unmanagement should be recursive, if we assume an entity's ancestors are always at least proxied
- * (and the non-recursive RO path here could maybe be dropped)
- */
-
- /** Applies management lifecycle callbacks (onManagementStarting, for all beforehand, then onManagementStopped, for all after) */
- protected void manageRecursive(Entity e, final ManagementTransitionMode initialMode) {
- checkManagementAllowed(e);
-
- final List<EntityInternal> allEntities = Lists.newArrayList();
- Predicate<EntityInternal> manageEntity = new Predicate<EntityInternal>() { public boolean apply(EntityInternal it) {
- ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
- if (mode==null) {
- setManagementTransitionMode(it, mode = initialMode);
- }
-
- Boolean isReadOnlyFromEntity = it.getManagementSupport().isReadOnlyRaw();
- if (isReadOnlyFromEntity==null) {
- if (mode.isReadOnly()) {
- // should have been marked by rebinder
- log.warn("Read-only entity "+it+" not marked as such on call to manage; marking and continuing");
- }
- it.getManagementSupport().setReadOnly(mode.isReadOnly());
- } else {
- if (!isReadOnlyFromEntity.equals(mode.isReadOnly())) {
- log.warn("Read-only status at entity "+it+" ("+isReadOnlyFromEntity+") not consistent with management mode "+mode);
- }
- }
-
- if (it.getManagementSupport().isDeployed()) {
- if (mode.wasNotLoaded()) {
- // silently bail out
- return false;
- } else {
- if (mode.wasPrimary() && mode.isPrimary()) {
- // active partial rebind; continue
- } else if (mode.wasReadOnly() && mode.isReadOnly()) {
- // reload in RO mode
- } else {
- // on initial non-RO rebind, should not have any deployed instances
- log.warn("Already deployed "+it+" when managing "+mode+"/"+initialMode+"; ignoring this and all descendants");
- return false;
- }
- }
- }
-
- // check RO status is consistent
- boolean isNowReadOnly = Boolean.TRUE.equals( ((EntityInternal)it).getManagementSupport().isReadOnly() );
- if (mode.isReadOnly()!=isNowReadOnly) {
- throw new IllegalStateException("Read-only status mismatch for "+it+": "+mode+" / RO="+isNowReadOnly);
- }
-
- allEntities.add(it);
- preManageNonRecursive(it, mode);
- it.getManagementSupport().onManagementStarting( new ManagementTransitionInfo(managementContext, mode) );
- return manageNonRecursive(it, mode);
- } };
- boolean isRecursive = true;
- if (initialMode.wasPrimary() && initialMode.isPrimary()) {
- // already managed, so this shouldn't be recursive
- // (in ActivePartialRebind we cheat, calling in to this method then skipping recursion).
- // it also falls through to here when doing a redundant promotion,
- // in that case we *should* be recursive; determine by checking whether a child exists and is preregistered.
- // the TODO above removing manageRebindRoot in favour of explicit mgmt list would clean this up a lot!
- Entity aChild = Iterables.getFirst(e.getChildren(), null);
- if (aChild!=null && isPreRegistered(aChild)) {
- log.debug("Managing "+e+" in mode "+initialMode+", doing this recursively because a child is preregistered");
- } else {
- log.debug("Managing "+e+" but skipping recursion, as mode is "+initialMode);
- isRecursive = false;
- }
- }
- if (!isRecursive) {
- manageEntity.apply( (EntityInternal)e );
- } else {
- recursively(e, manageEntity);
- }
-
- for (EntityInternal it : allEntities) {
- if (!it.getManagementSupport().isFullyManaged()) {
- ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
- ManagementTransitionInfo info = new ManagementTransitionInfo(managementContext, mode);
-
- it.getManagementSupport().onManagementStarted(info);
- managementContext.getRebindManager().getChangeListener().onManaged(it);
- }
- }
- }
-
- @Override
- public void unmanage(final Entity e) {
- unmanage(e, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT));
- }
-
- public void unmanage(final Entity e, final ManagementTransitionMode mode) {
- unmanage(e, mode, false);
- }
-
- private void unmanage(final Entity e, ManagementTransitionMode mode, boolean hasBeenReplaced) {
- if (shouldSkipUnmanagement(e)) return;
- final ManagementTransitionInfo info = new ManagementTransitionInfo(managementContext, mode);
-
- if (hasBeenReplaced) {
- // we are unmanaging an old instance after having replaced it
- // don't unmanage or even clear its fields, because there might be references to it
-
- if (mode.wasReadOnly()) {
- // if coming *from* read only; nothing needed
- } else {
- if (!mode.wasPrimary()) {
- log.warn("Unexpected mode "+mode+" for unmanage-replace "+e+" (applying anyway)");
- }
- // migrating away or in-place active partial rebind:
- ((EntityInternal)e).getManagementSupport().onManagementStopping(info);
- stopTasks(e);
- ((EntityInternal)e).getManagementSupport().onManagementStopped(info);
- }
- // do not remove from maps below, bail out now
- return;
-
- } else if (mode.wasReadOnly() && mode.isNoLongerLoaded()) {
- // we are unmanaging an instance (secondary); either stopping here or primary destroyed elsewhere
- ((EntityInternal)e).getManagementSupport().onManagementStopping(info);
- unmanageNonRecursive(e);
- stopTasks(e);
- ((EntityInternal)e).getManagementSupport().onManagementStopped(info);
- managementContext.getRebindManager().getChangeListener().onUnmanaged(e);
- if (managementContext.getGarbageCollector() != null) managementContext.getGarbageCollector().onUnmanaged(e);
-
- } else if (mode.wasPrimary() && mode.isNoLongerLoaded()) {
- // unmanaging a primary; currently this is done recursively
-
- /* TODO tidy up when it is recursive and when it isn't; if something is being unloaded or destroyed,
- * that probably *is* recursive, but the old mode might be different if in some cases things are read-only.
- * or maybe nothing needs to be recursive, we just make sure the callers (e.g. HighAvailabilityModeImpl.clearManagedItems)
- * call in a good order
- *
- * see notes above about recursive/manage/All/unmanageAll
- */
-
- // Need to store all child entities as onManagementStopping removes a child from the parent entity
- final List<EntityInternal> allEntities = Lists.newArrayList();
- recursively(e, new Predicate<EntityInternal>() { public boolean apply(EntityInternal it) {
- if (shouldSkipUnmanagement(it)) return false;
- allEntities.add(it);
- it.getManagementSupport().onManagementStopping(info);
- return true;
- } });
-
- for (EntityInternal it : allEntities) {
- if (shouldSkipUnmanagement(it)) continue;
- unmanageNonRecursive(it);
- stopTasks(it);
- }
- for (EntityInternal it : allEntities) {
- it.getManagementSupport().onManagementStopped(info);
- managementContext.getRebindManager().getChangeListener().onUnmanaged(it);
- if (managementContext.getGarbageCollector() != null) managementContext.getGarbageCollector().onUnmanaged(e);
- }
-
- } else {
- log.warn("Invalid mode for unmanage: "+mode+" on "+e+" (ignoring)");
- }
-
- preRegisteredEntitiesById.remove(e.getId());
- preManagedEntitiesById.remove(e.getId());
- entityProxiesById.remove(e.getId());
- entitiesById.remove(e.getId());
- entityModesById.remove(e.getId());
- }
-
- private void stopTasks(Entity entity) {
- stopTasks(entity, null);
- }
-
- /** stops all tasks (apart from any current one or its descendants) on this entity,
- * optionally -- if a timeout is given -- waiting for completion and warning on incomplete tasks */
- @Beta
- public void stopTasks(Entity entity, @Nullable Duration timeout) {
- CountdownTimer timeleft = timeout==null ? null : timeout.countdownTimer();
- // try forcibly interrupting tasks on managed entities
- Collection<Exception> exceptions = MutableSet.of();
- try {
- Set<Task<?>> tasksCancelled = MutableSet.of();
- for (Task<?> t: managementContext.getExecutionContext(entity).getTasks()) {
- if (entity.equals(BrooklynTaskTags.getContextEntity(Tasks.current())) && hasTaskAsAncestor(t, Tasks.current())) {
- // don't cancel if we are running inside a task on the target entity and
- // the task being considered is one we have submitted -- e.g. on "stop" don't cancel ourselves!
- // but if our current task is from another entity we probably do want to cancel them (we are probably invoking unmanage)
- continue;
- }
-
- if (!t.isDone()) {
- try {
- log.debug("Cancelling "+t+" on "+entity);
- tasksCancelled.add(t);
- t.cancel(true);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- log.debug("Error cancelling "+t+" on "+entity+" (will warn when all tasks are cancelled): "+e, e);
- exceptions.add(e);
- }
- }
- }
-
- if (timeleft!=null) {
- Set<Task<?>> tasksIncomplete = MutableSet.of();
- // go through all tasks, not just cancelled ones, in case there are previously cancelled ones which are not complete
- for (Task<?> t: managementContext.getExecutionContext(entity).getTasks()) {
- if (hasTaskAsAncestor(t, Tasks.current()))
- continue;
- if (!Tasks.blockUntilInternalTasksEnded(t, timeleft.getDurationRemaining())) {
- tasksIncomplete.add(t);
- }
- }
- if (!tasksIncomplete.isEmpty()) {
- log.warn("Incomplete tasks when stopping "+entity+": "+tasksIncomplete);
- }
- if (log.isTraceEnabled())
- log.trace("Cancelled "+tasksCancelled+" tasks for "+entity+", with "+
- timeleft.getDurationRemaining()+" remaining (of "+timeout+"): "+tasksCancelled);
- } else {
- if (log.isTraceEnabled())
- log.trace("Cancelled "+tasksCancelled+" tasks for "+entity+": "+tasksCancelled);
- }
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- log.warn("Error inspecting tasks to cancel on unmanagement: "+e, e);
- }
- if (!exceptions.isEmpty())
- log.warn("Error when cancelling tasks for "+entity+" on unmanagement: "+Exceptions.create(exceptions));
- }
-
- private boolean hasTaskAsAncestor(Task<?> t, Task<?> potentialAncestor) {
- if (t==null || potentialAncestor==null) return false;
- if (t.equals(potentialAncestor)) return true;
- return hasTaskAsAncestor(t.getSubmittedByTask(), potentialAncestor);
- }
-
- /**
- * activates management when effector invoked, warning unless context is acceptable
- * (currently only acceptable context is "start")
- */
- void manageIfNecessary(Entity entity, Object context) {
- if (!isRunning()) {
- return; // TODO Still a race for terminate being called, and then isManaged below returning false
- } else if (((EntityInternal)entity).getManagementSupport().wasDeployed()) {
- return;
- } else if (isManaged(entity)) {
- return;
- } else if (isPreManaged(entity)) {
- return;
- } else if (Boolean.TRUE.equals(((EntityInternal)entity).getManagementSupport().isReadOnly())) {
- return;
- } else {
- Entity rootUnmanaged = entity;
- while (true) {
- Entity candidateUnmanagedParent = rootUnmanaged.getParent();
- if (candidateUnmanagedParent == null || isManaged(candidateUnmanagedParent) || isPreManaged(candidateUnmanagedParent))
- break;
- rootUnmanaged = candidateUnmanagedParent;
- }
- if (context == Startable.START.getName())
- log.info("Activating local management for {} on start", rootUnmanaged);
- else
- log.warn("Activating local management for {} due to effector invocation on {}: {}", new Object[]{rootUnmanaged, entity, context});
- manage(rootUnmanaged);
- }
- }
-
- private void recursively(Entity e, Predicate<EntityInternal> action) {
- Entity otherPreregistered = preRegisteredEntitiesById.get(e.getId());
- if (otherPreregistered!=null) {
- // if something has been pre-registered, prefer it
- // (e.g. if we recursing through children, we might have a proxy from previous iteration;
- // the most recent will have been pre-registered)
- e = otherPreregistered;
- }
-
- boolean success = action.apply( (EntityInternal)e );
- if (!success) {
- return; // Don't manage children if action false/unnecessary for parent
- }
- for (Entity child : e.getChildren()) {
- recursively(child, action);
- }
- }
-
- /**
- * Whether the entity is in the process of being managed.
- */
- private synchronized boolean isPreManaged(Entity e) {
- return preManagedEntitiesById.containsKey(e.getId());
- }
-
- /**
- * Should ensure that the entity is now known about, but should not be accessible from other entities yet.
- *
- * Records that the given entity is about to be managed (used for answering {@link isPreManaged(Entity)}.
- * Note that refs to the given entity are stored in a a weak hashmap so if the subsequent management
- * attempt fails then this reference to the entity will eventually be discarded (if no-one else holds
- * a reference).
- */
- private synchronized boolean preManageNonRecursive(Entity e, ManagementTransitionMode mode) {
- Entity realE = toRealEntity(e);
-
- Object old = preManagedEntitiesById.put(e.getId(), realE);
- preRegisteredEntitiesById.remove(e.getId());
-
- if (old!=null && mode.wasNotLoaded()) {
- if (old.equals(e)) {
- log.warn("{} redundant call to pre-start management of entity {}, mode {}; ignoring", new Object[] { this, e, mode });
- } else {
- throw new IllegalStateException("call to pre-manage entity "+e+" ("+mode+") but different entity "+old+" already known under that id at "+this);
- }
- return false;
- } else {
- if (log.isTraceEnabled()) log.trace("{} pre-start management of entity {}, mode {}",
- new Object[] { this, e, mode });
- return true;
- }
- }
-
- /**
- * Should ensure that the entity is now managed somewhere, and known about in all the lists.
- * Returns true if the entity has now become managed; false if it was already managed (anything else throws exception)
- * @param isOrWasReadOnly
- */
- private synchronized boolean manageNonRecursive(Entity e, ManagementTransitionMode mode) {
- Entity old = entitiesById.get(e.getId());
-
- if (old!=null && mode.wasNotLoaded()) {
- if (old.equals(e)) {
- log.warn("{} redundant call to start management of entity {}; ignoring", this, e);
- } else {
- throw new IllegalStateException("call to manage entity "+e+" ("+mode+") but different entity "+old+" already known under that id at "+this);
- }
- return false;
- }
-
- BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(e),
- "{} starting management of entity {}", this, e);
- Entity realE = toRealEntity(e);
-
- Entity oldProxy = entityProxiesById.get(e.getId());
- Entity proxyE;
- if (oldProxy!=null) {
- if (mode.wasNotLoaded()) {
- throw new IllegalStateException("call to manage entity "+e+" from unloaded state ("+mode+") but already had proxy "+oldProxy+" already known under that id at "+this);
- }
- // make the old proxy point at this new delegate
- // (some other tricks done in the call below)
- ((EntityProxyImpl)(Proxy.getInvocationHandler(oldProxy))).resetDelegate(oldProxy, oldProxy, realE);
- proxyE = oldProxy;
- } else {
- proxyE = toProxyEntityIfAvailable(e);
- }
- entityProxiesById.put(e.getId(), proxyE);
- entityTypes.put(e.getId(), realE.getClass().getName());
- entitiesById.put(e.getId(), realE);
-
- preManagedEntitiesById.remove(e.getId());
- if ((e instanceof Application) && (e.getParent()==null)) {
- applications.add((Application)proxyE);
- applicationIds.add(e.getId());
- }
- if (!entities.contains(proxyE))
- entities.add(proxyE);
-
- if (old!=null && old!=e) {
- // passing the transition info will ensure the right shutdown steps invoked for old instance
- unmanage(old, mode, true);
- }
-
- return true;
- }
-
- /**
- * Should ensure that the entity is no longer managed anywhere, remove from all lists.
- * Returns true if the entity has been removed from management; if it was not previously managed (anything else throws exception)
- */
- private boolean unmanageNonRecursive(Entity e) {
- /*
- * When method is synchronized, hit deadlock:
- * 1. thread called unmanage() on a member of a group, so we got the lock and called group.removeMember;
- * this ties to synchronize on AbstractGroupImpl.members
- * 2. another thread was doing AbstractGroupImpl.addMember, which is synchronized on AbstractGroupImpl.members;
- * it tries to call Entities.manage(child) which calls LocalEntityManager.getEntity(), which is
- * synchronized on this.
- *
- * We MUST NOT call alien code from within the management framework while holding locks.
- * The AbstractGroup.removeMember is effectively alien because a user could override it, and because
- * it is entity specific.
- *
- * TODO Does getting then removing from groups risk this entity being added to other groups while
- * this is happening? Should abstractEntity.onManagementStopped or some such remove the entity
- * from its groups?
- */
-
- if (!getLastManagementTransitionMode(e.getId()).isReadOnly()) {
- e.clearParent();
- Collection<Group> groups = e.getGroups();
- for (Group group : groups) {
- if (!Entities.isNoLongerManaged(group)) group.removeMember(e);
- }
- if (e instanceof Group) {
- Collection<Entity> members = ((Group)e).getMembers();
- for (Entity member : members) {
- if (!Entities.isNoLongerManaged(member)) member.removeGroup((Group)e);
- }
- }
- } else {
- log.debug("No relations being updated on unmanage of read only {}", e);
- }
-
- synchronized (this) {
- Entity proxyE = toProxyEntityIfAvailable(e);
- if (e instanceof Application) {
- applications.remove(proxyE);
- applicationIds.remove(e.getId());
- }
-
- entities.remove(proxyE);
- entityProxiesById.remove(e.getId());
- entityModesById.remove(e.getId());
- Object old = entitiesById.remove(e.getId());
-
- entityTypes.remove(e.getId());
- if (old==null) {
- log.warn("{} call to stop management of unknown entity (already unmanaged?) {}; ignoring", this, e);
- return false;
- } else if (!old.equals(e)) {
- // shouldn't happen...
- log.error("{} call to stop management of entity {} removed different entity {}", new Object[] { this, e, old });
- return true;
- } else {
- if (log.isDebugEnabled()) log.debug("{} stopped management of entity {}", this, e);
- return true;
- }
- }
- }
-
- void addEntitySetListener(CollectionChangeListener<Entity> listener) {
- //must notify listener in a different thread to avoid deadlock (issue #378)
- AsyncCollectionChangeAdapter<Entity> wrappedListener = new AsyncCollectionChangeAdapter<Entity>(managementContext.getExecutionManager(), listener);
- entities.addPropertyChangeListener(new GroovyObservablesPropertyChangeToCollectionChangeAdapter(wrappedListener));
- }
-
- void removeEntitySetListener(CollectionChangeListener<Entity> listener) {
- AsyncCollectionChangeAdapter<Entity> wrappedListener = new AsyncCollectionChangeAdapter<Entity>(managementContext.getExecutionManager(), listener);
- entities.removePropertyChangeListener(new GroovyObservablesPropertyChangeToCollectionChangeAdapter(wrappedListener));
- }
-
- private boolean shouldSkipUnmanagement(Entity e) {
- if (e==null) {
- log.warn(""+this+" call to unmanage null entity; skipping",
- new IllegalStateException("source of null unmanagement call to "+this));
- return true;
- }
- if (!isManaged(e)) {
- log.warn("{} call to stop management of unknown entity (already unmanaged?) {}; skipping, and all descendants", this, e);
- return true;
- }
- return false;
- }
-
- private Entity toProxyEntityIfAvailable(Entity e) {
- checkNotNull(e, "entity");
-
- if (e instanceof EntityProxy) {
- return e;
- } else if (e instanceof AbstractEntity) {
- Entity result = ((AbstractEntity)e).getProxy();
- return (result == null) ? e : result;
- } else {
- // If we don't already know about the proxy, then use the real thing; presumably it's
- // the legacy way of creating the entity so didn't get a preManage() call
-
- return e;
- }
- }
-
- private Entity toRealEntity(Entity e) {
- checkNotNull(e, "entity");
-
- if (e instanceof AbstractEntity) {
- return e;
- } else {
- Entity result = toRealEntityOrNull(e.getId());
- if (result == null) {
- throw new IllegalStateException("No concrete entity known for entity "+e+" ("+e.getId()+", "+e.getEntityType().getName()+")");
- }
- return result;
- }
- }
-
- public boolean isKnownEntityId(String id) {
- return entitiesById.containsKey(id) || preManagedEntitiesById.containsKey(id) || preRegisteredEntitiesById.containsKey(id);
- }
-
- private Entity toRealEntityOrNull(String id) {
- Entity result;
- // prefer the preRegistered and preManaged entities, during hot proxying, they should be newer
- result = preRegisteredEntitiesById.get(id);
- if (result==null)
- result = preManagedEntitiesById.get(id);
- if (result==null)
- entitiesById.get(id);
- return result;
- }
-
- private boolean isRunning() {
- return managementContext.isRunning();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java b/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
deleted file mode 100644
index 31dc036..0000000
--- a/core/src/main/java/brooklyn/management/internal/LocalLocationManager.java
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.Closeable;
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.api.location.ProvisioningLocation;
-import org.apache.brooklyn.api.management.AccessController;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.BrooklynLogging;
-import brooklyn.config.BrooklynLogging.LoggingLevel;
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Lifecycle;
-import brooklyn.entity.proxying.InternalLocationFactory;
-import brooklyn.internal.storage.BrooklynStorage;
-
-import org.apache.brooklyn.location.basic.AbstractLocation;
-import org.apache.brooklyn.location.basic.LocationInternal;
-
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.task.Tasks;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-
-public class LocalLocationManager implements LocationManagerInternal {
-
- @Beta /* expect to remove when API returns LocationSpec or similar */
- public static final ConfigKey<Boolean> CREATE_UNMANAGED = ConfigKeys.newBooleanConfigKey("brooklyn.internal.location.createUnmanaged",
- "If set on a location or spec, causes the manager to create it in an unmanaged state (for peeking)", false);
-
- private static final Logger log = LoggerFactory.getLogger(LocalLocationManager.class);
-
- private final LocalManagementContext managementContext;
- private final InternalLocationFactory locationFactory;
-
- protected final Map<String,Location> locationsById = Maps.newLinkedHashMap();
- private final Map<String, Location> preRegisteredLocationsById = Maps.newLinkedHashMap();
-
- /** Management mode for each location */
- protected final Map<String,ManagementTransitionMode> locationModesById = Maps.newLinkedHashMap();
-
- private final BrooklynStorage storage;
- private Map<String, String> locationTypes;
-
- private static AtomicLong LOCATION_CNT = new AtomicLong(0);
-
- public LocalLocationManager(LocalManagementContext managementContext) {
- this.managementContext = checkNotNull(managementContext, "managementContext");
- this.locationFactory = new InternalLocationFactory(managementContext);
-
- this.storage = managementContext.getStorage();
- locationTypes = storage.getMap("locations");
- }
-
- public InternalLocationFactory getLocationFactory() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
- return locationFactory;
-
- }
-
- @Override
- public <T extends Location> T createLocation(LocationSpec<T> spec) {
- try {
- boolean createUnmanaged = ConfigBag.coerceFirstNonNullKeyValue(CREATE_UNMANAGED,
- spec.getConfig().get(CREATE_UNMANAGED), spec.getFlags().get(CREATE_UNMANAGED.getName()));
- if (createUnmanaged) {
- spec.removeConfig(CREATE_UNMANAGED);
- }
-
- T loc = locationFactory.createLocation(spec);
- if (!createUnmanaged) {
- manage(loc);
- } else {
- // remove references
- Location parent = loc.getParent();
- if (parent!=null) {
- ((AbstractLocation)parent).removeChild(loc);
- }
- preRegisteredLocationsById.remove(loc.getId());
- }
-
- return loc;
- } catch (Throwable e) {
- log.warn("Failed to create location using spec "+spec+" (rethrowing)", e);
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- public <T extends Location> T createLocation(Map<?,?> config, Class<T> type) {
- return createLocation(LocationSpec.create(config, type));
- }
-
- @Override
- public synchronized Collection<Location> getLocations() {
- return ImmutableList.copyOf(locationsById.values());
- }
-
- @Override
- public Collection<String> getLocationIds() {
- return ImmutableList.copyOf(locationsById.keySet());
- }
-
- @Override
- public synchronized Location getLocation(String id) {
- return locationsById.get(id);
- }
-
- public synchronized Location getLocationEvenIfPreManaged(String id) {
- Location result = locationsById.get(id);
- if (result == null) {
- result = preRegisteredLocationsById.get(id);
- }
- return result;
- }
-
- @Override
- public boolean isManaged(Location loc) {
- return (isRunning() && loc != null && getLocation(loc.getId()) != null);
- }
-
- synchronized boolean isPreRegistered(Location loc) {
- return preRegisteredLocationsById.containsKey(loc.getId());
- }
-
- public boolean isKnownLocationId(String id) {
- return preRegisteredLocationsById.containsKey(id) || locationsById.containsKey(id);
- }
-
- synchronized void prePreManage(Location loc) {
- if (isPreRegistered(loc)) {
- log.warn(""+this+" redundant call to pre-pre-manage location "+loc+"; skipping",
- new Exception("source of duplicate pre-pre-manage of "+loc));
- return;
- }
- preRegisteredLocationsById.put(loc.getId(), loc);
- }
-
- @Override
- public ManagementTransitionMode getLastManagementTransitionMode(String itemId) {
- return locationModesById.get(itemId);
- }
-
- @Override
- public void setManagementTransitionMode(Location item, ManagementTransitionMode mode) {
- locationModesById.put(item.getId(), mode);
- }
-
- // TODO synchronization issues here: see comment in LocalEntityManager.manage(Entity)
- /** management on creation */
- @Override
- public Location manage(Location loc) {
- if (isManaged(loc)) {
- // TODO put log.warn back in if/when manage(Location) becomes private; or could even have assert.
- // Can be stricter about contract.
- return loc;
- }
-
- Location parent = loc.getParent();
- if (parent != null && !managementContext.getLocationManager().isManaged(parent)) {
- log.warn("Parent location "+parent+" of "+loc+" is not managed; attempting to manage it (in future this may be disallowed)");
- return manage(parent);
- } else {
- return manageRecursive(loc, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.NONEXISTENT, BrooklynObjectManagementMode.MANAGED_PRIMARY));
- }
- }
-
- @Override
- public void manageRebindedRoot(Location item) {
- ManagementTransitionMode mode = getLastManagementTransitionMode(item.getId());
- Preconditions.checkNotNull(mode, "Mode not set for rebinding %s", item);
- manageRecursive(item, mode);
- }
-
- protected void checkManagementAllowed(Location item) {
- AccessController.Response access = managementContext.getAccessController().canManageLocation(item);
- if (!access.isAllowed()) {
- throw new IllegalStateException("Access controller forbids management of "+item+": "+access.getMsg());
- }
- }
-
- protected Location manageRecursive(Location loc, final ManagementTransitionMode initialMode) {
- // TODO see comments in LocalEntityManager about recursive management / manageRebindRoot v manageAll
-
- AccessController.Response access = managementContext.getAccessController().canManageLocation(loc);
- if (!access.isAllowed()) {
- throw new IllegalStateException("Access controller forbids management of "+loc+": "+access.getMsg());
- }
-
- long count = LOCATION_CNT.incrementAndGet();
- if (log.isDebugEnabled()) {
- String msg = "Managing location " + loc + " ("+initialMode+"), from " + Tasks.current()+" / "+Entitlements.getEntitlementContext();
- LoggingLevel level = (!initialMode.wasNotLoaded() || initialMode.isReadOnly() ? LoggingLevel.TRACE : LoggingLevel.DEBUG);
- if (count % 100 == 0) {
- // include trace periodically in case we get leaks or too much location management
- BrooklynLogging.log(log, level,
- msg, new Exception("Informational stack trace of call to manage location "+loc+" ("+count+" calls; "+getLocations().size()+" currently managed)"));
- } else {
- BrooklynLogging.log(log, level, msg);
- }
- }
-
- recursively(loc, new Predicate<AbstractLocation>() { public boolean apply(AbstractLocation it) {
- ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
- if (mode==null) {
- setManagementTransitionMode(it, mode = initialMode);
- }
-
- if (it.isManaged()) {
- if (mode.wasNotLoaded()) {
- // silently bail out
- return false;
- } else {
- // on rebind, we just replace, fall through to below
- }
- }
-
- boolean result = manageNonRecursive(it, mode);
- if (result) {
- it.setManagementContext(managementContext);
- if (mode.isPrimary()) {
- it.onManagementStarted();
- if (mode.isCreating()) {
- // Never record event on rebind; this isn't the location (e.g. the VM) being "created"
- // so don't tell listeners that.
- // TODO The location-event history should be persisted; currently it is lost on
- // rebind, unless there is a listener that is persisting the state externally itself.
- recordLocationEvent(it, Lifecycle.CREATED);
- }
- }
- managementContext.getRebindManager().getChangeListener().onManaged(it);
- }
- return result;
- } });
- return loc;
- }
-
- @Override
- public void unmanage(final Location loc) {
- unmanage(loc, ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT));
- }
-
- public void unmanage(final Location loc, final ManagementTransitionMode mode) {
- unmanage(loc, mode, false);
- }
-
- private void unmanage(final Location loc, final ManagementTransitionMode mode, boolean hasBeenReplaced) {
- if (shouldSkipUnmanagement(loc)) return;
-
- if (hasBeenReplaced) {
- // we are unmanaging an old instance after having replaced it;
- // don't unmanage or even clear its fields, because there might be references to it
-
- if (mode.wasReadOnly()) {
- // if coming *from* read only; nothing needed
- } else {
- if (!mode.wasPrimary()) {
- log.warn("Unexpected mode "+mode+" for unmanage-replace "+loc+" (applying anyway)");
- }
- // migrating away or in-place active partial rebind:
- managementContext.getRebindManager().getChangeListener().onUnmanaged(loc);
- if (managementContext.gc != null) managementContext.gc.onUnmanaged(loc);
- }
- // do not remove from maps below, bail out now
- return;
-
- } else if ((mode.wasPrimary() && mode.isReadOnly()) || (mode.wasReadOnly() && mode.isNoLongerLoaded())) {
- if (mode.isReadOnly() && mode.wasPrimary()) {
- // TODO shouldn't this fall into "hasBeenReplaced" above?
- log.debug("Unmanaging on demotion: "+loc+" ("+mode+")");
- }
- // we are unmanaging an instance whose primary management is elsewhere (either we were secondary, or we are being demoted)
- unmanageNonRecursiveRemoveFromRecords(loc, mode);
- managementContext.getRebindManager().getChangeListener().onUnmanaged(loc);
- if (managementContext.gc != null) managementContext.gc.onUnmanaged(loc);
- unmanageNonRecursiveClearItsFields(loc, mode);
-
- } else if (mode.isNoLongerLoaded()) {
- // Need to store all child entities as onManagementStopping removes a child from the parent entity
-
- // As above, see TODO in LocalEntityManager about recursive management / unmanagement v manageAll/unmanageAll
- recursively(loc, new Predicate<AbstractLocation>() { public boolean apply(AbstractLocation it) {
- if (shouldSkipUnmanagement(it)) return false;
- boolean result = unmanageNonRecursiveRemoveFromRecords(it, mode);
- if (result) {
- ManagementTransitionMode mode = getLastManagementTransitionMode(it.getId());
- if (mode==null) {
- // ad hoc creation e.g. tests
- log.debug("Missing transition mode for "+it+" when unmanaging; assuming primary/destroying");
- mode = ManagementTransitionMode.guessing(BrooklynObjectManagementMode.MANAGED_PRIMARY, BrooklynObjectManagementMode.NONEXISTENT);
- }
- if (mode.wasPrimary()) it.onManagementStopped();
- managementContext.getRebindManager().getChangeListener().onUnmanaged(it);
- if (mode.isDestroying()) recordLocationEvent(it, Lifecycle.DESTROYED);
- if (managementContext.gc != null) managementContext.gc.onUnmanaged(it);
- }
- unmanageNonRecursiveClearItsFields(loc, mode);
- return result;
- } });
-
- } else {
- log.warn("Invalid mode for unmanage: "+mode+" on "+loc+" (ignoring)");
- }
-
- if (loc instanceof Closeable) {
- Streams.closeQuietly( (Closeable)loc );
- }
-
- locationsById.remove(loc.getId());
- preRegisteredLocationsById.remove(loc.getId());
- locationModesById.remove(loc.getId());
- locationTypes.remove(loc.getId());
- }
-
- /**
- * Adds this location event to the usage record for the given location (creating the usage
- * record if one does not already exist).
- */
- private void recordLocationEvent(LocationInternal loc, Lifecycle state) {
- try {
- managementContext.getUsageManager().recordLocationEvent(loc, state);
- } catch (RuntimeInterruptedException e) {
- throw e;
- } catch (RuntimeException e) {
- log.warn("Failed to store location lifecycle event for "+loc+" (ignoring)", e);
- }
- }
-
- private void recursively(Location e, Predicate<AbstractLocation> action) {
- boolean success = action.apply( (AbstractLocation)e );
- if (!success) {
- return; // Don't manage children if action false/unnecessary for parent
- }
- for (Location child : e.getChildren()) {
- recursively(child, action);
- }
- }
-
- /**
- * Should ensure that the location is now managed somewhere, and known about in all the lists.
- * Returns true if the location has now become managed; false if it was already managed (anything else throws exception)
- * @param rebindPrimary true if rebinding primary, false if rebinding as copy, null if creating (not rebinding)
- */
- private synchronized boolean manageNonRecursive(Location loc, ManagementTransitionMode mode) {
- Location old = locationsById.put(loc.getId(), loc);
- preRegisteredLocationsById.remove(loc.getId());
-
- locationTypes.put(loc.getId(), loc.getClass().getName());
-
- if (old!=null && mode.wasNotLoaded()) {
- if (old.equals(loc)) {
- log.warn("{} redundant call to start management of location {}", this, loc);
- } else {
- throw new IllegalStateException("call to manage location "+loc+" but different location "+old+" already known under that id at "+this);
- }
- return false;
- }
-
- if (old!=null && old!=loc) {
- // passing the transition info will ensure the right shutdown steps invoked for old instance
- unmanage(old, mode, true);
- }
-
- return true;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private synchronized void unmanageNonRecursiveClearItsFields(Location loc, ManagementTransitionMode mode) {
- if (mode.isDestroying()) {
- ((AbstractLocation)loc).setParent(null, true);
-
- Location parent = ((AbstractLocation)loc).getParent();
- if (parent instanceof ProvisioningLocation<?>) {
- try {
- ((ProvisioningLocation)parent).release(loc);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- log.debug("Error releasing "+loc+" in its parent "+parent+": "+e);
- }
- }
- } else {
- // if not destroying, don't change the parent's children list
- ((AbstractLocation)loc).setParent(null, false);
- }
- // clear config to help with GC; i know you're not supposed to, but this seems to help, else config bag is littered with refs to entities etc
- // FIXME relies on config().getLocalBag() returning the underlying bag!
- ((AbstractLocation)loc).config().getLocalBag().clear();
- }
-
- /**
- * Should ensure that the location is no longer managed anywhere, remove from all lists.
- * Returns true if the location has been removed from management; if it was not previously managed (anything else throws exception)
- */
- private synchronized boolean unmanageNonRecursiveRemoveFromRecords(Location loc, ManagementTransitionMode mode) {
- Object old = locationsById.remove(loc.getId());
- locationTypes.remove(loc.getId());
- locationModesById.remove(loc.getId());
-
- if (old==null) {
- log.warn("{} call to stop management of unknown location (already unmanaged?) {}; ignoring", this, loc);
- return false;
- } else if (!old.equals(loc)) {
- // shouldn't happen...
- log.error("{} call to stop management of location {} removed different location {}; ignoring", new Object[] { this, loc, old });
- return true;
- } else {
- if (log.isDebugEnabled()) log.debug("{} stopped management of location {}", this, loc);
- return true;
- }
- }
-
- private boolean shouldSkipUnmanagement(Location loc) {
- if (loc==null) {
- log.warn(""+this+" call to unmanage null location; skipping",
- new IllegalStateException("source of null unmanagement call to "+this));
- return true;
- }
- if (!isManaged(loc)) {
- log.warn("{} call to stop management of unknown location (already unmanaged?) {}; skipping, and all descendants", this, loc);
- return true;
- }
- return false;
- }
-
- private boolean isRunning() {
- return managementContext.isRunning();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java b/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
deleted file mode 100644
index db9b33b..0000000
--- a/core/src/main/java/brooklyn/management/internal/LocalManagementContext.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static brooklyn.util.JavaGroovyEquivalents.elvis;
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Effector;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.AccessController;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.SubscriptionManager;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.TaskAdaptable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynProperties.Factory.Builder;
-import brooklyn.entity.drivers.downloads.BasicDownloadsManager;
-import brooklyn.entity.effector.Effectors;
-import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.entity.proxying.InternalLocationFactory;
-import brooklyn.entity.proxying.InternalPolicyFactory;
-import brooklyn.internal.BrooklynFeatureEnablement;
-import brooklyn.internal.storage.DataGridFactory;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.ha.OsgiManager;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.BasicExecutionContext;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.DynamicTasks;
-import brooklyn.util.task.TaskTags;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.Strings;
-
-import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableSet;
-
-/**
- * A local (single node) implementation of the {@link ManagementContext} API.
- */
-public class LocalManagementContext extends AbstractManagementContext {
-
- private static final Logger log = LoggerFactory.getLogger(LocalManagementContext.class);
-
- private static final Set<LocalManagementContext> INSTANCES = Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<LocalManagementContext, Boolean>()));
-
- private final Builder builder;
-
- private final List<ManagementContext.PropertiesReloadListener> reloadListeners = new CopyOnWriteArrayList<ManagementContext.PropertiesReloadListener>();
-
- @VisibleForTesting
- static Set<LocalManagementContext> getInstances() {
- synchronized (INSTANCES) {
- return ImmutableSet.copyOf(INSTANCES);
- }
- }
-
- // Note also called reflectively by BrooklynLeakListener
- public static void logAll(Logger logger){
- for (LocalManagementContext context : getInstances()) {
- logger.warn("Management Context "+context+" running, creation stacktrace:\n" + Throwables.getStackTraceAsString(context.constructionStackTrace));
- }
- }
-
- /** terminates all (best effort); returns count of sessions closed; if exceptions thrown, returns negative number.
- * semantics might change, particular in dealing with interminable mgmt contexts. */
- // Note also called reflectively by BrooklynLeakListener
- @Beta
- public static int terminateAll() {
- int closed=0,dangling=0;
- for (LocalManagementContext context : getInstances()) {
- try {
- context.terminate();
- closed++;
- }catch (Throwable t) {
- Exceptions.propagateIfFatal(t);
- log.warn("Failed to terminate management context", t);
- dangling++;
- }
- }
- if (dangling>0) return -dangling;
- return closed;
- }
-
- private String managementPlaneId;
- private String managementNodeId;
- private BasicExecutionManager execution;
- private SubscriptionManager subscriptions;
- private LocalEntityManager entityManager;
- private final LocalLocationManager locationManager;
- private final LocalAccessManager accessManager;
- private final LocalUsageManager usageManager;
- private OsgiManager osgiManager;
-
- public final Throwable constructionStackTrace = new Throwable("for construction stacktrace").fillInStackTrace();
-
- private final Map<String, Object> brooklynAdditionalProperties;
-
- /**
- * Creates a LocalManagement with default BrooklynProperties.
- */
- public LocalManagementContext() {
- this(BrooklynProperties.Factory.builderDefault());
- }
-
- public LocalManagementContext(BrooklynProperties brooklynProperties) {
- this(brooklynProperties, (DataGridFactory)null);
- }
-
- /**
- * Creates a new LocalManagementContext.
- *
- * @param brooklynProperties the BrooklynProperties.
- * @param datagridFactory the DataGridFactory to use. If this instance is null, it means that the system
- * is going to use BrooklynProperties to figure out which instance to load or otherwise
- * use a default instance.
- */
- @VisibleForTesting
- public LocalManagementContext(BrooklynProperties brooklynProperties, DataGridFactory datagridFactory) {
- this(Builder.fromProperties(brooklynProperties), datagridFactory);
- }
-
- public LocalManagementContext(Builder builder) {
- this(builder, null, null);
- }
-
- public LocalManagementContext(Builder builder, DataGridFactory datagridFactory) {
- this(builder, null, datagridFactory);
- }
-
- public LocalManagementContext(Builder builder, Map<String, Object> brooklynAdditionalProperties) {
- this(builder, brooklynAdditionalProperties, null);
- }
-
- public LocalManagementContext(BrooklynProperties brooklynProperties, Map<String, Object> brooklynAdditionalProperties) {
- this(Builder.fromProperties(brooklynProperties), brooklynAdditionalProperties, null);
- }
-
- public LocalManagementContext(Builder builder, Map<String, Object> brooklynAdditionalProperties, DataGridFactory datagridFactory) {
- super(builder.build(), datagridFactory);
-
- checkNotNull(configMap, "brooklynProperties");
-
- // TODO in a persisted world the planeId may be injected
- this.managementPlaneId = Strings.makeRandomId(8);
- this.managementNodeId = Strings.makeRandomId(8);
- this.builder = builder;
- this.brooklynAdditionalProperties = brooklynAdditionalProperties;
- if (brooklynAdditionalProperties != null)
- configMap.addFromMap(brooklynAdditionalProperties);
-
- BrooklynFeatureEnablement.init(configMap);
-
- this.locationManager = new LocalLocationManager(this);
- this.accessManager = new LocalAccessManager();
- this.usageManager = new LocalUsageManager(this);
-
- if (configMap.getConfig(OsgiManager.USE_OSGI)) {
- this.osgiManager = new OsgiManager(this);
- osgiManager.start();
- }
-
- INSTANCES.add(this);
- log.debug("Created management context "+this);
- }
-
- @Override
- public String getManagementPlaneId() {
- return managementPlaneId;
- }
-
- @Override
- public String getManagementNodeId() {
- return managementNodeId;
- }
-
- @Override
- public void prePreManage(Entity entity) {
- getEntityManager().prePreManage(entity);
- }
-
- @Override
- public void prePreManage(Location location) {
- getLocationManager().prePreManage(location);
- }
-
- @Override
- public synchronized Collection<Application> getApplications() {
- return getEntityManager().getApplications();
- }
-
- @Override
- public void addEntitySetListener(CollectionChangeListener<Entity> listener) {
- getEntityManager().addEntitySetListener(listener);
- }
-
- @Override
- public void removeEntitySetListener(CollectionChangeListener<Entity> listener) {
- getEntityManager().removeEntitySetListener(listener);
- }
-
- @Override
- protected void manageIfNecessary(Entity entity, Object context) {
- getEntityManager().manageIfNecessary(entity, context);
- }
-
- @Override
- public synchronized LocalEntityManager getEntityManager() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
-
- if (entityManager == null) {
- entityManager = new LocalEntityManager(this);
- }
- return entityManager;
- }
-
- @Override
- public InternalEntityFactory getEntityFactory() {
- return getEntityManager().getEntityFactory();
- }
-
- @Override
- public InternalLocationFactory getLocationFactory() {
- return getLocationManager().getLocationFactory();
- }
-
- @Override
- public InternalPolicyFactory getPolicyFactory() {
- return getEntityManager().getPolicyFactory();
- }
-
- @Override
- public synchronized LocalLocationManager getLocationManager() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
- return locationManager;
- }
-
- @Override
- public synchronized LocalAccessManager getAccessManager() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
- return accessManager;
- }
-
- @Override
- public synchronized LocalUsageManager getUsageManager() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
- return usageManager;
- }
-
- @Override
- public synchronized Maybe<OsgiManager> getOsgiManager() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
- if (osgiManager==null) return Maybe.absent("OSGi not available in this instance");
- return Maybe.of(osgiManager);
- }
-
- @Override
- public synchronized AccessController getAccessController() {
- return getAccessManager().getAccessController();
- }
-
- @Override
- public synchronized SubscriptionManager getSubscriptionManager() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
-
- if (subscriptions == null) {
- subscriptions = new LocalSubscriptionManager(getExecutionManager());
- }
- return subscriptions;
- }
-
- @Override
- public synchronized ExecutionManager getExecutionManager() {
- if (!isRunning()) throw new IllegalStateException("Management context no longer running");
-
- if (execution == null) {
- execution = new BasicExecutionManager(getManagementNodeId());
- gc = new BrooklynGarbageCollector(configMap, execution, getStorage());
- }
- return execution;
- }
-
- @Override
- public void terminate() {
- INSTANCES.remove(this);
- super.terminate();
- if (osgiManager!=null) {
- osgiManager.stop();
- osgiManager = null;
- }
- if (usageManager != null) usageManager.terminate();
- if (execution != null) execution.shutdownNow();
- if (gc != null) gc.shutdownNow();
- }
-
- @Override
- protected void finalize() {
- terminate();
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- public <T> Task<T> runAtEntity(Map flags, Entity entity, Callable<T> c) {
- manageIfNecessary(entity, elvis(Arrays.asList(flags.get("displayName"), flags.get("description"), flags, c)));
- return runAtEntity(entity, Tasks.<T>builder().dynamic(true).body(c).flags(flags).build());
- }
-
- protected <T> Task<T> runAtEntity(Entity entity, TaskAdaptable<T> task) {
- getExecutionContext(entity).submit(task);
- if (DynamicTasks.getTaskQueuingContext()!=null) {
- // put it in the queueing context so it appears in the GUI
- // mark it inessential as this is being invoked from code,
- // the caller will do 'get' to handle errors
- TaskTags.markInessential(task);
- DynamicTasks.getTaskQueuingContext().queue(task.asTask());
- }
- return task.asTask();
- }
-
- @Override
- protected <T> Task<T> runAtEntity(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters) {
- manageIfNecessary(entity, eff);
- // prefer to submit this from the current execution context so it sets up correct cross-context chaining
- ExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext();
- if (ec == null) {
- log.debug("Top-level effector invocation: {} on {}", eff, entity);
- ec = getExecutionContext(entity);
- }
- return runAtEntity(entity, Effectors.invocation(entity, eff, parameters));
- }
-
- @Override
- public boolean isManagedLocally(Entity e) {
- return true;
- }
-
- @Override
- public String toString() {
- return LocalManagementContext.class.getSimpleName()+"["+getManagementPlaneId()+"-"+getManagementNodeId()+"]";
- }
-
- @Override
- public void reloadBrooklynProperties() {
- log.info("Reloading brooklyn properties from " + builder);
- if (builder.hasDelegateOriginalProperties())
- log.warn("When reloading, mgmt context "+this+" properties are fixed, so reload will be of limited utility");
-
- BrooklynProperties properties = builder.build();
- configMap = properties;
- if (brooklynAdditionalProperties != null) {
- log.info("Reloading additional brooklyn properties from " + brooklynAdditionalProperties);
- configMap.addFromMap(brooklynAdditionalProperties);
- }
- this.downloadsManager = BasicDownloadsManager.newDefault(configMap);
- this.entitlementManager = Entitlements.newManager(this, configMap);
-
- clearLocationRegistry();
-
- BrooklynFeatureEnablement.init(configMap);
-
- // Notify listeners that properties have been reloaded
- for (PropertiesReloadListener listener : reloadListeners) {
- listener.reloaded();
- }
- }
-
- @VisibleForTesting
- public void clearLocationRegistry() {
- // Force reload of location registry
- this.locationRegistry = null;
- }
-
- @Override
- public void addPropertiesReloadListener(PropertiesReloadListener listener) {
- reloadListeners.add(checkNotNull(listener, "listener"));
- }
-
- @Override
- public void removePropertiesReloadListener(PropertiesReloadListener listener) {
- reloadListeners.remove(listener);
- }
-
- public void noteStartupComplete() {
- startupComplete = true;
- }
-}
[05/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java
new file mode 100644
index 0000000..7e34071
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java
@@ -0,0 +1,474 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import org.apache.brooklyn.core.management.ha.TestEntityFailingRebind.RebindException;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.InMemoryObjectStore;
+import brooklyn.entity.rebind.persister.ListeningObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.internal.BrooklynFeatureEnablement;
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Ticker;
+import com.google.common.collect.ImmutableList;
+
+@Test
+public class HighAvailabilityManagerSplitBrainTest {
+
+ private static final Logger log = LoggerFactory.getLogger(HighAvailabilityManagerSplitBrainTest.class);
+
+ private List<HaMgmtNode> nodes = new MutableList<HighAvailabilityManagerSplitBrainTest.HaMgmtNode>();
+ Map<String,String> sharedBackingStore = MutableMap.of();
+ Map<String,Date> sharedBackingStoreDates = MutableMap.of();
+ private AtomicLong sharedTime; // used to set the ticker's return value
+ private ClassLoader classLoader = getClass().getClassLoader();
+
+ public class HaMgmtNode {
+ // TODO share with HotStandbyTest and WarmStandbyTest and a few others (minor differences but worth it ultimately)
+
+ private ManagementContextInternal mgmt;
+ private String ownNodeId;
+ private String nodeName;
+ private ListeningObjectStore objectStore;
+ private ManagementPlaneSyncRecordPersister persister;
+ private HighAvailabilityManagerImpl ha;
+ private Ticker ticker;
+ private AtomicLong currentTime; // used to set the ticker's return value
+
+ public void setUp() throws Exception {
+ if (sharedTime==null)
+ currentTime = new AtomicLong(System.currentTimeMillis());
+
+ ticker = new Ticker() {
+ // strictly not a ticker because returns millis UTC, but it works fine even so
+ @Override public long read() {
+ if (sharedTime!=null) return sharedTime.get();
+ return currentTime.get();
+ }
+ };
+
+ nodeName = "node "+nodes.size();
+ mgmt = newLocalManagementContext();
+ ownNodeId = mgmt.getManagementNodeId();
+ objectStore = new ListeningObjectStore(newPersistenceObjectStore());
+ objectStore.injectManagementContext(mgmt);
+ objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
+ persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
+ ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
+ BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
+ mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
+ ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())
+ .setPollPeriod(Duration.PRACTICALLY_FOREVER)
+ .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
+ .setLocalTicker(ticker)
+ .setRemoteTicker(ticker)
+ .setPersister(persister);
+ log.info("Created "+nodeName+" "+ownNodeId);
+ }
+
+ public void tearDown() throws Exception {
+ if (ha != null) ha.stop();
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ if (objectStore != null) objectStore.deleteCompletely();
+ }
+
+ private long tickerCurrentMillis() {
+ return ticker.read();
+ }
+
+ private long tickerAdvance(Duration duration) {
+ if (sharedTime!=null)
+ throw new IllegalStateException("Using shared ticker; cannot advance private node clock");
+ currentTime.addAndGet(duration.toMilliseconds());
+ return tickerCurrentMillis();
+ }
+
+ @Override
+ public String toString() {
+ return nodeName+" "+ownNodeId;
+ }
+ }
+
+ private Boolean prevThrowOnRebind;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ prevThrowOnRebind = TestEntityFailingRebind.getThrowOnRebind();
+ TestEntityFailingRebind.setThrowOnRebind(true);
+ nodes.clear();
+ sharedBackingStore.clear();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ try {
+ for (HaMgmtNode n: nodes)
+ n.tearDown();
+ } finally {
+ if (prevThrowOnRebind != null) TestEntityFailingRebind.setThrowOnRebind(prevThrowOnRebind);
+ }
+ }
+
+ public HaMgmtNode newNode() throws Exception {
+ HaMgmtNode node = new HaMgmtNode();
+ node.setUp();
+ nodes.add(node);
+ return node;
+ }
+
+ private void sharedTickerAdvance(Duration duration) {
+ if (sharedTime==null) {
+ for (HaMgmtNode n: nodes)
+ n.tickerAdvance(duration);
+ } else {
+ sharedTime.addAndGet(duration.toMilliseconds());
+ }
+ }
+
+ private long sharedTickerCurrentMillis() {
+ return sharedTime.get();
+ }
+
+ protected void useSharedTime() {
+ if (!nodes.isEmpty())
+ throw new IllegalStateException("shared time must be set up before any nodes created");
+ sharedTime = new AtomicLong(System.currentTimeMillis());
+ }
+
+ protected ManagementContextInternal newLocalManagementContext() {
+ return new LocalManagementContextForTests();
+ }
+
+ protected PersistenceObjectStore newPersistenceObjectStore() {
+ return new InMemoryObjectStore(sharedBackingStore, sharedBackingStoreDates);
+ }
+
+ @Test
+ public void testDoubleRebindFails() throws Exception {
+ useSharedTime();
+ HaMgmtNode n1 = newNode();
+ HaMgmtNode n2 = newNode();
+
+ // first auto should become master
+ n1.ha.start(HighAvailabilityMode.AUTO);
+ n2.ha.start(HighAvailabilityMode.AUTO);
+ assertEquals(n1.ha.getNodeState(), ManagementNodeState.MASTER);
+
+ TestApplication app = ApplicationBuilder.newManagedApp(
+ EntitySpec.create(TestApplication.class).impl(TestEntityFailingRebind.class), n1.mgmt);
+ app.start(ImmutableList.<Location>of());
+
+ n1.mgmt.getRebindManager().forcePersistNow(false, null);
+
+ //don't publish state for a while (i.e. long store delays, failures)
+ sharedTickerAdvance(Duration.ONE_MINUTE);
+
+ try {
+ n2.ha.publishAndCheck(false);
+ fail("n2 rebind failure expected");
+ } catch (Exception e) {
+ assertNestedRebindException(e);
+ }
+
+ // re-check should re-assert successfully, no rebind expected as he was previously master
+ n1.ha.publishAndCheck(false);
+ ManagementPlaneSyncRecord memento;
+ memento = n1.ha.loadManagementPlaneSyncRecord(true);
+ assertEquals(memento.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.MASTER);
+ assertEquals(memento.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.FAILED);
+
+ // hot backup permitted by the TestEntityFailingRebind
+ n1.ha.changeMode(HighAvailabilityMode.HOT_BACKUP);
+ memento = n1.ha.loadManagementPlaneSyncRecord(true);
+ assertEquals(memento.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.HOT_BACKUP);
+ try {
+ n1.ha.changeMode(HighAvailabilityMode.MASTER);
+ fail("n1 rebind failure expected");
+ } catch (Exception e) {
+ assertNestedRebindException(e);
+ }
+
+ memento = n1.ha.loadManagementPlaneSyncRecord(true);
+ assertEquals(memento.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.FAILED);
+ assertEquals(memento.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.FAILED);
+ }
+
+ @Test
+ public void testStandbyRebind() throws Exception {
+ useSharedTime();
+ HaMgmtNode n1 = newNode();
+ HaMgmtNode n2 = newNode();
+
+ // first auto should become master
+ n1.ha.start(HighAvailabilityMode.AUTO);
+ n2.ha.start(HighAvailabilityMode.AUTO);
+
+ TestApplication app = ApplicationBuilder.newManagedApp(
+ EntitySpec.create(TestApplication.class).impl(TestEntityFailingRebind.class), n1.mgmt);
+ app.start(ImmutableList.<Location>of());
+
+ n1.mgmt.getRebindManager().forcePersistNow(false, null);
+
+ //don't publish state for a while (i.e. long store delays, failures)
+ sharedTickerAdvance(Duration.ONE_MINUTE);
+
+ try {
+ n2.ha.publishAndCheck(false);
+ fail("n2 rebind failure expected");
+ } catch (Exception e) {
+ assertNestedRebindException(e);
+ }
+
+ TestEntityFailingRebind.setThrowOnRebind(false);
+ n1.ha.publishAndCheck(false);
+
+ ManagementPlaneSyncRecord memento = n1.ha.loadManagementPlaneSyncRecord(true);
+ assertEquals(memento.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.MASTER);
+ assertEquals(memento.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.FAILED);
+ }
+
+ private void assertNestedRebindException(Throwable t) {
+ Throwable ptr = t;
+ while (ptr != null) {
+ if (ptr instanceof RebindException) {
+ return;
+ }
+ ptr = ptr.getCause();
+ }
+ Exceptions.propagate(t);
+ }
+
+ @Test
+ public void testIfNodeStopsBeingAbleToWrite() throws Exception {
+ useSharedTime();
+ log.info("time at start "+sharedTickerCurrentMillis());
+
+ HaMgmtNode n1 = newNode();
+ HaMgmtNode n2 = newNode();
+
+ // first auto should become master
+ n1.ha.start(HighAvailabilityMode.AUTO);
+ ManagementPlaneSyncRecord memento1 = n1.ha.loadManagementPlaneSyncRecord(true);
+
+ log.info(n1+" HA: "+memento1);
+ assertEquals(memento1.getMasterNodeId(), n1.ownNodeId);
+ Long time0 = sharedTickerCurrentMillis();
+ assertEquals(memento1.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time0);
+ assertEquals(memento1.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.MASTER);
+
+ // second - make explicit hot; that's a strictly more complex case than cold standby, so provides pretty good coverage
+ n2.ha.start(HighAvailabilityMode.HOT_STANDBY);
+ ManagementPlaneSyncRecord memento2 = n2.ha.loadManagementPlaneSyncRecord(true);
+
+ log.info(n2+" HA: "+memento2);
+ assertEquals(memento2.getMasterNodeId(), n1.ownNodeId);
+ assertEquals(memento2.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.MASTER);
+ assertEquals(memento2.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.HOT_STANDBY);
+ assertEquals(memento2.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time0);
+ assertEquals(memento2.getManagementNodes().get(n2.ownNodeId).getRemoteTimestamp(), time0);
+
+ // and no entities at either
+ assertEquals(n1.mgmt.getApplications().size(), 0);
+ assertEquals(n2.mgmt.getApplications().size(), 0);
+
+ // create
+ TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class), n1.mgmt);
+ app.start(ImmutableList.<Location>of());
+ app.setAttribute(TestApplication.MY_ATTRIBUTE, "hello");
+
+ assertEquals(n1.mgmt.getApplications().size(), 1);
+ assertEquals(n2.mgmt.getApplications().size(), 0);
+ log.info("persisting "+n1.ownNodeId);
+ n1.mgmt.getRebindManager().forcePersistNow(false, null);
+
+ n1.objectStore.setWritesFailSilently(true);
+ log.info(n1+" writes off");
+ sharedTickerAdvance(Duration.ONE_MINUTE);
+ log.info("time now "+sharedTickerCurrentMillis());
+ Long time1 = sharedTickerCurrentMillis();
+
+ log.info("publish "+n2.ownNodeId);
+ n2.ha.publishAndCheck(false);
+ ManagementPlaneSyncRecord memento2b = n2.ha.loadManagementPlaneSyncRecord(true);
+ log.info(n2+" HA now: "+memento2b);
+
+ // n2 infers n1 as failed
+ assertEquals(memento2b.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.FAILED);
+ assertEquals(memento2b.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.MASTER);
+ assertEquals(memento2b.getMasterNodeId(), n2.ownNodeId);
+ assertEquals(memento2b.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time0);
+ assertEquals(memento2b.getManagementNodes().get(n2.ownNodeId).getRemoteTimestamp(), time1);
+
+ assertEquals(n1.mgmt.getApplications().size(), 1);
+ assertEquals(n2.mgmt.getApplications().size(), 1);
+ assertEquals(n1.mgmt.getApplications().iterator().next().getAttribute(TestApplication.MY_ATTRIBUTE), "hello");
+
+ n1.objectStore.setWritesFailSilently(false);
+ log.info(n1+" writes on");
+
+ sharedTickerAdvance(Duration.ONE_SECOND);
+ log.info("time now "+sharedTickerCurrentMillis());
+ Long time2 = sharedTickerCurrentMillis();
+
+ log.info("publish "+n1.ownNodeId);
+ n1.ha.publishAndCheck(false);
+ ManagementPlaneSyncRecord memento1b = n1.ha.loadManagementPlaneSyncRecord(true);
+ log.info(n1+" HA now: "+memento1b);
+
+ ManagementNodeState expectedStateAfterDemotion = BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY) ?
+ ManagementNodeState.HOT_STANDBY : ManagementNodeState.STANDBY;
+
+ // n1 comes back and demotes himself
+ assertEquals(memento1b.getManagementNodes().get(n1.ownNodeId).getStatus(), expectedStateAfterDemotion);
+ assertEquals(memento1b.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.MASTER);
+ assertEquals(memento1b.getMasterNodeId(), n2.ownNodeId);
+ assertEquals(memento1b.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time2);
+ assertEquals(memento1b.getManagementNodes().get(n2.ownNodeId).getRemoteTimestamp(), time1);
+
+ // n2 now sees itself as master, with n1 in standby again
+ ManagementPlaneSyncRecord memento2c = n2.ha.loadManagementPlaneSyncRecord(true);
+ log.info(n2+" HA now: "+memento2c);
+ assertEquals(memento2c.getManagementNodes().get(n1.ownNodeId).getStatus(), expectedStateAfterDemotion);
+ assertEquals(memento2c.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.MASTER);
+ assertEquals(memento2c.getMasterNodeId(), n2.ownNodeId);
+ assertEquals(memento2c.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time2);
+ assertEquals(memento2c.getManagementNodes().get(n2.ownNodeId).getRemoteTimestamp(), time2);
+
+ // right number of entities at n2; n1 may or may not depending whether hot standby is default
+ assertEquals(n2.mgmt.getApplications().size(), 1);
+ assertEquals(n1.mgmt.getApplications().size(), BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY) ? 1 : 0);
+ }
+
+ @Test(invocationCount=50, groups="Integration")
+ public void testIfNodeStopsBeingAbleToWriteManyTimes() throws Exception {
+ testIfNodeStopsBeingAbleToWrite();
+ }
+
+ @Test
+ public void testSimultaneousStartup() throws Exception {
+ doTestConcurrentStartup(5, null);
+ }
+
+ @Test
+ public void testNearSimultaneousStartup() throws Exception {
+ doTestConcurrentStartup(20, Duration.millis(20));
+ }
+
+ @Test(invocationCount=50, groups="Integration")
+ public void testNearSimultaneousStartupManyTimes() throws Exception {
+ doTestConcurrentStartup(20, Duration.millis(20));
+ }
+
+ protected void doTestConcurrentStartup(int size, final Duration staggerStart) throws Exception {
+ useSharedTime();
+
+ List<Thread> spawned = MutableList.of();
+ for (int i=0; i<size; i++) {
+ final HaMgmtNode n = newNode();
+ Thread t = new Thread() { public void run() {
+ if (staggerStart!=null) Time.sleep(staggerStart.multiply(Math.random()));
+ n.ha.start(HighAvailabilityMode.AUTO);
+ n.ha.setPollPeriod(Duration.millis(20));
+ } };
+ spawned.add(t);
+ t.start();
+ }
+
+ try {
+ final Stopwatch timer = Stopwatch.createStarted();
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ ManagementPlaneSyncRecord memento = nodes.get(0).ha.loadManagementPlaneSyncRecord(true);
+ List<ManagementNodeState> counts = MutableList.of(), savedCounts = MutableList.of();
+ for (HaMgmtNode n: nodes) {
+ counts.add(n.ha.getNodeState());
+ ManagementNodeSyncRecord m = memento.getManagementNodes().get(n.ownNodeId);
+ if (m!=null) {
+ savedCounts.add(m.getStatus());
+ }
+ }
+ log.info("while starting "+nodes.size()+" nodes: "
+ +Collections.frequency(counts, ManagementNodeState.MASTER)+" M + "
+ +Collections.frequency(counts, ManagementNodeState.HOT_STANDBY)+" hot + "
+ +Collections.frequency(counts, ManagementNodeState.STANDBY)+" warm + "
+ +Collections.frequency(counts, ManagementNodeState.INITIALIZING)+" init; "
+ + memento.getManagementNodes().size()+" saved, "
+ +Collections.frequency(savedCounts, ManagementNodeState.MASTER)+" M + "
+ +Collections.frequency(savedCounts, ManagementNodeState.HOT_STANDBY)+" hot + "
+ +Collections.frequency(savedCounts, ManagementNodeState.STANDBY)+" warm + "
+ +Collections.frequency(savedCounts, ManagementNodeState.INITIALIZING)+" init");
+
+ if (timer.isRunning() && Duration.of(timer).compareTo(Duration.TEN_SECONDS)>0) {
+ log.warn("we seem to have a problem stabilizing"); //handy place to set a suspend-VM breakpoint!
+ timer.stop();
+ }
+ assertEquals(Collections.frequency(counts, ManagementNodeState.MASTER), 1);
+ assertEquals(Collections.frequency(counts, ManagementNodeState.HOT_STANDBY)+Collections.frequency(counts, ManagementNodeState.STANDBY), nodes.size()-1);
+ assertEquals(Collections.frequency(savedCounts, ManagementNodeState.MASTER), 1);
+ assertEquals(Collections.frequency(savedCounts, ManagementNodeState.HOT_STANDBY)+Collections.frequency(savedCounts, ManagementNodeState.STANDBY), nodes.size()-1);
+ }});
+ } catch (Throwable t) {
+ log.warn("Failed to stabilize (rethrowing): "+t, t);
+ throw Exceptions.propagate(t);
+ }
+
+ for (Thread t: spawned)
+ t.join(Duration.THIRTY_SECONDS.toMilliseconds());
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerTestFixture.java
new file mode 100644
index 0000000..5a7f79a
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerTestFixture.java
@@ -0,0 +1,287 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordDeltaImpl;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl.PromotionListener;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.BrooklynVersion;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
+import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord.Builder;
+import brooklyn.test.Asserts;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Ticker;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+
+@Test
+public abstract class HighAvailabilityManagerTestFixture {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(HighAvailabilityManagerTestFixture.class);
+
+ private ManagementPlaneSyncRecordPersister persister;
+ protected ManagementContextInternal managementContext;
+ private String ownNodeId;
+ private HighAvailabilityManagerImpl manager;
+ private Ticker ticker;
+ private AtomicLong currentTime; // used to set the ticker's return value
+ private RecordingPromotionListener promotionListener;
+ private ClassLoader classLoader = getClass().getClassLoader();
+ private PersistenceObjectStore objectStore;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ currentTime = new AtomicLong(1000000000L);
+ ticker = new Ticker() {
+ // strictly not a ticker because returns millis UTC, but it works fine even so
+ @Override public long read() {
+ return currentTime.get();
+ }
+ };
+ promotionListener = new RecordingPromotionListener();
+ managementContext = newLocalManagementContext();
+ ownNodeId = managementContext.getManagementNodeId();
+ objectStore = newPersistenceObjectStore();
+ objectStore.injectManagementContext(managementContext);
+ objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
+ persister = new ManagementPlaneSyncRecordPersisterToObjectStore(managementContext, objectStore, classLoader);
+ ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
+ BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(
+ objectStore,
+ managementContext.getBrooklynProperties(),
+ classLoader);
+ managementContext.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
+ manager = ((HighAvailabilityManagerImpl)managementContext.getHighAvailabilityManager())
+ .setPollPeriod(getPollPeriod())
+ .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
+ .setPromotionListener(promotionListener)
+ .setLocalTicker(ticker)
+ .setRemoteTicker(getRemoteTicker())
+ .setPersister(persister);
+ persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
+ .node(newManagerMemento(ownNodeId, ManagementNodeState.HOT_STANDBY))
+ .build());
+
+ }
+
+ protected ManagementContextInternal newLocalManagementContext() {
+ return LocalManagementContextForTests.newInstance();
+ }
+
+ protected abstract PersistenceObjectStore newPersistenceObjectStore();
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (manager != null) manager.stop();
+ if (managementContext != null) Entities.destroyAll(managementContext);
+ if (objectStore != null) objectStore.deleteCompletely();
+ }
+
+ // The web-console could still be polling (e.g. if have just restarted brooklyn), before the persister is set.
+ // Must not throw NPE, but instead return something sensible (e.g. an empty state record).
+ @Test
+ public void testGetManagementPlaneSyncStateDoesNotThrowNpeBeforePersisterSet() throws Exception {
+ HighAvailabilityManagerImpl manager2 = new HighAvailabilityManagerImpl(managementContext)
+ .setPollPeriod(Duration.millis(10))
+ .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
+ .setPromotionListener(promotionListener)
+ .setLocalTicker(ticker)
+ .setRemoteTicker(ticker);
+ try {
+ ManagementPlaneSyncRecord state = manager2.loadManagementPlaneSyncRecord(true);
+ assertNotNull(state);
+ } finally {
+ manager2.stop();
+ }
+
+ }
+ // Can get a log.error about our management node's heartbeat being out of date. Caused by
+ // poller first writing a heartbeat record, and then the clock being incremented. But the
+ // next poll fixes it.
+ public void testPromotes() throws Exception {
+ persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
+ .node(newManagerMemento(ownNodeId, ManagementNodeState.HOT_STANDBY))
+ .node(newManagerMemento("node1", ManagementNodeState.MASTER))
+ .setMaster("node1")
+ .build());
+
+ manager.start(HighAvailabilityMode.AUTO);
+
+ // Simulate passage of time; ticker used by this HA-manager so it will "correctly" publish
+ // its own heartbeat with the new time; but node1's record is now out-of-date.
+ tickerAdvance(Duration.seconds(31));
+
+ // Expect to be notified of our promotion, as the only other node
+ promotionListener.assertCalledEventually();
+ }
+
+ @Test(groups="Integration") // because one second wait in succeedsContinually
+ public void testDoesNotPromoteIfMasterTimeoutNotExpired() throws Exception {
+ persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
+ .node(newManagerMemento(ownNodeId, ManagementNodeState.HOT_STANDBY))
+ .node(newManagerMemento("node1", ManagementNodeState.MASTER))
+ .setMaster("node1")
+ .build());
+
+ manager.start(HighAvailabilityMode.AUTO);
+
+ tickerAdvance(Duration.seconds(25));
+
+ // Expect not to be notified, as 25s < 30s timeout
+ // (it's normally a fake clock so won't hit 30, even waiting 1s below - but in "IntegrationTest" subclasses it is real!)
+ Asserts.succeedsContinually(new Runnable() {
+ @Override public void run() {
+ assertTrue(promotionListener.callTimestamps.isEmpty(), "calls="+promotionListener.callTimestamps);
+ }});
+ }
+
+ public void testGetManagementPlaneStatus() throws Exception {
+ // with the name zzzzz the mgr created here should never be promoted by the alphabetical strategy!
+
+ tickerAdvance(Duration.FIVE_SECONDS);
+ persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
+ .node(newManagerMemento(ownNodeId, ManagementNodeState.STANDBY))
+ .node(newManagerMemento("zzzzzzz_node1", ManagementNodeState.STANDBY))
+ .build());
+ persister.loadSyncRecord();
+ long zzzTime = tickerCurrentMillis();
+ tickerAdvance(Duration.FIVE_SECONDS);
+
+ manager.start(HighAvailabilityMode.AUTO);
+ ManagementPlaneSyncRecord memento = manager.loadManagementPlaneSyncRecord(true);
+
+ // Note can assert timestamp because not "real" time; it's using our own Ticker
+ assertEquals(memento.getMasterNodeId(), ownNodeId);
+ assertEquals(memento.getManagementNodes().keySet(), ImmutableSet.of(ownNodeId, "zzzzzzz_node1"));
+ assertEquals(memento.getManagementNodes().get(ownNodeId).getNodeId(), ownNodeId);
+ assertEquals(memento.getManagementNodes().get(ownNodeId).getStatus(), ManagementNodeState.MASTER);
+ assertEquals(memento.getManagementNodes().get(ownNodeId).getLocalTimestamp(), tickerCurrentMillis());
+ assertEquals(memento.getManagementNodes().get("zzzzzzz_node1").getNodeId(), "zzzzzzz_node1");
+ assertEquals(memento.getManagementNodes().get("zzzzzzz_node1").getStatus(), ManagementNodeState.STANDBY);
+ assertEquals(memento.getManagementNodes().get("zzzzzzz_node1").getLocalTimestamp(), zzzTime);
+ }
+
+ @Test(groups="Integration", invocationCount=50) //because we have had non-deterministic failures
+ public void testGetManagementPlaneStatusManyTimes() throws Exception {
+ testGetManagementPlaneStatus();
+ }
+
+ @Test
+ public void testGetManagementPlaneSyncStateInfersTimedOutNodeAsFailed() throws Exception {
+ persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
+ .node(newManagerMemento(ownNodeId, ManagementNodeState.HOT_STANDBY))
+ .node(newManagerMemento("node1", ManagementNodeState.MASTER))
+ .setMaster("node1")
+ .build());
+
+ manager.start(HighAvailabilityMode.HOT_STANDBY);
+
+ ManagementPlaneSyncRecord state = manager.loadManagementPlaneSyncRecord(true);
+ assertEquals(state.getManagementNodes().get("node1").getStatus(), ManagementNodeState.MASTER);
+ assertEquals(state.getManagementNodes().get(ownNodeId).getStatus(), ManagementNodeState.HOT_STANDBY);
+
+ // Simulate passage of time; ticker used by this HA-manager so it will "correctly" publish
+ // its own heartbeat with the new time; but node1's record is now out-of-date.
+ tickerAdvance(Duration.seconds(31));
+
+ ManagementPlaneSyncRecord state2 = manager.loadManagementPlaneSyncRecord(true);
+ assertEquals(state2.getManagementNodes().get("node1").getStatus(), ManagementNodeState.FAILED);
+ assertNotEquals(state.getManagementNodes().get(ownNodeId).getStatus(), ManagementNodeState.FAILED);
+ }
+
+ protected Duration getPollPeriod() {
+ return Duration.millis(10);
+ }
+
+ protected long tickerCurrentMillis() {
+ return ticker.read();
+ }
+
+ protected long tickerAdvance(Duration duration) {
+ currentTime.addAndGet(duration.toMilliseconds());
+ return tickerCurrentMillis();
+ }
+
+ protected Ticker getRemoteTicker() {
+ return ticker;
+ }
+
+ protected ManagementNodeSyncRecord newManagerMemento(String nodeId, ManagementNodeState status) {
+ Builder rb = BasicManagementNodeSyncRecord.builder();
+ rb.brooklynVersion(BrooklynVersion.get()).nodeId(nodeId).status(status);
+ rb.localTimestamp(tickerCurrentMillis());
+ if (getRemoteTicker()!=null)
+ rb.remoteTimestamp(getRemoteTicker().read());
+ return rb.build();
+ }
+
+ public static class RecordingPromotionListener implements PromotionListener {
+ public final List<Long> callTimestamps = Lists.newCopyOnWriteArrayList();
+
+ @Override
+ public void promotingToMaster() {
+ callTimestamps.add(System.currentTimeMillis());
+ }
+
+ public void assertNotCalled() {
+ assertTrue(callTimestamps.isEmpty(), "calls="+callTimestamps);
+ }
+
+ public void assertCalled() {
+ assertFalse(callTimestamps.isEmpty(), "calls="+callTimestamps);
+ }
+
+ public void assertCalledEventually() {
+ Asserts.succeedsEventually(new Runnable() {
+ @Override public void run() {
+ assertCalled();
+ }});
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/HotStandbyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/HotStandbyTest.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/HotStandbyTest.java
new file mode 100644
index 0000000..da4f998
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/HotStandbyTest.java
@@ -0,0 +1,667 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.ArrayDeque;
+import java.util.Date;
+import java.util.Deque;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Feed;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import org.apache.brooklyn.core.management.internal.AbstractManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.test.EntityTestUtils;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
+import brooklyn.entity.rebind.RebindFeedTest.MyEntityWithFunctionFeedImpl;
+import brooklyn.entity.rebind.RebindFeedTest.MyEntityWithNewFeedsEachTimeImpl;
+import brooklyn.entity.rebind.RebindManagerImpl;
+import brooklyn.entity.rebind.RebindTestFixture;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.InMemoryObjectStore;
+import brooklyn.entity.rebind.persister.ListeningObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+
+import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation.LocalhostMachine;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.text.ByteSizeStrings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.collect.Iterables;
+
+public class HotStandbyTest {
+
+ private static final Logger log = LoggerFactory.getLogger(HotStandbyTest.class);
+
+ private List<HaMgmtNode> nodes = new MutableList<HotStandbyTest.HaMgmtNode>();
+ Map<String,String> sharedBackingStore = MutableMap.of();
+ Map<String,Date> sharedBackingStoreDates = MutableMap.of();
+ private ClassLoader classLoader = getClass().getClassLoader();
+
+ public class HaMgmtNode {
+ // TODO share with WarmStandbyTest and SplitBrainTest and a few others (minor differences but worth it ultimately)
+
+ private ManagementContextInternal mgmt;
+ private String ownNodeId;
+ private String nodeName;
+ private ListeningObjectStore objectStore;
+ private ManagementPlaneSyncRecordPersister persister;
+ private HighAvailabilityManagerImpl ha;
+ private Duration persistOrRebindPeriod = Duration.ONE_SECOND;
+
+ public void setUp() throws Exception {
+ nodeName = "node "+nodes.size();
+ mgmt = newLocalManagementContext();
+ ownNodeId = mgmt.getManagementNodeId();
+ objectStore = new ListeningObjectStore(newPersistenceObjectStore());
+ objectStore.injectManagementContext(mgmt);
+ objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
+ persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
+ ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
+ BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
+ ((RebindManagerImpl)mgmt.getRebindManager()).setPeriodicPersistPeriod(persistOrRebindPeriod);
+ mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
+ ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())
+ .setPollPeriod(Duration.PRACTICALLY_FOREVER)
+ .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
+ .setPersister(persister);
+ log.info("Created "+nodeName+" "+ownNodeId);
+ }
+
+ public void tearDownThisOnly() throws Exception {
+ if (ha != null) ha.stop();
+ if (mgmt!=null) mgmt.getRebindManager().stop();
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ }
+
+ public void tearDownAll() throws Exception {
+ tearDownThisOnly();
+ // can't delete the object store until all being torn down
+ if (objectStore != null) objectStore.deleteCompletely();
+ }
+
+ @Override
+ public String toString() {
+ return nodeName+" "+ownNodeId;
+ }
+
+ public RebindManagerImpl rebinder() {
+ return (RebindManagerImpl)mgmt.getRebindManager();
+ }
+ }
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ nodes.clear();
+ sharedBackingStore.clear();
+ }
+
+ public HaMgmtNode newNode(Duration persistOrRebindPeriod) throws Exception {
+ HaMgmtNode node = new HaMgmtNode();
+ node.persistOrRebindPeriod = persistOrRebindPeriod;
+ node.setUp();
+ nodes.add(node);
+ return node;
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ for (HaMgmtNode n: nodes)
+ n.tearDownAll();
+ }
+
+ protected ManagementContextInternal newLocalManagementContext() {
+ return new LocalManagementContextForTests();
+ }
+
+ protected PersistenceObjectStore newPersistenceObjectStore() {
+ return new InMemoryObjectStore(sharedBackingStore, sharedBackingStoreDates);
+ }
+
+ private HaMgmtNode createMaster(Duration persistOrRebindPeriod) throws Exception {
+ HaMgmtNode n1 = newNode(persistOrRebindPeriod);
+ n1.ha.start(HighAvailabilityMode.AUTO);
+ assertEquals(n1.ha.getNodeState(), ManagementNodeState.MASTER);
+ return n1;
+ }
+
+ private HaMgmtNode createHotStandby(Duration rebindPeriod) throws Exception {
+ HaMgmtNode n2 = newNode(rebindPeriod);
+ n2.ha.start(HighAvailabilityMode.HOT_STANDBY);
+ assertEquals(n2.ha.getNodeState(), ManagementNodeState.HOT_STANDBY);
+ return n2;
+ }
+
+ private TestApplication createFirstAppAndPersist(HaMgmtNode n1) throws Exception {
+ TestApplication app = TestApplication.Factory.newManagedInstanceForTests(n1.mgmt);
+ // for testing without enrichers, if desired:
+// TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).impl(TestApplicationNoEnrichersImpl.class), n1.mgmt);
+ app.setDisplayName("First App");
+ app.start(MutableList.<Location>of());
+ app.config().set(TestEntity.CONF_NAME, "first-app");
+ app.setAttribute(TestEntity.SEQUENCE, 3);
+
+ forcePersistNow(n1);
+ return app;
+ }
+
+ protected void forcePersistNow(HaMgmtNode n1) {
+ n1.mgmt.getRebindManager().forcePersistNow(false, null);
+ }
+
+ private Application expectRebindSequenceNumber(HaMgmtNode master, HaMgmtNode hotStandby, Application app, int expectedSensorSequenceValue, boolean immediate) {
+ Application appRO = hotStandby.mgmt.lookup(app.getId(), Application.class);
+
+ if (immediate) {
+ forcePersistNow(master);
+ forceRebindNow(hotStandby);
+ EntityTestUtils.assertAttributeEquals(appRO, TestEntity.SEQUENCE, expectedSensorSequenceValue);
+ } else {
+ EntityTestUtils.assertAttributeEqualsEventually(appRO, TestEntity.SEQUENCE, expectedSensorSequenceValue);
+ }
+
+ log.info("got sequence number "+expectedSensorSequenceValue+" from "+appRO);
+
+ // make sure the instance (proxy) is unchanged
+ Application appRO2 = hotStandby.mgmt.lookup(app.getId(), Application.class);
+ Assert.assertTrue(appRO2==appRO);
+
+ return appRO;
+ }
+
+ private void forceRebindNow(HaMgmtNode hotStandby) {
+ hotStandby.mgmt.getRebindManager().rebind(null, null, ManagementNodeState.HOT_STANDBY);
+ }
+
+ @Test
+ public void testHotStandbySeesInitialCustomNameConfigAndSensorValueButDoesntAllowChange() throws Exception {
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ TestApplication app = createFirstAppAndPersist(n1);
+ HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
+
+ assertEquals(n2.mgmt.getApplications().size(), 1);
+ Application appRO = n2.mgmt.lookup(app.getId(), Application.class);
+ Assert.assertNotNull(appRO);
+ Assert.assertTrue(appRO instanceof TestApplication);
+ assertEquals(appRO.getDisplayName(), "First App");
+ assertEquals(appRO.getConfig(TestEntity.CONF_NAME), "first-app");
+ assertEquals(appRO.getAttribute(TestEntity.SEQUENCE), (Integer)3);
+
+ try {
+ ((TestApplication)appRO).setAttribute(TestEntity.SEQUENCE, 4);
+ Assert.fail("Should not have allowed sensor to be set");
+ } catch (Exception e) {
+ Assert.assertTrue(e.toString().toLowerCase().contains("read-only"), "Error message did not contain expected text: "+e);
+ }
+ assertEquals(appRO.getAttribute(TestEntity.SEQUENCE), (Integer)3);
+ }
+
+ @Test
+ public void testHotStandbySeesChangesToNameConfigAndSensorValue() throws Exception {
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ TestApplication app = createFirstAppAndPersist(n1);
+ HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
+
+ assertEquals(n2.mgmt.getApplications().size(), 1);
+ Application appRO = n2.mgmt.lookup(app.getId(), Application.class);
+ Assert.assertNotNull(appRO);
+ assertEquals(appRO.getChildren().size(), 0);
+
+ // test changes
+
+ app.setDisplayName("First App Renamed");
+ app.config().set(TestEntity.CONF_NAME, "first-app-renamed");
+ app.setAttribute(TestEntity.SEQUENCE, 4);
+
+ appRO = expectRebindSequenceNumber(n1, n2, app, 4, true);
+ assertEquals(n2.mgmt.getEntityManager().getEntities().size(), 1);
+ assertEquals(appRO.getDisplayName(), "First App Renamed");
+ assertEquals(appRO.getConfig(TestEntity.CONF_NAME), "first-app-renamed");
+
+ // and change again for good measure!
+
+ app.setDisplayName("First App");
+ app.config().set(TestEntity.CONF_NAME, "first-app-restored");
+ app.setAttribute(TestEntity.SEQUENCE, 5);
+
+ appRO = expectRebindSequenceNumber(n1, n2, app, 5, true);
+ assertEquals(n2.mgmt.getEntityManager().getEntities().size(), 1);
+ assertEquals(appRO.getDisplayName(), "First App");
+ assertEquals(appRO.getConfig(TestEntity.CONF_NAME), "first-app-restored");
+ }
+
+
+ public void testHotStandbySeesStructuralChangesIncludingRemoval() throws Exception {
+ doTestHotStandbySeesStructuralChangesIncludingRemoval(true);
+ }
+
+ @Test(groups="Integration") // due to time (it waits for background persistence)
+ public void testHotStandbyUnforcedSeesStructuralChangesIncludingRemoval() throws Exception {
+ doTestHotStandbySeesStructuralChangesIncludingRemoval(false);
+ }
+
+ public void doTestHotStandbySeesStructuralChangesIncludingRemoval(boolean immediate) throws Exception {
+ HaMgmtNode n1 = createMaster(immediate ? Duration.PRACTICALLY_FOREVER : Duration.millis(200));
+ TestApplication app = createFirstAppAndPersist(n1);
+ HaMgmtNode n2 = createHotStandby(immediate ? Duration.PRACTICALLY_FOREVER : Duration.millis(200));
+
+ assertEquals(n2.mgmt.getApplications().size(), 1);
+ Application appRO = n2.mgmt.lookup(app.getId(), Application.class);
+ Assert.assertNotNull(appRO);
+ assertEquals(appRO.getChildren().size(), 0);
+
+ // test additions - new child, new app
+
+ TestEntity child = app.addChild(EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, "first-child"));
+ Entities.manage(child);
+ TestApplication app2 = TestApplication.Factory.newManagedInstanceForTests(n1.mgmt);
+ app2.config().set(TestEntity.CONF_NAME, "second-app");
+
+ app.setAttribute(TestEntity.SEQUENCE, 4);
+ appRO = expectRebindSequenceNumber(n1, n2, app, 4, immediate);
+
+ assertEquals(appRO.getChildren().size(), 1);
+ Entity childRO = Iterables.getOnlyElement(appRO.getChildren());
+ assertEquals(childRO.getId(), child.getId());
+ assertEquals(childRO.getConfig(TestEntity.CONF_NAME), "first-child");
+
+ assertEquals(n2.mgmt.getApplications().size(), 2);
+ Application app2RO = n2.mgmt.lookup(app2.getId(), Application.class);
+ Assert.assertNotNull(app2RO);
+ assertEquals(app2RO.getConfig(TestEntity.CONF_NAME), "second-app");
+
+ assertEquals(n2.mgmt.getEntityManager().getEntities().size(), 3);
+
+ // now test removals
+
+ Entities.unmanage(child);
+ Entities.unmanage(app2);
+
+ app.setAttribute(TestEntity.SEQUENCE, 5);
+ appRO = expectRebindSequenceNumber(n1, n2, app, 5, immediate);
+
+ EntityTestUtils.assertAttributeEqualsEventually(appRO, TestEntity.SEQUENCE, 5);
+ assertEquals(n2.mgmt.getEntityManager().getEntities().size(), 1);
+ assertEquals(appRO.getChildren().size(), 0);
+ assertEquals(n2.mgmt.getApplications().size(), 1);
+ Assert.assertNull(n2.mgmt.lookup(app2.getId(), Application.class));
+ Assert.assertNull(n2.mgmt.lookup(child.getId(), Application.class));
+ }
+
+ @Test(groups="Integration", invocationCount=50)
+ public void testHotStandbySeesStructuralChangesIncludingRemovalManyTimes() throws Exception {
+ doTestHotStandbySeesStructuralChangesIncludingRemoval(true);
+ }
+
+ Deque<Long> usedMemory = new ArrayDeque<Long>();
+ protected long noteUsedMemory(String message) {
+ Time.sleep(Duration.millis(200));
+ for (HaMgmtNode n: nodes) {
+ ((AbstractManagementContext)n.mgmt).getGarbageCollector().gcIteration();
+ }
+ System.gc(); System.gc();
+ Time.sleep(Duration.millis(50));
+ System.gc(); System.gc();
+ long mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
+ usedMemory.addLast(mem);
+ log.info("Memory used - "+message+": "+ByteSizeStrings.java().apply(mem));
+ return mem;
+ }
+ public void assertUsedMemoryLessThan(String event, long max) {
+ noteUsedMemory(event);
+ long nowUsed = usedMemory.peekLast();
+ if (nowUsed > max) {
+ // aggressively try to force GC
+ Time.sleep(Duration.ONE_SECOND);
+ usedMemory.removeLast();
+ noteUsedMemory(event+" (extra GC)");
+ nowUsed = usedMemory.peekLast();
+ if (nowUsed > max) {
+ Assert.fail("Too much memory used - "+ByteSizeStrings.java().apply(nowUsed)+" > max "+ByteSizeStrings.java().apply(max));
+ }
+ }
+ }
+ public void assertUsedMemoryMaxDelta(String event, long deltaMegabytes) {
+ assertUsedMemoryLessThan(event, usedMemory.peekLast() + deltaMegabytes*1024*1024);
+ }
+
+ @Test(groups="Integration")
+ public void testHotStandbyDoesNotLeakLotsOfRebinds() throws Exception {
+ log.info("Starting test "+JavaClassNames.niceClassAndMethod());
+ final int DELTA = 2;
+
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ TestApplication app = createFirstAppAndPersist(n1);
+ long initialUsed = noteUsedMemory("Created app");
+
+ HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
+ assertUsedMemoryMaxDelta("Standby created", DELTA);
+
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+ assertUsedMemoryMaxDelta("Persisted and rebinded once", DELTA);
+
+ for (int i=0; i<10; i++) {
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+ }
+ assertUsedMemoryMaxDelta("Persisted and rebinded 10x", DELTA);
+
+ for (int i=0; i<1000; i++) {
+ if ((i+1)%100==0) {
+ noteUsedMemory("iteration "+(i+1));
+ usedMemory.removeLast();
+ }
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+ }
+ assertUsedMemoryMaxDelta("Persisted and rebinded 1000x", DELTA);
+
+ Entities.unmanage(app);
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+
+ assertUsedMemoryLessThan("And now all unmanaged", initialUsed + DELTA*1000*1000);
+ }
+
+ static class BigObject {
+ public BigObject(int sizeBytes) { array = new byte[sizeBytes]; }
+ byte[] array;
+ }
+
+ @Test(groups="Integration")
+ public void testHotStandbyDoesNotLeakBigObjects() throws Exception {
+ log.info("Starting test "+JavaClassNames.niceClassAndMethod());
+ final int SIZE = 5;
+ final int SIZE_UP_BOUND = SIZE+2;
+ final int SIZE_DOWN_BOUND = SIZE-1;
+ final int GRACE = 2;
+ // the XML persistence uses a lot of space, we approx at between 2x and 3c
+ final int SIZE_IN_XML = 3*SIZE;
+ final int SIZE_IN_XML_DOWN = 2*SIZE;
+
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ TestApplication app = createFirstAppAndPersist(n1);
+ noteUsedMemory("Finished seeding");
+ Long initialUsed = usedMemory.peekLast();
+ app.config().set(TestEntity.CONF_OBJECT, new BigObject(SIZE*1000*1000));
+ assertUsedMemoryMaxDelta("Set a big config object", SIZE_UP_BOUND);
+ forcePersistNow(n1);
+ assertUsedMemoryMaxDelta("Persisted a big config object", SIZE_IN_XML);
+
+ HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
+ forceRebindNow(n2);
+ assertUsedMemoryMaxDelta("Rebinded", SIZE_UP_BOUND);
+
+ for (int i=0; i<10; i++)
+ forceRebindNow(n2);
+ assertUsedMemoryMaxDelta("Several more rebinds", GRACE);
+ for (int i=0; i<10; i++) {
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+ }
+ assertUsedMemoryMaxDelta("And more rebinds and more persists", GRACE);
+
+ app.config().set(TestEntity.CONF_OBJECT, "big is now small");
+ assertUsedMemoryMaxDelta("Big made small at primary", -SIZE_DOWN_BOUND);
+ forcePersistNow(n1);
+ assertUsedMemoryMaxDelta("And persisted", -SIZE_IN_XML_DOWN);
+
+ forceRebindNow(n2);
+ assertUsedMemoryMaxDelta("And at secondary", -SIZE_DOWN_BOUND);
+
+ Entities.unmanage(app);
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+
+ assertUsedMemoryLessThan("And now all unmanaged", initialUsed+GRACE*1000*1000);
+ }
+
+ @Test(groups="Integration") // because it's slow
+ // Sept 2014 - there is a small leak, of 200 bytes per child created and destroyed;
+ // but this goes away when the app is destroyed; it may be a benign record
+ public void testHotStandbyDoesNotLeakLotsOfRebindsCreatingAndDestroyingAChildEntity() throws Exception {
+ log.info("Starting test "+JavaClassNames.niceClassAndMethod());
+ final int DELTA = 2;
+
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ TestApplication app = createFirstAppAndPersist(n1);
+ long initialUsed = noteUsedMemory("Created app");
+
+ HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
+ assertUsedMemoryMaxDelta("Standby created", DELTA);
+
+ TestEntity lastChild = app.addChild(EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, "first-child"));
+ Entities.manage(lastChild);
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+ assertUsedMemoryMaxDelta("Child created and rebinded once", DELTA);
+
+ for (int i=0; i<1000; i++) {
+ if (i==9 || (i+1)%100==0) {
+ noteUsedMemory("iteration "+(i+1));
+ usedMemory.removeLast();
+ }
+ TestEntity newChild = app.addChild(EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, "first-child"));
+ Entities.manage(newChild);
+ Entities.unmanage(lastChild);
+ lastChild = newChild;
+
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+ }
+ assertUsedMemoryMaxDelta("Persisted and rebinded 1000x", DELTA);
+
+ Entities.unmanage(app);
+ forcePersistNow(n1);
+ forceRebindNow(n2);
+
+ assertUsedMemoryLessThan("And now all unmanaged", initialUsed + DELTA*1000*1000);
+ }
+
+ protected void assertHotStandby(HaMgmtNode n1) {
+ assertEquals(n1.ha.getNodeState(), ManagementNodeState.HOT_STANDBY);
+ Assert.assertTrue(n1.rebinder().isReadOnlyRunning());
+ Assert.assertFalse(n1.rebinder().isPersistenceRunning());
+ }
+
+ protected void assertMaster(HaMgmtNode n1) {
+ assertEquals(n1.ha.getNodeState(), ManagementNodeState.MASTER);
+ Assert.assertFalse(n1.rebinder().isReadOnlyRunning());
+ Assert.assertTrue(n1.rebinder().isPersistenceRunning());
+ }
+
+ @Test
+ public void testChangeMode() throws Exception {
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ TestApplication app = createFirstAppAndPersist(n1);
+ HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
+
+ TestEntity child = app.addChild(EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, "first-child"));
+ Entities.manage(child);
+ TestApplication app2 = TestApplication.Factory.newManagedInstanceForTests(n1.mgmt);
+ app2.config().set(TestEntity.CONF_NAME, "second-app");
+
+ forcePersistNow(n1);
+ n2.ha.setPriority(1);
+ n1.ha.changeMode(HighAvailabilityMode.HOT_STANDBY);
+
+ // both now hot standby
+ assertHotStandby(n1);
+ assertHotStandby(n2);
+
+ assertEquals(n1.mgmt.getApplications().size(), 2);
+ Application app2RO = n1.mgmt.lookup(app2.getId(), Application.class);
+ Assert.assertNotNull(app2RO);
+ assertEquals(app2RO.getConfig(TestEntity.CONF_NAME), "second-app");
+ try {
+ ((TestApplication)app2RO).setAttribute(TestEntity.SEQUENCE, 4);
+ Assert.fail("Should not have allowed sensor to be set");
+ } catch (Exception e) {
+ Assert.assertTrue(e.toString().toLowerCase().contains("read-only"), "Error message did not contain expected text: "+e);
+ }
+
+ n1.ha.changeMode(HighAvailabilityMode.AUTO);
+ n2.ha.changeMode(HighAvailabilityMode.HOT_STANDBY, true, false);
+ // both still hot standby (n1 will defer to n2 as it has higher priority)
+ assertHotStandby(n1);
+ assertHotStandby(n2);
+
+ // with priority 1, n2 will now be elected
+ n2.ha.changeMode(HighAvailabilityMode.AUTO);
+ assertHotStandby(n1);
+ assertMaster(n2);
+
+ assertEquals(n2.mgmt.getApplications().size(), 2);
+ Application app2B = n2.mgmt.lookup(app2.getId(), Application.class);
+ Assert.assertNotNull(app2B);
+ assertEquals(app2B.getConfig(TestEntity.CONF_NAME), "second-app");
+ ((TestApplication)app2B).setAttribute(TestEntity.SEQUENCE, 4);
+
+ forcePersistNow(n2);
+ forceRebindNow(n1);
+ Application app2BRO = n1.mgmt.lookup(app2.getId(), Application.class);
+ Assert.assertNotNull(app2BRO);
+ EntityTestUtils.assertAttributeEquals(app2BRO, TestEntity.SEQUENCE, 4);
+ }
+
+ @Test(groups="Integration", invocationCount=20)
+ public void testChangeModeManyTimes() throws Exception {
+ testChangeMode();
+ }
+
+ @Test
+ public void testChangeModeToDisabledAndBack() throws Exception {
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ n1.mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachine.class));
+ @SuppressWarnings("unused")
+ TestApplication app = createFirstAppAndPersist(n1);
+
+ HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
+
+ // disabled n1 allows n2 to become master when next we tell it to check
+ n1.ha.changeMode(HighAvailabilityMode.DISABLED);
+ n2.ha.changeMode(HighAvailabilityMode.AUTO);
+ assertMaster(n2);
+ assertEquals(n1.ha.getNodeState(), ManagementNodeState.FAILED);
+ Assert.assertTrue(n1.mgmt.getApplications().isEmpty(), "n1 should have had no apps; instead had: "+n1.mgmt.getApplications());
+ Assert.assertTrue(n1.mgmt.getEntityManager().getEntities().isEmpty(), "n1 should have had no entities; instead had: "+n1.mgmt.getEntityManager().getEntities());
+ Assert.assertTrue(n1.mgmt.getLocationManager().getLocations().isEmpty(), "n1 should have had no locations; instead had: "+n1.mgmt.getLocationManager().getLocations());
+
+ // we can now change n1 back to hot_standby
+ n1.ha.changeMode(HighAvailabilityMode.HOT_STANDBY);
+ assertHotStandby(n1);
+ // and it sees apps
+ Assert.assertFalse(n1.mgmt.getApplications().isEmpty(), "n1 should have had apps now");
+ Assert.assertFalse(n1.mgmt.getLocationManager().getLocations().isEmpty(), "n1 should have had locations now");
+ // and if n2 is disabled, n1 promotes
+ n2.ha.changeMode(HighAvailabilityMode.DISABLED);
+ n1.ha.changeMode(HighAvailabilityMode.AUTO);
+ assertMaster(n1);
+ assertEquals(n2.ha.getNodeState(), ManagementNodeState.FAILED);
+ }
+
+ @Test
+ public void testHotStandbyDoesNotStartFeeds() throws Exception {
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ TestApplication app = createFirstAppAndPersist(n1);
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntityWithFunctionFeedImpl.class));
+ forcePersistNow(n1);
+ Assert.assertTrue(entity.feeds().getFeeds().size() > 0, "Feeds: "+entity.feeds().getFeeds());
+ for (Feed feed : entity.feeds().getFeeds()) {
+ assertTrue(feed.isRunning(), "Feed expected running, but it is non-running");
+ }
+
+ HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
+ TestEntity entityRO = (TestEntity) n2.mgmt.lookup(entity.getId(), Entity.class);
+ Assert.assertTrue(entityRO.feeds().getFeeds().size() > 0, "Feeds: "+entity.feeds().getFeeds());
+ for (Feed feedRO : entityRO.feeds().getFeeds()) {
+ assertFalse(feedRO.isRunning(), "Feed expected non-active, but it is running");
+ }
+ }
+
+ @Test(groups="Integration")
+ public void testHotStandbyDoesNotStartFeedsRebindingManyTimes() throws Exception {
+ testHotStandbyDoesNotStartFeeds();
+ final HaMgmtNode hsb = createHotStandby(Duration.millis(10));
+ Repeater.create("until 10 rebinds").every(Duration.millis(100)).until(
+ new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return ((RebindManagerImpl)hsb.mgmt.getRebindManager()).getReadOnlyRebindCount() >= 10;
+ }
+ }).runRequiringTrue();
+ // make sure not too many tasks (allowing 5 for rebind etc; currently just 2)
+ RebindTestFixture.waitForTaskCountToBecome(hsb.mgmt, 5);
+ }
+
+ @Test(groups="Integration")
+ public void testHotStandbyDoesNotStartFeedsRebindingManyTimesWithAnotherFeedGenerator() throws Exception {
+ HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
+ TestApplication app = createFirstAppAndPersist(n1);
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntityWithNewFeedsEachTimeImpl.class));
+ forcePersistNow(n1);
+ Assert.assertTrue(entity.feeds().getFeeds().size() == 4, "Feeds: "+entity.feeds().getFeeds());
+
+ final HaMgmtNode hsb = createHotStandby(Duration.millis(10));
+ Repeater.create("until 10 rebinds").every(Duration.millis(100)).until(
+ new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return ((RebindManagerImpl)hsb.mgmt.getRebindManager()).getReadOnlyRebindCount() >= 10;
+ }
+ }).runRequiringTrue();
+ // make sure not too many tasks (allowing 5 for rebind etc; currently just 2)
+ RebindTestFixture.waitForTaskCountToBecome(hsb.mgmt, 5);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/ImmutableManagementPlaneSyncRecord.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/ImmutableManagementPlaneSyncRecord.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/ImmutableManagementPlaneSyncRecord.java
new file mode 100644
index 0000000..2f08057
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/ImmutableManagementPlaneSyncRecord.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+
+public class ImmutableManagementPlaneSyncRecord implements ManagementPlaneSyncRecord {
+ private final String masterNodeId;
+ private final Map<String, ManagementNodeSyncRecord> managementNodes;
+
+ ImmutableManagementPlaneSyncRecord(String masterNodeId, Map<String, ManagementNodeSyncRecord> nodes) {
+ this.masterNodeId = masterNodeId;
+ this.managementNodes = ImmutableMap.copyOf(nodes);
+ }
+
+ @Override
+ public String getMasterNodeId() {
+ return masterNodeId;
+ }
+
+ @Override
+ public Map<String, ManagementNodeSyncRecord> getManagementNodes() {
+ return managementNodes;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).add("master", masterNodeId).add("nodes", managementNodes.keySet()).toString();
+ }
+
+ @Override
+ public String toVerboseString() {
+ return Objects.toStringHelper(this).add("master", masterNodeId).add("nodes", managementNodes).toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordPersisterInMemory.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordPersisterInMemory.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordPersisterInMemory.java
new file mode 100644
index 0000000..5791c88
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/ManagementPlaneSyncRecordPersisterInMemory.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.IOException;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.rebind.persister.InMemoryObjectStore;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.VisibleForTesting;
+
+/** @deprecated since 0.7.0 use {@link ManagementPlaneSyncRecordPersisterToObjectStore}
+ * with {@link InMemoryObjectStore}
+ * <code>
+ * new ManagementPlaneSyncRecordPersisterToObjectStore(new InMemoryObjectStore(), classLoader)
+ * </code> */
+@Deprecated
+public class ManagementPlaneSyncRecordPersisterInMemory implements ManagementPlaneSyncRecordPersister {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ManagementPlaneSyncRecordPersisterInMemory.class);
+
+ private final MutableManagementPlaneSyncRecord memento = new MutableManagementPlaneSyncRecord();
+
+ private volatile boolean running = true;
+
+ @Override
+ public synchronized void stop() {
+ running = false;
+ }
+
+ @Override
+ public ManagementPlaneSyncRecord loadSyncRecord() throws IOException {
+ if (!running) {
+ throw new IllegalStateException("Persister not running; cannot load memento");
+ }
+
+ return memento.snapshot();
+ }
+
+ @VisibleForTesting
+ @Override
+ public synchronized void waitForWritesCompleted(Duration timeout) throws InterruptedException, TimeoutException {
+ // The synchronized is sufficient - guarantee that no concurrent calls
+ return;
+ }
+
+ @Override
+ public synchronized void delta(Delta delta) {
+ if (!running) {
+ if (LOG.isDebugEnabled()) LOG.debug("Persister not running; ignoring checkpointed delta of manager-memento");
+ return;
+ }
+
+ for (ManagementNodeSyncRecord m : delta.getNodes()) {
+ memento.addNode(m);
+ }
+ for (String id : delta.getRemovedNodeIds()) {
+ memento.deleteNode(id);
+ }
+ switch (delta.getMasterChange()) {
+ case NO_CHANGE:
+ break; // no-op
+ case SET_MASTER:
+ memento.setMasterNodeId(checkNotNull(delta.getNewMasterOrNull()));
+ break;
+ case CLEAR_MASTER:
+ memento.setMasterNodeId(null);
+ break; // no-op
+ default:
+ throw new IllegalStateException("Unknown state for master-change: "+delta.getMasterChange());
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/MasterChooserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/MasterChooserTest.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/MasterChooserTest.java
new file mode 100644
index 0000000..8958c4b
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/MasterChooserTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.core.management.ha.BasicMasterChooser.AlphabeticMasterChooser;
+import org.apache.brooklyn.core.management.ha.BasicMasterChooser.ScoredRecord;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.BrooklynVersion;
+import brooklyn.entity.basic.EntityFunctions;
+import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+public class MasterChooserTest {
+
+ private MutableManagementPlaneSyncRecord memento;
+ private AlphabeticMasterChooser chooser;
+ private long now;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ memento = new MutableManagementPlaneSyncRecord();
+ chooser = new AlphabeticMasterChooser();
+ now = System.currentTimeMillis();
+ }
+
+ @Test
+ public void testChoosesFirstAlphanumeric() throws Exception {
+ memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now));
+ memento.addNode(newManagerMemento("node2", ManagementNodeState.STANDBY, now));
+ memento.addNode(newManagerMemento("node3", ManagementNodeState.STANDBY, now));
+ Duration heartbeatTimeout = Duration.THIRTY_SECONDS;
+ String ownNodeId = "node2";
+ assertEquals(chooser.choose(memento, heartbeatTimeout, ownNodeId).getNodeId(), "node1");
+ }
+
+ @Test
+ public void testReturnsNullIfNoValid() throws Exception {
+ memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now - 31*1000));
+ Duration heartbeatTimeout = Duration.THIRTY_SECONDS;
+ assertNull(chooser.choose(memento, heartbeatTimeout, "node2"));
+ }
+
+ @Test
+ public void testFiltersOutByHeartbeat() throws Exception {
+ memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now - 31*1000));
+ memento.addNode(newManagerMemento("node2", ManagementNodeState.STANDBY, now - 20*1000));
+ memento.addNode(newManagerMemento("node3", ManagementNodeState.STANDBY, now));
+ Duration heartbeatTimeout = Duration.THIRTY_SECONDS;
+ assertEquals(getIds(chooser.sort(chooser.filterHealthy(memento, heartbeatTimeout, now))), ImmutableList.of("node2", "node3"));
+ }
+
+ protected static List<String> getIds(List<ScoredRecord<?>> filterHealthy) {
+ return ImmutableList.copyOf(Iterables.transform(filterHealthy, EntityFunctions.id()));
+ }
+
+ @Test
+ public void testFiltersOutByStatusNotPreferringMaster() throws Exception {
+ assertEquals(doTestFiltersOutByStatus(false, false), ImmutableList.of("node4", "node5"));
+ }
+ @Test
+ public void testFiltersOutByStatusPreferringMaster() throws Exception {
+ assertEquals(doTestFiltersOutByStatus(true, false), ImmutableList.of("node5", "node4"));
+ }
+
+ @Test
+ public void testFiltersOutByStatusNotPreferringHot() throws Exception {
+ assertEquals(doTestFiltersOutByStatus(false, true), ImmutableList.of("node4", "node5", "node6"));
+ }
+ @Test
+ public void testFiltersOutByStatusPreferringHot() throws Exception {
+ assertEquals(doTestFiltersOutByStatus(true, true), ImmutableList.of("node5", "node6", "node4"));
+ }
+
+ protected List<String> doTestFiltersOutByStatus(boolean preferHot, boolean includeHot) throws Exception {
+ chooser = new AlphabeticMasterChooser(preferHot);
+ memento.addNode(newManagerMemento("node1", ManagementNodeState.FAILED, now));
+ memento.addNode(newManagerMemento("node2", ManagementNodeState.TERMINATED, now));
+ memento.addNode(newManagerMemento("node3", null, now));
+ memento.addNode(newManagerMemento("node4", ManagementNodeState.STANDBY, now));
+ memento.addNode(newManagerMemento("node5", ManagementNodeState.MASTER, now));
+ if (includeHot)
+ memento.addNode(newManagerMemento("node6", ManagementNodeState.HOT_STANDBY, now));
+ return getIds(chooser.sort(chooser.filterHealthy(memento, Duration.THIRTY_SECONDS, now)));
+ }
+
+ @Test
+ public void testExplicityPriority() throws Exception {
+ chooser = new AlphabeticMasterChooser();
+ memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now, BrooklynVersion.get(), 2L));
+ memento.addNode(newManagerMemento("node2", ManagementNodeState.STANDBY, now, BrooklynVersion.get(), -1L));
+ memento.addNode(newManagerMemento("node3", ManagementNodeState.STANDBY, now, BrooklynVersion.get(), null));
+ List<String> order = getIds(chooser.sort(chooser.filterHealthy(memento, Duration.THIRTY_SECONDS, now)));
+ assertEquals(order, ImmutableList.of("node1", "node3", "node2"));
+ }
+
+ @Test
+ public void testVersionsMaybeNull() throws Exception {
+ chooser = new AlphabeticMasterChooser();
+ memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now, "v10", null));
+ memento.addNode(newManagerMemento("node2", ManagementNodeState.STANDBY, now, "v3-snapshot", null));
+ memento.addNode(newManagerMemento("node3", ManagementNodeState.STANDBY, now, "v3-snapshot", -1L));
+ memento.addNode(newManagerMemento("node4", ManagementNodeState.STANDBY, now, "v3-snapshot", null));
+ memento.addNode(newManagerMemento("node5", ManagementNodeState.STANDBY, now, "v3-stable", null));
+ memento.addNode(newManagerMemento("node6", ManagementNodeState.STANDBY, now, "v1", null));
+ memento.addNode(newManagerMemento("node7", ManagementNodeState.STANDBY, now, null, null));
+ List<String> order = getIds(chooser.sort(chooser.filterHealthy(memento, Duration.THIRTY_SECONDS, now)));
+ assertEquals(order, ImmutableList.of("node1", "node5", "node6", "node2", "node4", "node7", "node3"));
+ }
+
+ private ManagementNodeSyncRecord newManagerMemento(String nodeId, ManagementNodeState status, long timestamp) {
+ return newManagerMemento(nodeId, status, timestamp, BrooklynVersion.get(), null);
+ }
+ private ManagementNodeSyncRecord newManagerMemento(String nodeId, ManagementNodeState status, long timestamp,
+ String version, Long priority) {
+ return BasicManagementNodeSyncRecord.builder().brooklynVersion(version).nodeId(nodeId).status(status).localTimestamp(timestamp).remoteTimestamp(timestamp).
+ priority(priority).build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/MutableManagementPlaneSyncRecord.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/MutableManagementPlaneSyncRecord.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/MutableManagementPlaneSyncRecord.java
new file mode 100644
index 0000000..d9c8943
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/MutableManagementPlaneSyncRecord.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+
+import com.google.common.collect.Maps;
+
+public class MutableManagementPlaneSyncRecord implements ManagementPlaneSyncRecord {
+ private String masterNodeId;
+ private Map<String, ManagementNodeSyncRecord> managementNodes = Maps.newConcurrentMap();
+
+ @Override
+ public String getMasterNodeId() {
+ return masterNodeId;
+ }
+
+ @Override
+ public Map<String, ManagementNodeSyncRecord> getManagementNodes() {
+ return managementNodes;
+ }
+
+ @Override
+ public String toVerboseString() {
+ return toString();
+ }
+
+ public ImmutableManagementPlaneSyncRecord snapshot() {
+ return new ImmutableManagementPlaneSyncRecord(masterNodeId, managementNodes);
+ }
+
+ public void setMasterNodeId(String masterNodeId) {
+ this.masterNodeId = masterNodeId;
+ }
+
+ public void addNode(ManagementNodeSyncRecord memento) {
+ managementNodes.put(memento.getNodeId(), memento);
+ }
+
+ public void deleteNode(String nodeId) {
+ managementNodes.remove(nodeId);
+ }
+}
\ No newline at end of file
[33/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/catalog
Posted by ha...@apache.org.
[BROOKLYN-162] Refactor package in ./core/catalog
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/6caee589
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/6caee589
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/6caee589
Branch: refs/heads/master
Commit: 6caee5899a7e6f26095caeda6518cbaaa4abd271
Parents: 9cf456d
Author: Hadrian Zbarcea <ha...@apache.org>
Authored: Sat Aug 15 00:17:33 2015 -0400
Committer: Hadrian Zbarcea <ha...@apache.org>
Committed: Sat Aug 15 00:17:33 2015 -0400
----------------------------------------------------------------------
.../java/brooklyn/catalog/CatalogLoadMode.java | 73 -
.../brooklyn/catalog/CatalogPredicates.java | 143 --
.../catalog/internal/BasicBrooklynCatalog.java | 1315 ------------------
.../internal/CatalogBundleConverter.java | 63 -
.../catalog/internal/CatalogBundleDto.java | 93 --
.../catalog/internal/CatalogClasspathDo.java | 334 -----
.../catalog/internal/CatalogClasspathDto.java | 43 -
.../brooklyn/catalog/internal/CatalogDo.java | 365 -----
.../brooklyn/catalog/internal/CatalogDto.java | 230 ---
.../catalog/internal/CatalogDtoUtils.java | 67 -
.../catalog/internal/CatalogEntityItemDto.java | 43 -
.../catalog/internal/CatalogInitialization.java | 449 ------
.../catalog/internal/CatalogItemBuilder.java | 128 --
.../catalog/internal/CatalogItemComparator.java | 143 --
.../catalog/internal/CatalogItemDo.java | 193 ---
.../internal/CatalogItemDtoAbstract.java | 404 ------
.../catalog/internal/CatalogLibrariesDo.java | 42 -
.../catalog/internal/CatalogLibrariesDto.java | 53 -
.../internal/CatalogLocationItemDto.java | 43 -
.../catalog/internal/CatalogPolicyItemDto.java | 43 -
.../internal/CatalogTemplateItemDto.java | 42 -
.../brooklyn/catalog/internal/CatalogUtils.java | 254 ----
.../catalog/internal/CatalogXmlSerializer.java | 73 -
.../brooklyn/config/BrooklynServerConfig.java | 4 +-
.../brooklyn/entity/basic/AbstractEntity.java | 2 +-
.../rebind/BasicCatalogItemRebindSupport.java | 2 +-
.../rebind/RebindContextLookupContext.java | 3 +-
.../brooklyn/entity/rebind/RebindIteration.java | 4 +-
.../rebind/dto/BasicCatalogItemMemento.java | 5 +-
.../entity/rebind/dto/MementosGenerators.java | 2 +-
.../BrooklynMementoPersisterToObjectStore.java | 2 +-
.../CatalogItemLibrariesConverter.java | 3 +-
.../rebind/persister/XmlMementoSerializer.java | 4 +-
.../main/java/brooklyn/util/ResourceUtils.java | 6 +-
.../brooklyn/core/catalog/CatalogLoadMode.java | 73 +
.../core/catalog/CatalogPredicates.java | 142 ++
.../catalog/internal/BasicBrooklynCatalog.java | 1315 ++++++++++++++++++
.../internal/CatalogBundleConverter.java | 63 +
.../core/catalog/internal/CatalogBundleDto.java | 93 ++
.../catalog/internal/CatalogClasspathDo.java | 334 +++++
.../catalog/internal/CatalogClasspathDto.java | 43 +
.../core/catalog/internal/CatalogDo.java | 365 +++++
.../core/catalog/internal/CatalogDto.java | 230 +++
.../core/catalog/internal/CatalogDtoUtils.java | 67 +
.../catalog/internal/CatalogEntityItemDto.java | 43 +
.../catalog/internal/CatalogInitialization.java | 449 ++++++
.../catalog/internal/CatalogItemBuilder.java | 128 ++
.../catalog/internal/CatalogItemComparator.java | 143 ++
.../core/catalog/internal/CatalogItemDo.java | 193 +++
.../internal/CatalogItemDtoAbstract.java | 404 ++++++
.../catalog/internal/CatalogLibrariesDo.java | 42 +
.../catalog/internal/CatalogLibrariesDto.java | 53 +
.../internal/CatalogLocationItemDto.java | 43 +
.../catalog/internal/CatalogPolicyItemDto.java | 43 +
.../internal/CatalogTemplateItemDto.java | 42 +
.../core/catalog/internal/CatalogUtils.java | 254 ++++
.../catalog/internal/CatalogXmlSerializer.java | 74 +
.../OsgiBrooklynClassLoadingContext.java | 2 +-
.../ha/HighAvailabilityManagerImpl.java | 4 +-
.../internal/AbstractManagementContext.java | 6 +-
.../internal/ManagementContextInternal.java | 2 +-
.../NonDeploymentManagementContext.java | 2 +-
.../location/basic/BasicLocationRegistry.java | 2 +-
.../location/basic/CatalogLocationResolver.java | 3 +-
.../test/java/brooklyn/BrooklynVersionTest.java | 7 +-
.../brooklyn/camp/lite/CampYamlLiteTest.java | 8 +-
.../catalog/internal/CatalogDtoTest.java | 149 --
.../internal/CatalogItemComparatorTest.java | 80 --
.../catalog/internal/CatalogLoadTest.java | 77 -
.../catalog/internal/CatalogScanTest.java | 199 ---
.../catalog/internal/CatalogTestUtils.java | 46 -
.../catalog/internal/CatalogVersioningTest.java | 156 ---
.../catalog/internal/MyCatalogItems.java | 37 -
.../rebind/ActivePartialRebindVersionTest.java | 2 +-
.../entity/rebind/RebindCatalogEntityTest.java | 2 +-
.../entity/rebind/RebindCatalogItemTest.java | 6 +-
.../entity/rebind/RebindTestFixture.java | 2 +-
.../persister/XmlMementoSerializerTest.java | 6 +-
.../core/catalog/internal/CatalogDtoTest.java | 158 +++
.../internal/CatalogItemComparatorTest.java | 82 ++
.../core/catalog/internal/CatalogLoadTest.java | 80 ++
.../core/catalog/internal/CatalogScanTest.java | 200 +++
.../core/catalog/internal/CatalogTestUtils.java | 47 +
.../catalog/internal/CatalogVersioningTest.java | 159 +++
.../core/catalog/internal/MyCatalogItems.java | 37 +
.../osgi/OsgiVersionMoreEntityTest.java | 10 +-
.../BrooklynAssemblyTemplateInstantiator.java | 4 +-
.../BrooklynComponentTemplateResolver.java | 2 +-
.../BrooklynEntityDecorationResolver.java | 2 +-
.../spi/creation/BrooklynEntityMatcher.java | 2 +-
.../service/BrooklynServiceTypeResolver.java | 2 +-
.../lookup/AbstractTemplateBrooklynLookup.java | 3 +-
.../lookup/AssemblyTemplateBrooklynLookup.java | 3 +-
...PlatformComponentTemplateBrooklynLookup.java | 3 +-
.../camp/brooklyn/AbstractYamlRebindTest.java | 2 +-
.../camp/brooklyn/AbstractYamlTest.java | 2 +-
.../CatalogOsgiVersionMoreEntityTest.java | 4 +-
.../brooklyn/catalog/CatalogYamlEntityTest.java | 2 +-
.../catalog/CatalogYamlLocationTest.java | 2 +-
.../brooklyn/catalog/CatalogYamlPolicyTest.java | 2 +-
.../brooklyn/catalog/CatalogYamlRebindTest.java | 2 +-
.../catalog/CatalogYamlVersioningTest.java | 4 +-
.../main/java/org/apache/brooklyn/cli/Main.java | 4 +-
.../brooklyn/launcher/BrooklynLauncher.java | 2 +-
.../BrooklynLauncherRebindCatalogTest.java | 2 +-
.../brooklyn/launcher/BrooklynLauncherTest.java | 2 +-
.../rest/resources/ApplicationResource.java | 2 +-
.../rest/resources/CatalogResource.java | 12 +-
.../rest/resources/LocationResource.java | 4 +-
.../rest/util/BrooklynRestResourceUtils.java | 2 +-
.../brooklyn/rest/util/WebResourceUtils.java | 4 +-
.../rest/resources/CatalogResourceTest.java | 2 +-
.../util/BrooklynRestResourceUtilsTest.java | 6 +-
113 files changed, 5482 insertions(+), 5481 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java b/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java
deleted file mode 100644
index 6341a10..0000000
--- a/core/src/main/java/brooklyn/catalog/CatalogLoadMode.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog;
-
-import org.slf4j.LoggerFactory;
-
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.entity.rebind.persister.PersistMode;
-
-/** @deprecated since 0.7.0 replaced by {@link CatalogInitialization} */
-@Deprecated
-public enum CatalogLoadMode {
- /**
- * The server will load its initial catalog from the URL configured in
- * {@link brooklyn.config.BrooklynServerConfig#BROOKLYN_CATALOG_URL} and will
- * disregard existing persisted state.
- */
- LOAD_BROOKLYN_CATALOG_URL,
-
- /**
- * The server will load its initial catalog from previously persisted state,
- * and will behave as {@link #LOAD_BROOKLYN_CATALOG_URL} if no state exists.
- */
- LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE,
-
- /**
- * The server will load its initial catalog from previously persisted state.
- * The catalog will be empty if no previous state exists.
- */
- LOAD_PERSISTED_STATE;
-
- /**
- * @return A catalog load mode suitable for the given persistence mode:
- * <ul>
- * <li>disabled: {@link #LOAD_BROOKLYN_CATALOG_URL}</li>
- * <li>rebind: {@link #LOAD_PERSISTED_STATE}</li>
- * <li>auto or clean: {@link #LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE}</li>
- * </ul>
- */
- public static CatalogLoadMode forPersistMode(PersistMode m) {
- // Clean case relies on the persistence directory being cleaned and rebind manager
- // believing the store to be empty.
- switch (m) {
- case DISABLED:
- return LOAD_BROOKLYN_CATALOG_URL;
- case AUTO:
- case CLEAN:
- return LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE;
- case REBIND:
- return LOAD_PERSISTED_STATE;
- default:
- LoggerFactory.getLogger(CatalogLoadMode.class)
- .warn("Unhandled persistence mode {}. Catalog defaulting to {}", m.name(), LOAD_BROOKLYN_CATALOG_URL.name());
- return LOAD_BROOKLYN_CATALOG_URL;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java b/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
deleted file mode 100644
index 07dcbe0..0000000
--- a/core/src/main/java/brooklyn/catalog/CatalogPredicates.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.api.policy.PolicySpec;
-import org.apache.brooklyn.core.management.entitlement.Entitlements;
-
-import brooklyn.catalog.internal.CatalogUtils;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-
-public class CatalogPredicates {
-
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> isCatalogItemType(final CatalogItemType ciType) {
- return new Predicate<CatalogItem<T,SpecT>>() {
- @Override
- public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
- return (item != null) && item.getCatalogItemType()==ciType;
- }
- };
- }
-
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> deprecated(final boolean deprecated) {
- return new Predicate<CatalogItem<T,SpecT>>() {
- @Override
- public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
- return (item != null) && item.isDeprecated() == deprecated;
- }
- };
- }
-
- public static final Predicate<CatalogItem<Application,EntitySpec<? extends Application>>> IS_TEMPLATE =
- CatalogPredicates.<Application,EntitySpec<? extends Application>>isCatalogItemType(CatalogItemType.TEMPLATE);
- public static final Predicate<CatalogItem<Entity,EntitySpec<?>>> IS_ENTITY =
- CatalogPredicates.<Entity,EntitySpec<?>>isCatalogItemType(CatalogItemType.ENTITY);
- public static final Predicate<CatalogItem<Policy,PolicySpec<?>>> IS_POLICY =
- CatalogPredicates.<Policy,PolicySpec<?>>isCatalogItemType(CatalogItemType.POLICY);
- public static final Predicate<CatalogItem<Location,LocationSpec<?>>> IS_LOCATION =
- CatalogPredicates.<Location,LocationSpec<?>>isCatalogItemType(CatalogItemType.LOCATION);
-
- public static final Function<CatalogItem<?,?>,String> ID_OF_ITEM_TRANSFORMER = new Function<CatalogItem<?,?>, String>() {
- @Override @Nullable
- public String apply(@Nullable CatalogItem<?,?> input) {
- if (input==null) return null;
- return input.getId();
- }
- };
-
- /** @deprecated since 0.7.0 use {@link #displayName(Predicate)} */
- @Deprecated
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> name(final Predicate<? super String> filter) {
- return displayName(filter);
- }
-
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> displayName(final Predicate<? super String> filter) {
- return new Predicate<CatalogItem<T,SpecT>>() {
- @Override
- public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
- return (item != null) && filter.apply(item.getDisplayName());
- }
- };
- }
-
- @Deprecated
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> registeredTypeName(final Predicate<? super String> filter) {
- return symbolicName(filter);
- }
-
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> symbolicName(final Predicate<? super String> filter) {
- return new Predicate<CatalogItem<T,SpecT>>() {
- @Override
- public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
- return (item != null) && filter.apply(item.getSymbolicName());
- }
- };
- }
-
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> javaType(final Predicate<? super String> filter) {
- return new Predicate<CatalogItem<T,SpecT>>() {
- @Override
- public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
- return (item != null) && filter.apply(item.getJavaType());
- }
- };
- }
-
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> xml(final Predicate<? super String> filter) {
- return new Predicate<CatalogItem<T,SpecT>>() {
- @Override
- public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
- return (item != null) && filter.apply(item.toXmlString());
- }
- };
- }
-
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> entitledToSee(final ManagementContext mgmt) {
- return new Predicate<CatalogItem<T,SpecT>>() {
- @Override
- public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
- return (item != null) &&
- Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, item.getCatalogItemId());
- }
- };
- }
-
- public static <T,SpecT> Predicate<CatalogItem<T,SpecT>> isBestVersion(final ManagementContext mgmt) {
- return new Predicate<CatalogItem<T,SpecT>>() {
- @Override
- public boolean apply(@Nullable CatalogItem<T,SpecT> item) {
- return CatalogUtils.isBestVersion(mgmt, item);
- }
- };
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
deleted file mode 100644
index 88474e7..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ /dev/null
@@ -1,1315 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import io.brooklyn.camp.CampPlatform;
-import io.brooklyn.camp.spi.AssemblyTemplate;
-import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
-import io.brooklyn.camp.spi.pdp.DeploymentPlan;
-
-import java.lang.reflect.Method;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.yaml.snakeyaml.Yaml;
-
-import brooklyn.basic.BrooklynObjectInternal.ConfigurationSupportInternal;
-import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
-
-import org.apache.brooklyn.api.basic.AbstractBrooklynObjectSpec;
-import org.apache.brooklyn.api.catalog.BrooklynCatalog;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.api.policy.PolicySpec;
-import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
-
-import brooklyn.catalog.CatalogPredicates;
-import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
-import brooklyn.config.BrooklynServerConfig;
-
-import org.apache.brooklyn.location.basic.BasicLocationRegistry;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.javalang.AggregateClassLoader;
-import brooklyn.util.javalang.LoadedClassLoader;
-import brooklyn.util.javalang.Reflections;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-import brooklyn.util.yaml.Yamls;
-import brooklyn.util.yaml.Yamls.YamlExtract;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Iterables;
-
-/* TODO the complex tree-structured catalogs are only useful when we are relying on those separate catalog classloaders
- * to isolate classpaths. with osgi everything is just put into the "manual additions" catalog. */
-public class BasicBrooklynCatalog implements BrooklynCatalog {
- private static final String POLICIES_KEY = "brooklyn.policies";
- private static final String LOCATIONS_KEY = "brooklyn.locations";
- public static final String NO_VERSION = "0.0.0.SNAPSHOT";
-
- private static final Logger log = LoggerFactory.getLogger(BasicBrooklynCatalog.class);
-
- public static class BrooklynLoaderTracker {
- public static final ThreadLocal<BrooklynClassLoadingContext> loader = new ThreadLocal<BrooklynClassLoadingContext>();
-
- public static void setLoader(BrooklynClassLoadingContext val) {
- loader.set(val);
- }
-
- // TODO Stack, for recursive calls?
- public static void unsetLoader(BrooklynClassLoadingContext val) {
- loader.set(null);
- }
-
- public static BrooklynClassLoadingContext getLoader() {
- return loader.get();
- }
- }
-
- private final ManagementContext mgmt;
- private CatalogDo catalog;
- private volatile CatalogDo manualAdditionsCatalog;
- private volatile LoadedClassLoader manualAdditionsClasses;
- private final AggregateClassLoader rootClassLoader = AggregateClassLoader.newInstanceWithNoLoaders();
-
- public BasicBrooklynCatalog(ManagementContext mgmt) {
- this(mgmt, CatalogDto.newNamedInstance("empty catalog", "empty catalog", "empty catalog, expected to be reset later"));
- }
-
- public BasicBrooklynCatalog(ManagementContext mgmt, CatalogDto dto) {
- this.mgmt = checkNotNull(mgmt, "managementContext");
- this.catalog = new CatalogDo(mgmt, dto);
- }
-
- public boolean blockIfNotLoaded(Duration timeout) {
- try {
- return getCatalog().blockIfNotLoaded(timeout);
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- public void reset(CatalogDto dto) {
- reset(dto, true);
- }
-
- public void reset(CatalogDto dto, boolean failOnLoadError) {
- // Unregister all existing persisted items.
- for (CatalogItem<?, ?> toRemove : getCatalogItems()) {
- if (log.isTraceEnabled()) {
- log.trace("Scheduling item for persistence removal: {}", toRemove.getId());
- }
- mgmt.getRebindManager().getChangeListener().onUnmanaged(toRemove);
- }
- CatalogDo catalog = new CatalogDo(mgmt, dto);
- CatalogUtils.logDebugOrTraceIfRebinding(log, "Resetting "+this+" catalog to "+dto);
- catalog.load(mgmt, null, failOnLoadError);
- CatalogUtils.logDebugOrTraceIfRebinding(log, "Reloaded catalog for "+this+", now switching");
- this.catalog = catalog;
- resetRootClassLoader();
- this.manualAdditionsCatalog = null;
-
- // Inject management context into and persist all the new entries.
- for (CatalogItem<?, ?> entry : getCatalogItems()) {
- boolean setManagementContext = false;
- if (entry instanceof CatalogItemDo) {
- CatalogItemDo<?, ?> cid = CatalogItemDo.class.cast(entry);
- if (cid.getDto() instanceof CatalogItemDtoAbstract) {
- CatalogItemDtoAbstract<?, ?> cdto = CatalogItemDtoAbstract.class.cast(cid.getDto());
- if (cdto.getManagementContext() == null) {
- cdto.setManagementContext((ManagementContextInternal) mgmt);
- }
- setManagementContext = true;
- }
- }
- if (!setManagementContext) {
- log.warn("Can't set management context on entry with unexpected type in catalog. type={}, " +
- "expected={}", entry, CatalogItemDo.class);
- }
- if (log.isTraceEnabled()) {
- log.trace("Scheduling item for persistence addition: {}", entry.getId());
- }
- mgmt.getRebindManager().getChangeListener().onManaged(entry);
- }
-
- }
-
- /**
- * Resets the catalog to the given entries
- */
- @Override
- public void reset(Collection<CatalogItem<?, ?>> entries) {
- CatalogDto newDto = CatalogDto.newDtoFromCatalogItems(entries, "explicit-catalog-reset");
- reset(newDto);
- }
-
- public CatalogDo getCatalog() {
- return catalog;
- }
-
- protected CatalogItemDo<?,?> getCatalogItemDo(String symbolicName, String version) {
- String fixedVersionId = getFixedVersionId(symbolicName, version);
- if (fixedVersionId == null) {
- //no items with symbolicName exist
- return null;
- }
-
- return catalog.getIdCache().get( CatalogUtils.getVersionedId(symbolicName, fixedVersionId) );
- }
-
- private String getFixedVersionId(String symbolicName, String version) {
- if (!DEFAULT_VERSION.equals(version)) {
- return version;
- } else {
- return getDefaultVersion(symbolicName);
- }
- }
-
- private String getDefaultVersion(String symbolicName) {
- Iterable<CatalogItem<Object, Object>> versions = getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo(symbolicName)));
- Collection<CatalogItem<Object, Object>> orderedVersions = sortVersionsDesc(versions);
- if (!orderedVersions.isEmpty()) {
- return orderedVersions.iterator().next().getVersion();
- } else {
- return null;
- }
- }
-
- private <T,SpecT> Collection<CatalogItem<T,SpecT>> sortVersionsDesc(Iterable<CatalogItem<T,SpecT>> versions) {
- return ImmutableSortedSet.orderedBy(CatalogItemComparator.<T,SpecT>getInstance()).addAll(versions).build();
- }
-
- @Override
- @Deprecated
- public CatalogItem<?,?> getCatalogItem(String symbolicName) {
- return getCatalogItem(symbolicName, DEFAULT_VERSION);
- }
-
- @Override
- public CatalogItem<?,?> getCatalogItem(String symbolicName, String version) {
- if (symbolicName == null) return null;
- checkNotNull(version, "version");
- CatalogItemDo<?, ?> itemDo = getCatalogItemDo(symbolicName, version);
- if (itemDo == null) return null;
- return itemDo.getDto();
- }
-
- @Override
- @Deprecated
- public void deleteCatalogItem(String id) {
- //Delete only if installed through the
- //deprecated methods. Don't support DEFAULT_VERSION for delete.
- deleteCatalogItem(id, NO_VERSION);
- }
-
- @Override
- public void deleteCatalogItem(String symbolicName, String version) {
- log.debug("Deleting manual catalog item from "+mgmt+": "+symbolicName + ":" + version);
- checkNotNull(symbolicName, "id");
- checkNotNull(version, "version");
- if (DEFAULT_VERSION.equals(version)) {
- throw new IllegalStateException("Deleting items with unspecified version (argument DEFAULT_VERSION) not supported.");
- }
- CatalogItem<?, ?> item = getCatalogItem(symbolicName, version);
- CatalogItemDtoAbstract<?,?> itemDto = getAbstractCatalogItem(item);
- if (itemDto == null) {
- throw new NoSuchElementException("No catalog item found with id "+symbolicName);
- }
- if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
- manualAdditionsCatalog.deleteEntry(itemDto);
-
- // Ensure the cache is de-populated
- getCatalog().deleteEntry(itemDto);
-
- // And indicate to the management context that it should be removed.
- if (log.isTraceEnabled()) {
- log.trace("Scheduling item for persistence removal: {}", itemDto.getId());
- }
- if (itemDto.getCatalogItemType() == CatalogItemType.LOCATION) {
- @SuppressWarnings("unchecked")
- CatalogItem<Location,LocationSpec<?>> locationItem = (CatalogItem<Location, LocationSpec<?>>) itemDto;
- ((BasicLocationRegistry)mgmt.getLocationRegistry()).removeDefinedLocation(locationItem);
- }
- mgmt.getRebindManager().getChangeListener().onUnmanaged(itemDto);
-
- }
-
- @Override
- @Deprecated
- public <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id) {
- return getCatalogItem(type, id, DEFAULT_VERSION);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T,SpecT> CatalogItem<T,SpecT> getCatalogItem(Class<T> type, String id, String version) {
- if (id==null || version==null) return null;
- CatalogItem<?,?> result = getCatalogItem(id, version);
- if (result==null) return null;
- if (type==null || type.isAssignableFrom(result.getCatalogItemJavaType()))
- return (CatalogItem<T,SpecT>)result;
- return null;
- }
-
- @Override
- public void persist(CatalogItem<?, ?> catalogItem) {
- checkArgument(getCatalogItem(catalogItem.getSymbolicName(), catalogItem.getVersion()) != null, "Unknown catalog item %s", catalogItem);
- mgmt.getRebindManager().getChangeListener().onChanged(catalogItem);
- }
-
- @Override
- public ClassLoader getRootClassLoader() {
- if (rootClassLoader.isEmpty() && catalog!=null) {
- resetRootClassLoader();
- }
- return rootClassLoader;
- }
-
- private void resetRootClassLoader() {
- rootClassLoader.reset(ImmutableList.of(catalog.getRootClassLoader()));
- }
-
- /**
- * Loads this catalog. No effect if already loaded.
- */
- public void load() {
- log.debug("Loading catalog for " + mgmt);
- getCatalog().load(mgmt, null);
- if (log.isDebugEnabled()) {
- log.debug("Loaded catalog for " + mgmt + ": " + catalog + "; search classpath is " + catalog.getRootClassLoader());
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T, SpecT> SpecT createSpec(CatalogItem<T, SpecT> item) {
- if (item == null) return null;
- CatalogItemDo<T,SpecT> loadedItem = (CatalogItemDo<T, SpecT>) getCatalogItemDo(item.getSymbolicName(), item.getVersion());
- if (loadedItem == null) throw new RuntimeException(item+" not in catalog; cannot create spec");
- Class<SpecT> specType = loadedItem.getSpecType();
- if (specType==null) return null;
-
- String yaml = loadedItem.getPlanYaml();
-
- if (yaml!=null) {
- // preferred way is to parse the yaml, to resolve references late;
- // the parsing on load is to populate some fields, but it is optional.
- // TODO messy for location and policy that we need brooklyn.{locations,policies} root of the yaml, but it works;
- // see related comment when the yaml is set, in addAbstractCatalogItems
- // (not sure if anywhere else relies on that syntax; if not, it should be easy to fix!)
- DeploymentPlan plan = makePlanFromYaml(yaml);
- BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item);
- SpecT spec;
- switch (item.getCatalogItemType()) {
- case TEMPLATE:
- case ENTITY:
- spec = createEntitySpec(loadedItem.getSymbolicName(), plan, loader);
- break;
- case POLICY:
- spec = createPolicySpec(loadedItem.getSymbolicName(), plan, loader);
- break;
- case LOCATION:
- spec = createLocationSpec(plan, loader);
- break;
- default: throw new RuntimeException("Only entity, policy & location catalog items are supported. Unsupported catalog item type " + item.getCatalogItemType());
- }
- ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId());
-
- if (Strings.isBlank( ((AbstractBrooklynObjectSpec<?, ?>)spec).getDisplayName() ))
- ((AbstractBrooklynObjectSpec<?, ?>)spec).displayName(item.getDisplayName());
-
- return spec;
- }
-
- // revert to legacy mechanism
- SpecT spec = null;
- Method method;
- try {
- method = Reflections.findMethod(specType, "create", Class.class);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- throw new IllegalStateException("Unsupported creation of spec type "+specType+"; it must have a public static create(Class) method", e);
- }
- try {
- if (loadedItem.getJavaType()!=null) {
- SpecT specT = (SpecT) method.invoke(null, loadedItem.loadJavaClass(mgmt));
- spec = specT;
- }
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- throw new IllegalStateException("Error creating "+specType+" "+loadedItem.getJavaType()+": "+e, e);
- }
-
- if (spec==null)
- throw new IllegalStateException("Unknown how to create instance of "+this);
-
- return spec;
- }
-
- private <T, SpecT> SpecT createSpec(String optionalId, CatalogItemType ciType, DeploymentPlan plan, BrooklynClassLoadingContext loader) {
- Preconditions.checkNotNull(ciType, "catalog item type for "+plan);
- switch (ciType) {
- case TEMPLATE:
- case ENTITY:
- return createEntitySpec(optionalId, plan, loader);
- case LOCATION: return createLocationSpec(plan, loader);
- case POLICY: return createPolicySpec(optionalId, plan, loader);
- }
- throw new IllegalStateException("Unknown CI Type "+ciType+" for "+plan);
- }
-
- @SuppressWarnings("unchecked")
- private <T, SpecT> SpecT createEntitySpec(String symbolicName, DeploymentPlan plan, BrooklynClassLoadingContext loader) {
- CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
-
- // TODO should not register new AT each time we instantiate from the same plan; use some kind of cache
- AssemblyTemplate at;
- BrooklynLoaderTracker.setLoader(loader);
- try {
- at = camp.pdp().registerDeploymentPlan(plan);
- } finally {
- BrooklynLoaderTracker.unsetLoader(loader);
- }
-
- try {
- AssemblyTemplateInstantiator instantiator = at.getInstantiator().newInstance();
- if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
- return (SpecT) ((AssemblyTemplateSpecInstantiator)instantiator).createNestedSpec(at, camp, loader,
- getInitialEncounteredSymbol(symbolicName));
- }
- throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- private MutableSet<String> getInitialEncounteredSymbol(String symbolicName) {
- return symbolicName==null ? MutableSet.<String>of() : MutableSet.of(symbolicName);
- }
-
- private <T, SpecT> SpecT createPolicySpec(String symbolicName, DeploymentPlan plan, BrooklynClassLoadingContext loader) {
- return createPolicySpec(plan, loader, getInitialEncounteredSymbol(symbolicName));
- }
-
- private <T, SpecT> SpecT createPolicySpec(DeploymentPlan plan, BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) {
- //Would ideally re-use io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityDecorationResolver.PolicySpecResolver
- //but it is CAMP specific and there is no easy way to get hold of it.
- Object policies = checkNotNull(plan.getCustomAttributes().get(POLICIES_KEY), "policy config");
- if (!(policies instanceof Iterable<?>)) {
- throw new IllegalStateException("The value of " + POLICIES_KEY + " must be an Iterable.");
- }
-
- Object policy = Iterables.getOnlyElement((Iterable<?>)policies);
-
- return createPolicySpec(loader, policy, encounteredCatalogTypes);
- }
-
- @SuppressWarnings("unchecked")
- private <T, SpecT> SpecT createPolicySpec(BrooklynClassLoadingContext loader, Object policy, Set<String> encounteredCatalogTypes) {
- Map<String, Object> itemMap;
- if (policy instanceof String) {
- itemMap = ImmutableMap.<String, Object>of("type", policy);
- } else if (policy instanceof Map) {
- itemMap = (Map<String, Object>) policy;
- } else {
- throw new IllegalStateException("Policy expected to be string or map. Unsupported object type " + policy.getClass().getName() + " (" + policy.toString() + ")");
- }
-
- String versionedId = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "policy_type", "policyType", "type"), "policy type");
- PolicySpec<? extends Policy> spec;
- CatalogItem<?, ?> policyItem = CatalogUtils.getCatalogItemOptionalVersion(mgmt, versionedId);
- if (policyItem != null && !encounteredCatalogTypes.contains(policyItem.getSymbolicName())) {
- if (policyItem.getCatalogItemType() != CatalogItemType.POLICY) {
- throw new IllegalStateException("Non-policy catalog item in policy context: " + policyItem);
- }
- //TODO re-use createSpec
- BrooklynClassLoadingContext itemLoader = CatalogUtils.newClassLoadingContext(mgmt, policyItem);
- if (policyItem.getPlanYaml() != null) {
- DeploymentPlan plan = makePlanFromYaml(policyItem.getPlanYaml());
- encounteredCatalogTypes.add(policyItem.getSymbolicName());
- return createPolicySpec(plan, itemLoader, encounteredCatalogTypes);
- } else if (policyItem.getJavaType() != null) {
- spec = PolicySpec.create((Class<Policy>)itemLoader.loadClass(policyItem.getJavaType()));
- } else {
- throw new IllegalStateException("Invalid policy item - neither yaml nor javaType: " + policyItem);
- }
- } else {
- spec = PolicySpec.create(loader.loadClass(versionedId, Policy.class));
- }
- Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config");
- if (brooklynConfig != null) {
- spec.configure(brooklynConfig);
- }
- return (SpecT) spec;
- }
-
- private <T, SpecT> SpecT createLocationSpec(DeploymentPlan plan, BrooklynClassLoadingContext loader) {
- // See #createPolicySpec; this impl is modeled on that.
- // spec.catalogItemId is set by caller
- Object locations = checkNotNull(plan.getCustomAttributes().get(LOCATIONS_KEY), "location config");
- if (!(locations instanceof Iterable<?>)) {
- throw new IllegalStateException("The value of " + LOCATIONS_KEY + " must be an Iterable.");
- }
-
- Object location = Iterables.getOnlyElement((Iterable<?>)locations);
-
- return createLocationSpec(loader, location);
- }
-
- @SuppressWarnings("unchecked")
- private <T, SpecT> SpecT createLocationSpec(BrooklynClassLoadingContext loader, Object location) {
- Map<String, Object> itemMap;
- if (location instanceof String) {
- itemMap = ImmutableMap.<String, Object>of("type", location);
- } else if (location instanceof Map) {
- itemMap = (Map<String, Object>) location;
- } else {
- throw new IllegalStateException("Location expected to be string or map. Unsupported object type " + location.getClass().getName() + " (" + location.toString() + ")");
- }
-
- String type = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "location_type", "locationType", "type"), "location type");
- Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config");
- Maybe<Class<? extends Location>> javaClass = loader.tryLoadClass(type, Location.class);
- if (javaClass.isPresent()) {
- LocationSpec<?> spec = LocationSpec.create(javaClass.get());
- if (brooklynConfig != null) {
- spec.configure(brooklynConfig);
- }
- return (SpecT) spec;
- } else {
- Maybe<Location> loc = mgmt.getLocationRegistry().resolve(type, false, brooklynConfig);
- if (loc.isPresent()) {
- // TODO extensions?
- Map<String, Object> locConfig = ((ConfigurationSupportInternal)loc.get().config()).getBag().getAllConfig();
- Class<? extends Location> locType = loc.get().getClass();
- Set<Object> locTags = loc.get().tags().getTags();
- String locDisplayName = loc.get().getDisplayName();
- return (SpecT) LocationSpec.create(locType)
- .configure(locConfig)
- .displayName(locDisplayName)
- .tags(locTags);
- } else {
- throw new IllegalStateException("No class or resolver found for location type "+type);
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
- @Deprecated
- public <T,SpecT> Class<? extends T> loadClass(CatalogItem<T,SpecT> item) {
- if (log.isDebugEnabled())
- log.debug("Loading class for catalog item " + item);
- checkNotNull(item);
- CatalogItemDo<?,?> loadedItem = getCatalogItemDo(item.getSymbolicName(), item.getVersion());
- if (loadedItem==null) throw new NoSuchElementException("Unable to load '"+item.getId()+"' to instantiate it");
- return (Class<? extends T>) loadedItem.getJavaClass();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- /** @deprecated since 0.7.0 use {@link #createSpec(CatalogItem)} */
- @Deprecated
- public <T> Class<? extends T> loadClassByType(String typeName, Class<T> typeClass) {
- final CatalogItem<?,?> resultI = getCatalogItemForType(typeName);
-
- if (resultI == null) {
- throw new NoSuchElementException("Unable to find catalog item for type "+typeName);
- }
-
- return (Class<? extends T>) loadClass(resultI);
- }
-
- @Deprecated /** @deprecated since 0.7.0 only used by other deprecated items */
- private <T,SpecT> CatalogItemDtoAbstract<T,SpecT> getAbstractCatalogItem(CatalogItem<T,SpecT> item) {
- while (item instanceof CatalogItemDo) item = ((CatalogItemDo<T,SpecT>)item).itemDto;
- if (item==null) return null;
- if (item instanceof CatalogItemDtoAbstract) return (CatalogItemDtoAbstract<T,SpecT>) item;
- throw new IllegalStateException("Cannot unwrap catalog item '"+item+"' (type "+item.getClass()+") to restore DTO");
- }
-
- @SuppressWarnings("unchecked")
- private static <T> Maybe<T> getFirstAs(Map<?,?> map, Class<T> type, String firstKey, String ...otherKeys) {
- if (map==null) return Maybe.absent("No map available");
- String foundKey = null;
- Object value = null;
- if (map.containsKey(firstKey)) foundKey = firstKey;
- else for (String key: otherKeys) {
- if (map.containsKey(key)) {
- foundKey = key;
- break;
- }
- }
- if (foundKey==null) return Maybe.absent("Missing entry '"+firstKey+"'");
- value = map.get(foundKey);
- if (type.equals(String.class) && Number.class.isInstance(value)) value = value.toString();
- if (!type.isInstance(value))
- throw new IllegalArgumentException("Entry for '"+firstKey+"' should be of type "+type+", not "+value.getClass());
- return Maybe.of((T)value);
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private Maybe<Map<?,?>> getFirstAsMap(Map<?,?> map, String firstKey, String ...otherKeys) {
- return (Maybe<Map<?,?>>)(Maybe) getFirstAs(map, Map.class, firstKey, otherKeys);
- }
-
- private List<CatalogItemDtoAbstract<?,?>> collectCatalogItems(String yaml) {
- Map<?,?> itemDef = Yamls.getAs(Yamls.parseAll(yaml), Map.class);
- Map<?,?> catalogMetadata = getFirstAsMap(itemDef, "brooklyn.catalog").orNull();
- if (catalogMetadata==null)
- log.warn("No `brooklyn.catalog` supplied in catalog request; using legacy mode for "+itemDef);
- catalogMetadata = MutableMap.copyOf(catalogMetadata);
-
- List<CatalogItemDtoAbstract<?, ?>> result = MutableList.of();
-
- collectCatalogItems(Yamls.getTextOfYamlAtPath(yaml, "brooklyn.catalog").getMatchedYamlTextOrWarn(),
- catalogMetadata, result, null);
-
- itemDef.remove("brooklyn.catalog");
- catalogMetadata.remove("item");
- catalogMetadata.remove("items");
- if (!itemDef.isEmpty()) {
- log.debug("Reading brooklyn.catalog peer keys as item ('top-level syntax')");
- Map<String,?> rootItem = MutableMap.of("item", itemDef);
- String rootItemYaml = yaml;
- YamlExtract yamlExtract = Yamls.getTextOfYamlAtPath(rootItemYaml, "brooklyn.catalog");
- String match = yamlExtract.withOriginalIndentation(true).withKeyIncluded(true).getMatchedYamlTextOrWarn();
- if (match!=null) {
- if (rootItemYaml.startsWith(match)) rootItemYaml = Strings.removeFromStart(rootItemYaml, match);
- else rootItemYaml = Strings.replaceAllNonRegex(rootItemYaml, "\n"+match, "");
- }
- collectCatalogItems("item:\n"+makeAsIndentedObject(rootItemYaml), rootItem, result, catalogMetadata);
- }
-
- return result;
- }
-
- @SuppressWarnings("unchecked")
- private void collectCatalogItems(String sourceYaml, Map<?,?> itemMetadata, List<CatalogItemDtoAbstract<?, ?>> result, Map<?,?> parentMetadata) {
-
- if (sourceYaml==null) sourceYaml = new Yaml().dump(itemMetadata);
-
- Map<Object,Object> catalogMetadata = MutableMap.builder().putAll(parentMetadata).putAll(itemMetadata).build();
-
- // brooklyn.libraries we treat specially, to append the list, with the child's list preferred in classloading order
- // `libraries` is supported in some places as a legacy syntax; it should always be `brooklyn.libraries` for new apps
- // TODO in 0.8.0 require brooklyn.libraries, don't allow "libraries" on its own
- List<?> librariesNew = MutableList.copyOf(getFirstAs(itemMetadata, List.class, "brooklyn.libraries", "libraries").orNull());
- Collection<CatalogBundle> libraryBundlesNew = CatalogItemDtoAbstract.parseLibraries(librariesNew);
-
- List<?> librariesCombined = MutableList.copyOf(librariesNew)
- .appendAll(getFirstAs(parentMetadata, List.class, "brooklyn.libraries", "libraries").orNull());
- if (!librariesCombined.isEmpty())
- catalogMetadata.put("brooklyn.libraries", librariesCombined);
- Collection<CatalogBundle> libraryBundles = CatalogItemDtoAbstract.parseLibraries(librariesCombined);
-
- // TODO as this may take a while if downloading, the REST call should be async
- // (this load is required for the scan below and I think also for yaml resolution)
- CatalogUtils.installLibraries(mgmt, libraryBundlesNew);
-
- Boolean scanJavaAnnotations = getFirstAs(itemMetadata, Boolean.class, "scanJavaAnnotations", "scan_java_annotations").orNull();
- if (scanJavaAnnotations==null || !scanJavaAnnotations) {
- // don't scan
- } else {
- // scan for annotations: if libraries here, scan them; if inherited libraries error; else scan classpath
- if (!libraryBundlesNew.isEmpty()) {
- result.addAll(scanAnnotationsFromBundles(mgmt, libraryBundlesNew, catalogMetadata));
- } else if (libraryBundles.isEmpty()) {
- result.addAll(scanAnnotationsFromLocal(mgmt, catalogMetadata));
- } else {
- throw new IllegalStateException("Cannot scan catalog node no local bundles, and with inherited bundles we will not scan the classpath");
- }
- }
-
- Object items = catalogMetadata.remove("items");
- Object item = catalogMetadata.remove("item");
-
- if (items!=null) {
- int count = 0;
- for (Map<?,?> i: ((List<Map<?,?>>)items)) {
- collectCatalogItems(Yamls.getTextOfYamlAtPath(sourceYaml, "items", count).getMatchedYamlTextOrWarn(),
- i, result, catalogMetadata);
- count++;
- }
- }
-
- if (item==null) return;
-
- // now look at the actual item, first correcting the sourceYaml and interpreting the catalog metadata
- String itemYaml = Yamls.getTextOfYamlAtPath(sourceYaml, "item").getMatchedYamlTextOrWarn();
- if (itemYaml!=null) sourceYaml = itemYaml;
- else sourceYaml = new Yaml().dump(item);
-
- CatalogItemType itemType = TypeCoercions.coerce(getFirstAs(catalogMetadata, Object.class, "itemType", "item_type").orNull(), CatalogItemType.class);
- BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, "<load>:0", libraryBundles);
-
- String id = getFirstAs(catalogMetadata, String.class, "id").orNull();
- String version = getFirstAs(catalogMetadata, String.class, "version").orNull();
- String symbolicName = getFirstAs(catalogMetadata, String.class, "symbolicName").orNull();
- String displayName = getFirstAs(catalogMetadata, String.class, "displayName").orNull();
- String name = getFirstAs(catalogMetadata, String.class, "name").orNull();
-
- if ((Strings.isNonBlank(id) || Strings.isNonBlank(symbolicName)) &&
- Strings.isNonBlank(displayName) &&
- Strings.isNonBlank(name) && !name.equals(displayName)) {
- log.warn("Name property will be ignored due to the existence of displayName and at least one of id, symbolicName");
- }
-
- PlanInterpreterGuessingType planInterpreter = new PlanInterpreterGuessingType(null, item, sourceYaml, itemType, loader, result).reconstruct();
- if (!planInterpreter.isResolved()) {
- throw Exceptions.create("Could not resolve item "
- + (Strings.isNonBlank(id) ? id : Strings.isNonBlank(symbolicName) ? symbolicName : Strings.isNonBlank(name) ? name : "<no-name>")
- + ":\n"+sourceYaml, planInterpreter.getErrors());
- }
- itemType = planInterpreter.getCatalogItemType();
- Map<?, ?> itemAsMap = planInterpreter.getItem();
- // the "plan yaml" includes the services: ... or brooklyn.policies: ... outer key,
- // as opposed to the rawer { type: xxx } map without that outer key which is valid as item input
- // TODO this plan yaml is needed for subsequent reconstruction; would be nicer if it weren't!
-
- // if symname not set, infer from: id, then name, then item id, then item name
- if (Strings.isBlank(symbolicName)) {
- if (Strings.isNonBlank(id)) {
- if (CatalogUtils.looksLikeVersionedId(id)) {
- symbolicName = CatalogUtils.getIdFromVersionedId(id);
- } else {
- symbolicName = id;
- }
- } else if (Strings.isNonBlank(name)) {
- if (CatalogUtils.looksLikeVersionedId(name)) {
- symbolicName = CatalogUtils.getIdFromVersionedId(name);
- } else {
- symbolicName = name;
- }
- } else {
- symbolicName = setFromItemIfUnset(symbolicName, itemAsMap, "id");
- symbolicName = setFromItemIfUnset(symbolicName, itemAsMap, "name");
- if (Strings.isBlank(symbolicName)) {
- log.error("Can't infer catalog item symbolicName from the following plan:\n" + sourceYaml);
- throw new IllegalStateException("Can't infer catalog item symbolicName from catalog item metadata");
- }
- }
- }
-
- // if version not set, infer from: id, then from name, then item version
- if (CatalogUtils.looksLikeVersionedId(id)) {
- String versionFromId = CatalogUtils.getVersionFromVersionedId(id);
- if (versionFromId != null && Strings.isNonBlank(version) && !versionFromId.equals(version)) {
- throw new IllegalArgumentException("Discrepency between version set in id " + versionFromId + " and version property " + version);
- }
- version = versionFromId;
- }
- if (Strings.isBlank(version)) {
- if (CatalogUtils.looksLikeVersionedId(name)) {
- version = CatalogUtils.getVersionFromVersionedId(name);
- } else if (Strings.isBlank(version)) {
- version = setFromItemIfUnset(version, itemAsMap, "version");
- if (version==null) {
- log.warn("No version specified for catalog item " + symbolicName + ". Using default value.");
- version = null;
- }
- }
- }
-
- // if not set, ID can come from symname:version, failing that, from the plan.id, failing that from the sym name
- if (Strings.isBlank(id)) {
- // let ID be inferred, especially from name, to support style where only "name" is specified, with inline version
- if (Strings.isNonBlank(symbolicName) && Strings.isNonBlank(version)) {
- id = symbolicName + ":" + version;
- }
- id = setFromItemIfUnset(id, itemAsMap, "id");
- if (Strings.isBlank(id)) {
- if (Strings.isNonBlank(symbolicName)) {
- id = symbolicName;
- } else {
- log.error("Can't infer catalog item id from the following plan:\n" + sourceYaml);
- throw new IllegalStateException("Can't infer catalog item id from catalog item metadata");
- }
- }
- }
-
- if (Strings.isBlank(displayName)) {
- if (Strings.isNonBlank(name)) displayName = name;
- displayName = setFromItemIfUnset(displayName, itemAsMap, "name");
- }
-
- String description = getFirstAs(catalogMetadata, String.class, "description").orNull();
- description = setFromItemIfUnset(description, itemAsMap, "description");
-
- // icon.url is discouraged, but kept for legacy compatibility; should deprecate this
- final String catalogIconUrl = getFirstAs(catalogMetadata, String.class, "iconUrl", "icon_url", "icon.url").orNull();
-
- final String deprecated = getFirstAs(catalogMetadata, String.class, "deprecated").orNull();
- final Boolean catalogDeprecated = Boolean.valueOf(deprecated);
-
- // run again now that we know the ID
- planInterpreter = new PlanInterpreterGuessingType(id, item, sourceYaml, itemType, loader, result).reconstruct();
- if (!planInterpreter.isResolved()) {
- throw new IllegalStateException("Could not resolve plan once id and itemType are known (recursive reference?): "+sourceYaml);
- }
- String sourcePlanYaml = planInterpreter.getPlanYaml();
-
- CatalogItemDtoAbstract<?, ?> dto = createItemBuilder(itemType, symbolicName, version)
- .libraries(libraryBundles)
- .displayName(displayName)
- .description(description)
- .deprecated(catalogDeprecated)
- .iconUrl(catalogIconUrl)
- .plan(sourcePlanYaml)
- .build();
-
- dto.setManagementContext((ManagementContextInternal) mgmt);
- result.add(dto);
- }
-
- private String setFromItemIfUnset(String oldValue, Map<?,?> item, String fieldAttr) {
- if (Strings.isNonBlank(oldValue)) return oldValue;
- if (item!=null) {
- Object newValue = item.get(fieldAttr);
- if (newValue instanceof String && Strings.isNonBlank((String)newValue))
- return (String)newValue;
- }
- return oldValue;
- }
-
- private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsFromLocal(ManagementContext mgmt, Map<Object, Object> catalogMetadata) {
- CatalogDto dto = CatalogDto.newNamedInstance("Local Scanned Catalog", "All annotated Brooklyn entities detected in the classpath", "scanning-local-classpath");
- return scanAnnotationsInternal(mgmt, new CatalogDo(dto), catalogMetadata);
- }
-
- private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsFromBundles(ManagementContext mgmt, Collection<CatalogBundle> libraries, Map<Object, Object> catalogMetadata) {
- CatalogDto dto = CatalogDto.newNamedInstance("Bundles Scanned Catalog", "All annotated Brooklyn entities detected in bundles", "scanning-bundles-classpath-"+libraries.hashCode());
- List<String> urls = MutableList.of();
- for (CatalogBundle b: libraries) {
- // TODO currently does not support pre-installed bundles identified by name:version
- // (ie where URL not supplied)
- if (Strings.isNonBlank(b.getUrl())) {
- urls.add(b.getUrl());
- }
- }
-
- if (urls.isEmpty()) {
- log.warn("No bundles to scan: scanJavaAnnotations currently only applies to OSGi bundles provided by URL");
- return MutableList.of();
- }
-
- CatalogDo subCatalog = new CatalogDo(dto);
- subCatalog.addToClasspath(urls.toArray(new String[0]));
- return scanAnnotationsInternal(mgmt, subCatalog, catalogMetadata);
- }
-
- private Collection<CatalogItemDtoAbstract<?, ?>> scanAnnotationsInternal(ManagementContext mgmt, CatalogDo subCatalog, Map<Object, Object> catalogMetadata) {
- // TODO this does java-scanning only;
- // the call when scanning bundles should use the CatalogItem instead and use OSGi when loading for scanning
- // (or another scanning mechanism). see comments on CatalogClasspathDo.load
- subCatalog.mgmt = mgmt;
- subCatalog.setClasspathScanForEntities(CatalogScanningModes.ANNOTATIONS);
- subCatalog.load();
- // TODO apply metadata? (extract YAML from the items returned)
- // also see doc .../catalog/index.md which says we might not apply metadata
- @SuppressWarnings({ "unchecked", "rawtypes" })
- Collection<CatalogItemDtoAbstract<?, ?>> result = (Collection<CatalogItemDtoAbstract<?, ?>>)(Collection)Collections2.transform(
- (Collection<CatalogItemDo<Object,Object>>)(Collection)subCatalog.getIdCache().values(),
- itemDoToDtoAddingSelectedMetadataDuringScan(catalogMetadata));
- return result;
- }
-
- private class PlanInterpreterGuessingType {
-
- final String id;
- final Map<?,?> item;
- final String itemYaml;
- final BrooklynClassLoadingContext loader;
- final List<CatalogItemDtoAbstract<?, ?>> itemsDefinedSoFar;
-
- CatalogItemType catalogItemType;
- String planYaml;
- @SuppressWarnings("unused")
- DeploymentPlan plan;
- AbstractBrooklynObjectSpec<?,?> spec;
- boolean resolved = false;
- List<Exception> errors = MutableList.of();
-
- public PlanInterpreterGuessingType(@Nullable String id, Object item, String itemYaml, @Nullable CatalogItemType optionalCiType,
- BrooklynClassLoadingContext loader, List<CatalogItemDtoAbstract<?,?>> itemsDefinedSoFar) {
- // ID is useful to prevent recursive references (currently for entities only)
- this.id = id;
-
- if (item instanceof String) {
- // if just a string supplied, wrap as map
- this.item = MutableMap.of("type", item);
- this.itemYaml = "type:\n"+makeAsIndentedObject(itemYaml);
- } else {
- this.item = (Map<?,?>)item;
- this.itemYaml = itemYaml;
- }
- this.catalogItemType = optionalCiType;
- this.loader = loader;
- this.itemsDefinedSoFar = itemsDefinedSoFar;
- }
-
- public PlanInterpreterGuessingType reconstruct() {
- if (catalogItemType==CatalogItemType.TEMPLATE) {
- // template *must* be explicitly defined, and if so, none of the other calls apply
- attemptType(null, CatalogItemType.TEMPLATE);
-
- } else {
- attemptType(null, CatalogItemType.ENTITY);
-
- attemptType("services", CatalogItemType.ENTITY);
- attemptType(POLICIES_KEY, CatalogItemType.POLICY);
- attemptType(LOCATIONS_KEY, CatalogItemType.LOCATION);
- }
-
- if (!resolved && catalogItemType==CatalogItemType.TEMPLATE) {
- // anything goes, for an explicit template, because we can't easily recurse into the types
- planYaml = itemYaml;
- resolved = true;
- }
-
- return this;
- }
-
- public boolean isResolved() { return resolved; }
-
- /** Returns potentially useful errors encountered while guessing types.
- * May only be available where the type is known. */
- public List<Exception> getErrors() {
- return errors;
- }
-
- public CatalogItemType getCatalogItemType() {
- return catalogItemType;
- }
-
- public String getPlanYaml() {
- return planYaml;
- }
-
- private boolean attemptType(String key, CatalogItemType candidateCiType) {
- if (resolved) return false;
- if (catalogItemType!=null && catalogItemType!=candidateCiType) return false;
-
- final String candidateYaml;
- if (key==null) candidateYaml = itemYaml;
- else {
- if (item.containsKey(key))
- candidateYaml = itemYaml;
- else
- candidateYaml = key + ":\n" + makeAsIndentedList(itemYaml);
- }
- // first look in collected items, if a key is given
- String type = (String) item.get("type");
- String version = null;
- if (CatalogUtils.looksLikeVersionedId(type)) {
- version = CatalogUtils.getVersionFromVersionedId(type);
- type = CatalogUtils.getIdFromVersionedId(type);
- }
- if (type!=null && key!=null) {
- for (CatalogItemDtoAbstract<?,?> candidate: itemsDefinedSoFar) {
- if (candidateCiType == candidate.getCatalogItemType() &&
- (type.equals(candidate.getSymbolicName()) || type.equals(candidate.getId()))) {
- if (version==null || version.equals(candidate.getVersion())) {
- // matched - exit
- catalogItemType = candidateCiType;
- planYaml = candidateYaml;
- resolved = true;
- return true;
- }
- }
- }
- }
-
- // then try parsing plan - this will use loader
- try {
- DeploymentPlan candidatePlan = makePlanFromYaml(candidateYaml);
- spec = createSpec(id, candidateCiType, candidatePlan, loader);
- if (spec!=null) {
- catalogItemType = candidateCiType;
- plan = candidatePlan;
- planYaml = candidateYaml;
- resolved = true;
- }
- return true;
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- // record the error if we have reason to expect this guess to succeed
- if (item.containsKey("services") && (candidateCiType==CatalogItemType.ENTITY || candidateCiType==CatalogItemType.TEMPLATE)) {
- // explicit services supplied, so plan should have been parseable for an entity or a a service
- errors.add(e);
- } else if (catalogItemType!=null && key!=null) {
- // explicit itemType supplied, so plan should be parseable in the cases where we're given a key
- // (when we're not given a key, the previous block should apply)
- errors.add(e);
- } else {
- // all other cases, the error is probably due to us not getting the type right, ignore it
- if (log.isTraceEnabled())
- log.trace("Guessing type of plan, it looks like it isn't "+candidateCiType+"/"+key+": "+e);
- }
- }
-
- // finally try parsing a cut-down plan, in case there is a nested reference to a newly defined catalog item
- if (type!=null && key!=null) {
- try {
- String cutDownYaml = key + ":\n" + makeAsIndentedList("type: "+type);
- DeploymentPlan candidatePlan = makePlanFromYaml(cutDownYaml);
- Object cutdownSpec = createSpec(id, candidateCiType, candidatePlan, loader);
- if (cutdownSpec!=null) {
- catalogItemType = candidateCiType;
- planYaml = candidateYaml;
- resolved = true;
- }
- return true;
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- }
- }
-
- return false;
- }
- public Map<?,?> getItem() {
- return item;
- }
- }
-
- private String makeAsIndentedList(String yaml) {
- String[] lines = yaml.split("\n");
- lines[0] = "- "+lines[0];
- for (int i=1; i<lines.length; i++)
- lines[i] = " " + lines[i];
- return Strings.join(lines, "\n");
- }
-
- private String makeAsIndentedObject(String yaml) {
- String[] lines = yaml.split("\n");
- for (int i=0; i<lines.length; i++)
- lines[i] = " " + lines[i];
- return Strings.join(lines, "\n");
- }
-
- private CatalogItemBuilder<?> createItemBuilder(CatalogItemType itemType, String itemId, String version) {
- Preconditions.checkNotNull(itemType, "itemType required");
- switch (itemType) {
- case ENTITY: return CatalogItemBuilder.newEntity(itemId, version);
- case TEMPLATE: return CatalogItemBuilder.newTemplate(itemId, version);
- case POLICY: return CatalogItemBuilder.newPolicy(itemId, version);
- case LOCATION: return CatalogItemBuilder.newLocation(itemId, version);
- }
- throw new IllegalStateException("Unexpected itemType: "+itemType);
- }
-
- // these kept as their logic may prove useful; Apr 2015
-// private boolean isApplicationSpec(EntitySpec<?> spec) {
-// return !Boolean.TRUE.equals(spec.getConfig().get(EntityManagementUtils.WRAPPER_APP_MARKER));
-// }
-//
-// private boolean isEntityPlan(DeploymentPlan plan) {
-// return plan!=null && !plan.getServices().isEmpty() || !plan.getArtifacts().isEmpty();
-// }
-//
-// private boolean isPolicyPlan(DeploymentPlan plan) {
-// return !isEntityPlan(plan) && plan.getCustomAttributes().containsKey(POLICIES_KEY);
-// }
-//
-// private boolean isLocationPlan(DeploymentPlan plan) {
-// return !isEntityPlan(plan) && plan.getCustomAttributes().containsKey(LOCATIONS_KEY);
-// }
-
- private DeploymentPlan makePlanFromYaml(String yaml) {
- CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
- return camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
- }
-
- //------------------------
-
- @Override
- public CatalogItem<?,?> addItem(String yaml) {
- return addItem(yaml, false);
- }
-
- @Override
- public List<? extends CatalogItem<?,?>> addItems(String yaml) {
- return addItems(yaml, false);
- }
-
- @Override
- public CatalogItem<?,?> addItem(String yaml, boolean forceUpdate) {
- return Iterables.getOnlyElement(addItems(yaml, forceUpdate));
- }
-
- @Override
- public List<? extends CatalogItem<?,?>> addItems(String yaml, boolean forceUpdate) {
- log.debug("Adding manual catalog item to "+mgmt+": "+yaml);
- checkNotNull(yaml, "yaml");
- List<CatalogItemDtoAbstract<?, ?>> result = collectCatalogItems(yaml);
- // do this at the end for atomic updates; if there are intra-yaml references, we handle them specially
- for (CatalogItemDtoAbstract<?, ?> item: result) {
- addItemDto(item, forceUpdate);
- }
- return result;
- }
-
- private CatalogItem<?,?> addItemDto(CatalogItemDtoAbstract<?, ?> itemDto, boolean forceUpdate) {
- CatalogItem<?, ?> existingDto = checkItemAllowedAndIfSoReturnAnyDuplicate(itemDto, true, forceUpdate);
- if (existingDto!=null) {
- // it's a duplicate, and not forced, just return it
- log.trace("Using existing duplicate for catalog item {}", itemDto.getId());
- return existingDto;
- }
-
- if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
- manualAdditionsCatalog.addEntry(itemDto);
-
- // Ensure the cache is populated and it is persisted by the management context
- getCatalog().addEntry(itemDto);
-
- // Request that the management context persist the item.
- if (log.isTraceEnabled()) {
- log.trace("Scheduling item for persistence addition: {}", itemDto.getId());
- }
- if (itemDto.getCatalogItemType() == CatalogItemType.LOCATION) {
- @SuppressWarnings("unchecked")
- CatalogItem<Location,LocationSpec<?>> locationItem = (CatalogItem<Location, LocationSpec<?>>) itemDto;
- ((BasicLocationRegistry)mgmt.getLocationRegistry()).updateDefinedLocation(locationItem);
- }
- mgmt.getRebindManager().getChangeListener().onManaged(itemDto);
-
- return itemDto;
- }
-
- /** returns item DTO if item is an allowed duplicate, or null if it should be added (there is no duplicate),
- * throwing if item cannot be added */
- private CatalogItem<?, ?> checkItemAllowedAndIfSoReturnAnyDuplicate(CatalogItem<?,?> itemDto, boolean allowDuplicates, boolean forceUpdate) {
- if (forceUpdate) return null;
- CatalogItemDo<?, ?> existingItem = getCatalogItemDo(itemDto.getSymbolicName(), itemDto.getVersion());
- if (existingItem == null) return null;
- // check if they are equal
- CatalogItem<?, ?> existingDto = existingItem.getDto();
- if (existingDto.equals(itemDto)) {
- if (allowDuplicates) return existingItem;
- throw new IllegalStateException("Updating existing catalog entries, even with the same content, is forbidden: " +
- itemDto.getSymbolicName() + ":" + itemDto.getVersion() + ". Use forceUpdate argument to override.");
- } else {
- throw new IllegalStateException("Updating existing catalog entries is forbidden: " +
- itemDto.getSymbolicName() + ":" + itemDto.getVersion() + ". Use forceUpdate argument to override.");
- }
- }
-
- @Override @Deprecated /** @deprecated see super */
- public void addItem(CatalogItem<?,?> item) {
- //assume forceUpdate for backwards compatibility
- log.debug("Adding manual catalog item to "+mgmt+": "+item);
- checkNotNull(item, "item");
- CatalogUtils.installLibraries(mgmt, item.getLibraries());
- if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
- manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item));
- }
-
- @Override @Deprecated /** @deprecated see super */
- public CatalogItem<?,?> addItem(Class<?> type) {
- //assume forceUpdate for backwards compatibility
- log.debug("Adding manual catalog item to "+mgmt+": "+type);
- checkNotNull(type, "type");
- if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
- manualAdditionsClasses.addClass(type);
- return manualAdditionsCatalog.classpath.addCatalogEntry(type);
- }
-
- private synchronized void loadManualAdditionsCatalog() {
- if (manualAdditionsCatalog!=null) return;
- CatalogDto manualAdditionsCatalogDto = CatalogDto.newNamedInstance(
- "Manual Catalog Additions", "User-additions to the catalog while Brooklyn is running, " +
- "created "+Time.makeDateString(),
- "manual-additions");
- CatalogDo manualAdditionsCatalog = catalog.addCatalog(manualAdditionsCatalogDto);
- if (manualAdditionsCatalog==null) {
- // not hard to support, but slightly messy -- probably have to use ID's to retrieve the loaded instance
- // for now block once, then retry
- log.warn("Blocking until catalog is loaded before changing it");
- boolean loaded = blockIfNotLoaded(Duration.TEN_SECONDS);
- if (!loaded)
- log.warn("Catalog still not loaded after delay; subsequent operations may fail");
- manualAdditionsCatalog = catalog.addCatalog(manualAdditionsCatalogDto);
- if (manualAdditionsCatalog==null) {
- throw new UnsupportedOperationException("Catalogs cannot be added until the base catalog is loaded, and catalog is taking a while to load!");
- }
- }
-
- log.debug("Creating manual additions catalog for "+mgmt+": "+manualAdditionsCatalog);
- manualAdditionsClasses = new LoadedClassLoader();
- ((AggregateClassLoader)manualAdditionsCatalog.classpath.getLocalClassLoader()).addFirst(manualAdditionsClasses);
-
- // expose when we're all done
- this.manualAdditionsCatalog = manualAdditionsCatalog;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- public <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems() {
- if (!getCatalog().isLoaded()) {
- // some callers use this to force the catalog to load (maybe when starting as hot_backup without a catalog ?)
- log.debug("Forcing catalog load on access of catalog items");
- load();
- }
- return ImmutableList.copyOf((Iterable)catalog.getIdCache().values());
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- public <T,SpecT> Iterable<CatalogItem<T,SpecT>> getCatalogItems(Predicate<? super CatalogItem<T,SpecT>> filter) {
- Iterable<CatalogItemDo<T,SpecT>> filtered = Iterables.filter((Iterable)catalog.getIdCache().values(), (Predicate<CatalogItem<T,SpecT>>)(Predicate) filter);
- return Iterables.transform(filtered, BasicBrooklynCatalog.<T,SpecT>itemDoToDto());
- }
-
- private static <T,SpecT> Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>> itemDoToDto() {
- return new Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>>() {
- @Override
- public CatalogItem<T,SpecT> apply(@Nullable CatalogItemDo<T,SpecT> item) {
- if (item==null) return null;
- return item.getDto();
- }
- };
- }
-
- private static <T,SpecT> Function<CatalogItemDo<T, SpecT>, CatalogItem<T,SpecT>> itemDoToDtoAddingSelectedMetadataDuringScan(final Map<Object, Object> catalogMetadata) {
- return new Function<CatalogItemDo<T,SpecT>, CatalogItem<T,SpecT>>() {
- @Override
- public CatalogItem<T,SpecT> apply(@Nullable CatalogItemDo<T,SpecT> item) {
- if (item==null) return null;
- CatalogItemDtoAbstract<T, SpecT> dto = (CatalogItemDtoAbstract<T, SpecT>) item.getDto();
-
- // when scanning we only allow version and libraries to be overwritten
-
- String version = getFirstAs(catalogMetadata, String.class, "version").orNull();
- if (Strings.isNonBlank(version)) dto.setVersion(version);
-
- Object librariesCombined = catalogMetadata.get("brooklyn.libraries");
- if (librariesCombined instanceof Collection) {
- // will be set by scan -- slightly longwinded way to retrieve, but scanning for osgi needs an overhaul in any case
- Collection<CatalogBundle> libraryBundles = CatalogItemDtoAbstract.parseLibraries((Collection<?>) librariesCombined);
- dto.setLibraries(libraryBundles);
- }
- // replace java type with plan yaml -- needed for libraries / catalog item to be picked up,
- // but probably useful to transition away from javaType altogether
- dto.setSymbolicName(dto.getJavaType());
- switch (dto.getCatalogItemType()) {
- case TEMPLATE:
- case ENTITY:
- dto.setPlanYaml("services: [{ type: "+dto.getJavaType()+" }]");
- break;
- case POLICY:
- dto.setPlanYaml(POLICIES_KEY + ": [{ type: "+dto.getJavaType()+" }]");
- break;
- case LOCATION:
- dto.setPlanYaml(LOCATIONS_KEY + ": [{ type: "+dto.getJavaType()+" }]");
- break;
- }
- dto.setJavaType(null);
-
- return dto;
- }
- };
- }
-
- transient CatalogXmlSerializer serializer;
-
- public String toXmlString() {
- if (serializer==null) loadSerializer();
- return serializer.toString(catalog.dto);
- }
-
- private synchronized void loadSerializer() {
- if (serializer==null)
- serializer = new CatalogXmlSerializer();
- }
-
- @Deprecated
- public CatalogItem<?,?> getCatalogItemForType(String typeName) {
- final CatalogItem<?,?> resultI;
- final BrooklynCatalog catalog = mgmt.getCatalog();
- if (CatalogUtils.looksLikeVersionedId(typeName)) {
- //All catalog identifiers of the form xxxx:yyyy are composed of symbolicName+version.
- //No javaType is allowed as part of the identifier.
- resultI = CatalogUtils.getCatalogItemOptionalVersion(mgmt, typeName);
- } else {
- //Usually for catalog items with javaType (that is items from catalog.xml)
- //the symbolicName and javaType match because symbolicName (was ID)
- //is not specified explicitly. But could be the case that there is an item
- //whose symbolicName is explicitly set to be different from the javaType.
- //Note that in the XML the attribute is called registeredTypeName.
- Iterable<CatalogItem<Object,Object>> resultL = catalog.getCatalogItems(CatalogPredicates.javaType(Predicates.equalTo(typeName)));
- if (!Iterables.isEmpty(resultL)) {
- //Push newer versions in front of the list (not that there should
- //be more than one considering the items are coming from catalog.xml).
- resultI = sortVersionsDesc(resultL).iterator().next();
- if (log.isDebugEnabled() && Iterables.size(resultL)>1) {
- log.debug("Found "+Iterables.size(resultL)+" matches in catalog for type "+typeName+"; returning the result with preferred version, "+resultI);
- }
- } else {
- //As a last resort try searching for items with the same symbolicName supposedly
- //different from the javaType.
- resultI = catalog.getCatalogItem(typeName, BrooklynCatalog.DEFAULT_VERSION);
- if (resultI != null) {
- if (resultI.getJavaType() == null) {
- //Catalog items scanned from the classpath (using reflection and annotations) now
- //get yaml spec rather than a java type. Can't use those when creating apps from
- //the legacy app spec format.
- log.warn("Unable to find catalog item for type "+typeName +
- ". There is an existing catalog item with ID " + resultI.getId() +
- " but it doesn't define a class type.");
- return null;
- }
- }
- }
- }
- return resultI;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/brooklyn/catalog/internal/CatalogBundleConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogBundleConverter.java b/core/src/main/java/brooklyn/catalog/internal/CatalogBundleConverter.java
deleted file mode 100644
index 5ef4a96..0000000
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogBundleConverter.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.catalog.internal;
-
-import com.thoughtworks.xstream.converters.Converter;
-import com.thoughtworks.xstream.converters.MarshallingContext;
-import com.thoughtworks.xstream.converters.UnmarshallingContext;
-import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
-import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
-import com.thoughtworks.xstream.io.HierarchicalStreamReader;
-import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
-import com.thoughtworks.xstream.mapper.Mapper;
-
-
-/**
- * Convert old-style catalog.xml file formats to the latest version.
- * The code is needed only during transition to the new version, can be removed after a while.
- */
-@Deprecated
-public class CatalogBundleConverter implements Converter {
-
- private ReflectionConverter delegateConverter;
-
- public CatalogBundleConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
- this.delegateConverter = new ReflectionConverter(mapper, reflectionProvider);
- }
-
- @Override
- public boolean canConvert(@SuppressWarnings("rawtypes") Class type) {
- return type == CatalogBundleDto.class;
- }
-
- @Override
- public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
- context.convertAnother(source, delegateConverter);
- }
-
- @Override
- public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
- if (reader.hasMoreChildren()) {
- return context.convertAnother(context.currentObject(), CatalogBundleDto.class, delegateConverter);
- } else {
- return new CatalogBundleDto(null, null, reader.getValue());
- }
- }
-
-}
[29/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/catalog
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java
new file mode 100644
index 0000000..2bf9cca
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDo.java
@@ -0,0 +1,334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import org.reflections.util.ClasspathHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.api.catalog.Catalog;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.javalang.AggregateClassLoader;
+import brooklyn.util.javalang.ReflectionScanner;
+import brooklyn.util.javalang.UrlClassLoader;
+import brooklyn.util.os.Os;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Time;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Iterables;
+
+public class CatalogClasspathDo {
+
+ public static enum CatalogScanningModes {
+ /** the classpath is not scanned;
+ * for any catalog which is presented over the internet this is recommended (to prevent loading) and is the default;
+ * (you should explicitly list the items to include; it may be useful to autogenerate it by using a local catalog
+ * scanning with ANNOTATIONS, viwing that by running mgmt.getCatalog().toXmlString(),
+ * then editing the resulting XML (e.g. setting the classpath and removing the scan attribute) */
+ NONE,
+
+ /** types in the classpath are scanned for annotations indicating inclusion in the catalog ({@link Catalog});
+ * this is the default if no catalog is supplied, scanning the local classpath */
+ ANNOTATIONS,
+
+ @Beta
+ /** all catalog-friendly types are included,
+ * even if not annotated for inclusion in the catalog; useful for quick hacking,
+ * or a classpath (and possibly in future a regex, if added) which is known to have only good things in it;
+ * however the precise semantics of what is included is subject to change,
+ * and it is strongly recommended to use the {@link Catalog} annotation and scan for annotations
+ * <p>
+ * a catalog-friendly type is currently defined as:
+ * any concrete non-anonymous (and not a non-static inner) class implementing Entity or Policy;
+ * and additionally for entities and applications, an interface with the {@link ImplementedBy} annotation;
+ * note that this means classes done "properly" with both an interface and an implementation
+ * will be included twice, once as interface and once as implementation;
+ * this guarantees inclusion of anything previously included (implementations;
+ * and this will be removed from catalog in future likely),
+ * plus things now done properly (which will become the only way in the future)
+ **/
+ TYPES
+ }
+
+ private static final Logger log = LoggerFactory.getLogger(CatalogClasspathDo.class);
+
+ private final CatalogDo catalog;
+ private final CatalogClasspathDto classpath;
+ private final CatalogScanningModes scanMode;
+
+ boolean isLoaded = false;
+ private URL[] urls;
+
+ private final AggregateClassLoader classloader = AggregateClassLoader.newInstanceWithNoLoaders();
+ private volatile boolean classloaderLoaded = false;
+
+ public CatalogClasspathDo(CatalogDo catalog) {
+ this.catalog = Preconditions.checkNotNull(catalog, "catalog");
+ this.classpath = catalog.dto.classpath;
+ this.scanMode = (classpath != null) ? classpath.scan : null;
+ }
+
+ /** causes all scanning-based classpaths to scan the classpaths
+ * (but does _not_ load all JARs) */
+ // TODO this does a Java scan; we also need an OSGi scan which uses the OSGi classloaders when loading for scanning and resolving dependencies
+ synchronized void load() {
+ if (classpath == null || isLoaded) return;
+
+ if (classpath.getEntries() == null) {
+ urls = new URL[0];
+ } else {
+ urls = new URL[classpath.getEntries().size()];
+ for (int i=0; i<urls.length; i++) {
+ try {
+ String u = classpath.getEntries().get(i);
+ if (u.startsWith("classpath:")) {
+ // special support for classpath: url's
+ // TODO put convenience in ResourceUtils for extracting to a normal url
+ // (or see below)
+ InputStream uin = ResourceUtils.create(this).getResourceFromUrl(u);
+ File f = Os.newTempFile("brooklyn-catalog-"+u, null);
+ FileOutputStream fout = new FileOutputStream(f);
+ try {
+ Streams.copy(uin, fout);
+ } finally {
+ Streams.closeQuietly(fout);
+ Streams.closeQuietly(uin);
+ }
+ u = f.toURI().toString();
+ }
+ urls[i] = new URL(u);
+
+ // TODO potential disk leak above as we have no way to know when the temp file can be removed earlier than server shutdown;
+ // a better way to handle this is to supply a stream handler (but URLConnection is a little bit hard to work with):
+// urls[i] = new URL(null, classpath.getEntries().get(i) // (handy construtor for reparsing urls, without splitting into uri first)
+// , new URLStreamHandler() {
+// @Override
+// protected URLConnection openConnection(URL u) throws IOException {
+// new ResourceUtils(null). ???
+// }
+// });
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ log.error("Error loading URL "+classpath.getEntries().get(i)+" in definition of catalog "+catalog+"; skipping definition");
+ throw Exceptions.propagate(e);
+ }
+ }
+ }
+
+ // prefix is supported (but not really used yet) --
+ // seems to have _better_ URL-discovery with prefixes
+ // (might also offer regex ? but that is post-load filter as opposed to native optimisation)
+ String prefix = null;
+
+ if (scanMode==null || scanMode==CatalogScanningModes.NONE)
+ return;
+
+ Stopwatch timer = Stopwatch.createStarted();
+ ReflectionScanner scanner = null;
+ if (!catalog.isLocal()) {
+ log.warn("Scanning not supported for remote catalogs; ignoring scan request in "+catalog);
+ } else if (classpath.getEntries() == null || classpath.getEntries().isEmpty()) {
+ // scan default classpath:
+ ClassLoader baseCL = null;
+ Iterable<URL> baseCP = null;
+ if (catalog.mgmt instanceof ManagementContextInternal) {
+ baseCL = ((ManagementContextInternal)catalog.mgmt).getBaseClassLoader();
+ baseCP = ((ManagementContextInternal)catalog.mgmt).getBaseClassPathForScanning();
+ }
+ scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
+ if (scanner.getSubTypesOf(Entity.class).isEmpty()) {
+ try {
+ ((ManagementContextInternal)catalog.mgmt).setBaseClassPathForScanning(ClasspathHelper.forJavaClassPath());
+ log.debug("Catalog scan of default classloader returned nothing; reverting to java.class.path");
+ baseCP = ((ManagementContextInternal)catalog.mgmt).getBaseClassPathForScanning();
+ scanner = new ReflectionScanner(baseCP, prefix, baseCL, catalog.getRootClassLoader());
+ } catch (Exception e) {
+ log.info("Catalog scan is empty, and unable to use java.class.path (base classpath is "+baseCP+"): "+e);
+ Exceptions.propagateIfFatal(e);
+ }
+ }
+ } else {
+ // scan specified jars:
+ scanner = new ReflectionScanner(urls==null || urls.length==0 ? null : Arrays.asList(urls), prefix, getLocalClassLoader());
+ }
+
+ if (scanner!=null) {
+ int count = 0, countApps = 0;
+ if (scanMode==CatalogScanningModes.ANNOTATIONS) {
+ Set<Class<?>> catalogClasses = scanner.getTypesAnnotatedWith(Catalog.class);
+ for (Class<?> c: catalogClasses) {
+ try {
+ CatalogItem<?,?> item = addCatalogEntry(c);
+ count++;
+ if (CatalogTemplateItemDto.class.isInstance(item)) countApps++;
+ } catch (Exception e) {
+ log.warn("Failed to add catalog entry for "+c+"; continuing scan...", e);
+ }
+ }
+ } else if (scanMode==CatalogScanningModes.TYPES) {
+ Iterable<Class<?>> entities = this.excludeInvalidClasses(
+ Iterables.concat(scanner.getSubTypesOf(Entity.class),
+ // not sure why we have to look for sub-types of Application,
+ // they should be picked up as sub-types of Entity, but in maven builds (only!)
+ // they are not -- i presume a bug in scanner
+ scanner.getSubTypesOf(Application.class),
+ scanner.getSubTypesOf(ApplicationBuilder.class)));
+ for (Class<?> c: entities) {
+ if (Application.class.isAssignableFrom(c) || ApplicationBuilder.class.isAssignableFrom(c)) {
+ addCatalogEntry(new CatalogTemplateItemDto(), c);
+ countApps++;
+ } else {
+ addCatalogEntry(new CatalogEntityItemDto(), c);
+ }
+ count++;
+ }
+ Iterable<Class<? extends Policy>> policies = this.excludeInvalidClasses(scanner.getSubTypesOf(Policy.class));
+ for (Class<?> c: policies) {
+ addCatalogEntry(new CatalogPolicyItemDto(), c);
+ count++;
+ }
+
+ Iterable<Class<? extends Location>> locations = this.excludeInvalidClasses(scanner.getSubTypesOf(Location.class));
+ for (Class<?> c: locations) {
+ addCatalogEntry(new CatalogLocationItemDto(), c);
+ count++;
+ }
+ } else {
+ throw new IllegalStateException("Unsupported catalog scan mode "+scanMode+" for "+this);
+ }
+ log.debug("Catalog '"+catalog.dto.name+"' classpath scan completed: loaded "+
+ count+" item"+Strings.s(count)+" ("+countApps+" app"+Strings.s(countApps)+") in "+Time.makeTimeStringRounded(timer));
+ }
+
+ isLoaded = true;
+ }
+
+ /** removes inner classes (non-static nesteds) and others;
+ * bear in mind named ones will be hard to instantiate without the outer class instance) */
+ private <T> Iterable<Class<? extends T>> excludeInvalidClasses(Iterable<Class<? extends T>> input) {
+ Predicate<Class<? extends T>> f = new Predicate<Class<? extends T>>() {
+ @Override
+ public boolean apply(@Nullable Class<? extends T> input) {
+ if (input==null) return false;
+ if (input.isLocalClass() || input.isAnonymousClass()) return false;
+ if (Modifier.isAbstract(input.getModifiers())) {
+ if (input.getAnnotation(ImplementedBy.class)==null)
+ return false;
+ }
+ // non-abstract top-level classes are okay
+ if (!input.isMemberClass()) return true;
+ if (!Modifier.isStatic(input.getModifiers())) return false;
+ // nested classes only okay if static
+ return true;
+ }
+ };
+ return Iterables.filter(input, f);
+ }
+
+ /** augments the given item with annotations and class data for the given class, then adds to catalog
+ * @deprecated since 0.7.0 the classpath DO is replaced by libraries */
+ @Deprecated
+ public CatalogItem<?,?> addCatalogEntry(Class<?> c) {
+ if (Application.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
+ if (ApplicationBuilder.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogTemplateItemDto(), c);
+ if (Entity.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogEntityItemDto(), c);
+ if (Policy.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogPolicyItemDto(), c);
+ if (Location.class.isAssignableFrom(c)) return addCatalogEntry(new CatalogLocationItemDto(), c);
+ throw new IllegalStateException("Cannot add "+c+" to catalog: unsupported type "+c.getName());
+ }
+
+ /** augments the given item with annotations and class data for the given class, then adds to catalog
+ * @deprecated since 0.7.0 the classpath DO is replaced by libraries */
+ @Deprecated
+ public CatalogItem<?,?> addCatalogEntry(CatalogItemDtoAbstract<?,?> item, Class<?> c) {
+ Catalog annotations = c.getAnnotation(Catalog.class);
+ item.setSymbolicName(c.getName());
+ item.setJavaType(c.getName());
+ item.setDisplayName(firstNonEmpty(c.getSimpleName(), c.getName()));
+ if (annotations!=null) {
+ item.setDisplayName(firstNonEmpty(annotations.name(), item.getDisplayName()));
+ item.setDescription(firstNonEmpty(annotations.description()));
+ item.setIconUrl(firstNonEmpty(annotations.iconUrl()));
+ }
+ if (log.isTraceEnabled())
+ log.trace("adding to catalog: "+c+" (from catalog "+catalog+")");
+ catalog.addEntry(item);
+ return item;
+ }
+
+ private static String firstNonEmpty(String ...candidates) {
+ for (String c: candidates)
+ if (c!=null && !c.isEmpty()) return c;
+ return null;
+ }
+
+ /** returns classloader for the entries specified here */
+ public ClassLoader getLocalClassLoader() {
+ if (!classloaderLoaded) loadLocalClassLoader();
+ return classloader;
+ }
+
+ protected synchronized void loadLocalClassLoader() {
+ if (classloaderLoaded) return;
+ if (urls==null) return;
+ classloader.addFirst(new UrlClassLoader(urls));
+ classloaderLoaded = true;
+ return;
+ }
+
+ /** adds the given URL as something this classloader will load
+ * (however no scanning is done) */
+ public void addToClasspath(URL u, boolean updateDto) {
+ if (updateDto) classpath.getEntries().add(u.toExternalForm());
+ addToClasspath(new UrlClassLoader(u));
+ }
+
+ /** adds the given URL as something this classloader will load
+ * (however no scanning is done).
+ * <p>
+ * the DTO will _not_ be updated. */
+ public void addToClasspath(ClassLoader loader) {
+ classloader.addFirst(loader);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDto.java
new file mode 100644
index 0000000..5779a4e
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogClasspathDto.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+
+public class CatalogClasspathDto {
+
+ /** whether/what to scan; defaults to 'none' */
+ CatalogScanningModes scan;
+ private List<String> entries;
+
+ public synchronized void addEntry(String url) {
+ if (entries==null)
+ entries = new CopyOnWriteArrayList<String>();
+
+ entries.add(url);
+ }
+
+ public synchronized List<String> getEntries() {
+ return entries;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDo.java
new file mode 100644
index 0000000..8e53e28
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDo.java
@@ -0,0 +1,365 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.javalang.AggregateClassLoader;
+import brooklyn.util.net.Urls;
+import brooklyn.util.time.CountdownTimer;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+
+public class CatalogDo {
+
+ private static final Logger log = LoggerFactory.getLogger(CatalogDo.class);
+
+ volatile boolean isLoaded = false;
+ final CatalogDto dto;
+ ManagementContext mgmt = null;
+ CatalogDo parent = null;
+
+ List<CatalogDo> childrenCatalogs = new ArrayList<CatalogDo>();
+ CatalogClasspathDo classpath;
+ private Map<String, CatalogItemDo<?,?>> cacheById;
+
+ AggregateClassLoader childrenClassLoader = AggregateClassLoader.newInstanceWithNoLoaders();
+ ClassLoader recursiveClassLoader;
+
+ protected CatalogDo(CatalogDto dto) {
+ this.dto = Preconditions.checkNotNull(dto);
+ }
+
+ public CatalogDo(ManagementContext mgmt, CatalogDto dto) {
+ this(dto);
+ this.mgmt = mgmt;
+ }
+
+ boolean isLoaded() {
+ return isLoaded;
+ }
+
+ /** Calls {@link #load(CatalogDo)} with a null parent. */
+ public CatalogDo load() {
+ return load(null);
+ }
+
+ /** Calls {@link #load(ManagementContext, CatalogDo)} with the catalog's existing management context. */
+ public CatalogDo load(CatalogDo parent) {
+ return load(mgmt, parent);
+ }
+
+ /** Calls {@link #load(ManagementContext, CatalogDo, boolean)} failing on load errors. */
+ public synchronized CatalogDo load(ManagementContext mgmt, CatalogDo parent) {
+ return load(mgmt, parent, true);
+ }
+
+ /** causes all URL-based catalogs to have their manifests loaded,
+ * and all scanning-based classpaths to scan the classpaths
+ * (but does not load all JARs)
+ */
+ public synchronized CatalogDo load(ManagementContext mgmt, CatalogDo parent, boolean failOnLoadError) {
+ if (isLoaded()) {
+ if (mgmt!=null && !Objects.equal(mgmt, this.mgmt)) {
+ throw new IllegalStateException("Cannot set mgmt "+mgmt+" on "+this+" after catalog is loaded");
+ }
+ log.debug("Catalog "+this+" is already loaded");
+ return this;
+ }
+ loadThisCatalog(mgmt, parent, failOnLoadError);
+ loadChildrenCatalogs(failOnLoadError);
+ buildCaches();
+ return this;
+ }
+
+ protected synchronized void loadThisCatalog(ManagementContext mgmt, CatalogDo parent, boolean failOnLoadError) {
+ if (isLoaded()) return;
+ CatalogUtils.logDebugOrTraceIfRebinding(log, "Loading catalog {} into {}", this, parent);
+ if (this.parent!=null && !this.parent.equals(parent))
+ log.warn("Catalog "+this+" being initialised with different parent "+parent+" when already parented by "+this.parent, new Throwable("source of reparented "+this));
+ if (this.mgmt!=null && !this.mgmt.equals(mgmt))
+ log.warn("Catalog "+this+" being initialised with different mgmt "+mgmt+" when already managed by "+this.mgmt, new Throwable("source of reparented "+this));
+ this.parent = parent;
+ this.mgmt = mgmt;
+ dto.populate();
+ loadCatalogClasspath();
+ loadCatalogItems(failOnLoadError);
+ isLoaded = true;
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+
+ private void loadCatalogClasspath() {
+ try {
+ classpath = new CatalogClasspathDo(this);
+ classpath.load();
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ log.error("Unable to load catalog "+this+" (ignoring): "+e);
+ log.info("Trace for failure to load "+this+": "+e, e);
+ }
+ }
+
+ private void loadCatalogItems(boolean failOnLoadError) {
+ Iterable<CatalogItemDtoAbstract<?, ?>> entries = dto.getUniqueEntries();
+ if (entries!=null) {
+ for (CatalogItemDtoAbstract<?,?> entry : entries) {
+ try {
+ CatalogUtils.installLibraries(mgmt, entry.getLibraries());
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ if (failOnLoadError) {
+ Exceptions.propagate(e);
+ } else {
+ log.error("Loading bundles for catalog item " + entry + " failed: " + e.getMessage(), e);
+ }
+ }
+ }
+ }
+ }
+
+ public boolean blockIfNotLoaded(Duration timeout) throws InterruptedException {
+ if (isLoaded()) return true;
+ synchronized (this) {
+ if (isLoaded()) return true;
+ CountdownTimer timer = CountdownTimer.newInstanceStarted(timeout);
+ while (!isLoaded())
+ if (!timer.waitOnForExpiry(this))
+ return false;
+ return true;
+ }
+ }
+
+ protected void loadChildrenCatalogs(boolean failOnLoadError) {
+ if (dto.catalogs!=null) {
+ for (CatalogDto child: dto.catalogs) {
+ loadCatalog(child, failOnLoadError);
+ }
+ }
+ }
+
+ CatalogDo loadCatalog(CatalogDto child, boolean failOnLoadError) {
+ CatalogDo childL = new CatalogDo(child);
+ childrenCatalogs.add(childL);
+ childL.load(mgmt, this, failOnLoadError);
+ childrenClassLoader.addFirst(childL.getRecursiveClassLoader());
+ clearCache(false);
+ return childL;
+ }
+
+ protected Map<String, CatalogItemDo<?,?>> getIdCache() {
+ Map<String, CatalogItemDo<?,?>> cache = this.cacheById;
+ if (cache==null) cache = buildCaches();
+ return cache;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected synchronized Map<String, CatalogItemDo<?,?>> buildCaches() {
+ if (cacheById != null) return cacheById;
+ CatalogUtils.logDebugOrTraceIfRebinding(log, "Building cache for {}", this);
+ if (!isLoaded())
+ log.debug("Catalog not fully loaded when loading cache of "+this);
+
+ Map<String, CatalogItemDo<?,?>> cache = new LinkedHashMap<String, CatalogItemDo<?,?>>();
+
+ // build the cache; first from children catalogs, then from local entities
+ // so that root and near-root takes precedence over deeper items;
+ // and go through in reverse order so that things at the top of the file take precedence
+ // (both in the cache and in the aggregate class loader);
+ // however anything added _subsequently_ will take precedence (again in both)
+ if (dto.catalogs!=null) {
+ List<CatalogDo> catalogsReversed = new ArrayList<CatalogDo>(childrenCatalogs);
+ Collections.reverse(catalogsReversed);
+ for (CatalogDo child: catalogsReversed) {
+ cache.putAll(child.getIdCache());
+ }
+ }
+ if (dto.getUniqueEntries()!=null) {
+ List<CatalogItemDtoAbstract<?,?>> entriesReversed = MutableList.copyOf(dto.getUniqueEntries());
+ Collections.reverse(entriesReversed);
+ for (CatalogItemDtoAbstract<?,?> entry: entriesReversed)
+ cache.put(entry.getId(), new CatalogItemDo(this, entry));
+ }
+ this.cacheById = cache;
+ return cache;
+ }
+
+ protected synchronized void clearCache(boolean deep) {
+ this.cacheById = null;
+ if (deep) {
+ for (CatalogDo child : childrenCatalogs) {
+ child.clearCache(true);
+ }
+ }
+ clearParentCache();
+ }
+ protected void clearParentCache() {
+ if (this.parent!=null)
+ this.parent.clearCache(false);
+ }
+
+ /**
+ * Adds the given entry to the catalog, with no enrichment.
+ * Callers may prefer {@link CatalogClasspathDo#addCatalogEntry(CatalogItemDtoAbstract, Class)}
+ */
+ public synchronized void addEntry(CatalogItemDtoAbstract<?,?> entry) {
+ dto.addEntry(entry);
+
+ // could do clearCache(false); but this is slightly more efficient...
+ if (cacheById != null) {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ CatalogItemDo<?, ?> cdo = new CatalogItemDo(this, entry);
+ cacheById.put(entry.getId(), cdo);
+ }
+ clearParentCache();
+
+ if (mgmt != null) {
+ mgmt.getRebindManager().getChangeListener().onManaged(entry);
+ }
+ }
+
+ /**
+ * Removes the given entry from the catalog.
+ */
+ public synchronized void deleteEntry(CatalogItemDtoAbstract<?, ?> entry) {
+ dto.removeEntry(entry);
+
+ // could do clearCache(false); but this is slightly more efficient...
+ if (cacheById != null) {
+ cacheById.remove(entry.getId());
+ }
+ clearParentCache();
+
+ if (mgmt != null) {
+ // TODO: Can the entry be in more than one catalogue? The management context has no notion of
+ // catalogue hierarchy so this will effectively remove it from all catalogues.
+ // (YES- we're assuming ID's are unique across all catalogues; if not, things get out of sync;
+ // however see note at top of BasicBrooklynCatalog --
+ // manualCatalog and OSGi is used for everything now except legacy XML trees)
+ mgmt.getRebindManager().getChangeListener().onUnmanaged(entry);
+ }
+ }
+
+ /** returns loaded catalog, if this has been loaded */
+ CatalogDo addCatalog(CatalogDto child) {
+ if (dto.catalogs == null)
+ dto.catalogs = new ArrayList<CatalogDto>();
+ dto.catalogs.add(child);
+ if (!isLoaded())
+ return null;
+ return loadCatalog(child, true);
+ }
+
+ /** adds the given urls; filters out any nulls supplied */
+ public synchronized void addToClasspath(String ...urls) {
+ if (dto.classpath == null)
+ dto.classpath = new CatalogClasspathDto();
+ for (String url: urls) {
+ if (url!=null)
+ dto.classpath.addEntry(url);
+ }
+ if (isLoaded())
+ throw new IllegalStateException("dynamic classpath entry value update not supported");
+ // easy enough to add, just support unload+reload (and can also allow dynamic setScan below)
+ // but more predictable if we don't; the one exception is in the manualAdditionsCatalog
+ // where BasicBrooklynCatalog reaches in and updates the DTO and/or CompositeClassLoader directly, if necessary
+// for (String url: urls)
+// loadedClasspath.addEntry(url);
+ }
+
+ public synchronized void setClasspathScanForEntities(CatalogScanningModes value) {
+ if (dto.classpath == null)
+ dto.classpath = new CatalogClasspathDto();
+ dto.classpath.scan = value;
+ if (isLoaded())
+ throw new IllegalStateException("dynamic classpath scan value update not supported");
+ // easy enough to add, see above
+ }
+
+ @Override
+ public String toString() {
+ String size = cacheById == null ? "not yet loaded" : "size " + cacheById.size();
+ return "Loaded:" + dto + "(" + size + ")";
+ }
+
+ /** is "local" if it and all ancestors are not based on any remote urls */
+ public boolean isLocal() {
+ if (dto.url != null) {
+ String proto = Urls.getProtocol(dto.url);
+ if (proto != null) {
+ // 'file' is the only protocol accepted as "local"
+ if (!"file".equals(proto)) return false;
+ }
+ }
+ return parent == null || parent.isLocal();
+ }
+
+ /** classloader for only the entries in this catalog's classpath */
+ public ClassLoader getLocalClassLoader() {
+ if (classpath != null) return classpath.getLocalClassLoader();
+ return null;
+ }
+
+ /** recursive classloader is the local classloader plus all children catalog's classloader */
+ public ClassLoader getRecursiveClassLoader() {
+ if (recursiveClassLoader == null) loadRecursiveClassLoader();
+ return recursiveClassLoader;
+ }
+
+ protected synchronized void loadRecursiveClassLoader() {
+ if (recursiveClassLoader!=null) return;
+ AggregateClassLoader cl = AggregateClassLoader.newInstanceWithNoLoaders();
+ cl.addFirst(childrenClassLoader);
+ ClassLoader local = getLocalClassLoader();
+ if (local != null) cl.addFirst(local);
+ if (parent == null) {
+ // we are root. include the mgmt base classloader and/or standard class loaders
+ ClassLoader base = mgmt != null ? ((ManagementContextInternal)mgmt).getBaseClassLoader() : null;
+ if (base != null) cl.addFirst(base);
+ else {
+ cl.addFirst(getClass().getClassLoader());
+ cl.addFirst(Object.class.getClassLoader());
+ }
+ }
+ recursiveClassLoader = cl;
+ }
+
+ /** the root classloader is the recursive CL from the outermost catalog
+ * (which includes the base classloader from the mgmt context, if set) */
+ public ClassLoader getRootClassLoader() {
+ if (parent != null) return parent.getRootClassLoader();
+ return getRecursiveClassLoader();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java
new file mode 100644
index 0000000..847f114
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDto.java
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.PropagatedRuntimeException;
+import brooklyn.util.stream.Streams;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
+@Beta
+public class CatalogDto {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CatalogDto.class);
+
+ String id;
+ String url;
+ String contents;
+ String contentsDescription;
+ String name;
+ String description;
+ CatalogClasspathDto classpath;
+ private List<CatalogItemDtoAbstract<?,?>> entries = null;
+
+ // for thread-safety, any dynamic additions to this should be handled by a method
+ // in this class which does copy-on-write
+ List<CatalogDto> catalogs = null;
+
+ public static CatalogDto newDefaultLocalScanningDto(CatalogClasspathDo.CatalogScanningModes scanMode) {
+ CatalogDo result = new CatalogDo(
+ newNamedInstance("Local Scanned Catalog", "All annotated Brooklyn entities detected in the default classpath", "scanning-local-classpath") );
+ result.setClasspathScanForEntities(scanMode);
+ return result.dto;
+ }
+
+ /** @deprecated since 0.7.0 use {@link #newDtoFromXmlUrl(String)} if you must, but note the xml format itself is deprecated */
+ @Deprecated
+ public static CatalogDto newDtoFromUrl(String url) {
+ return newDtoFromXmlUrl(url);
+ }
+
+ /** @deprecated since 0.7.0 the xml format is deprecated; use YAML parse routines on BasicBrooklynCatalog */
+ @Deprecated
+ public static CatalogDto newDtoFromXmlUrl(String url) {
+ if (LOG.isDebugEnabled()) LOG.debug("Retrieving catalog from: {}", url);
+ try {
+ InputStream source = ResourceUtils.create().getResourceFromUrl(url);
+ String contents = Streams.readFullyString(source);
+ return newDtoFromXmlContents(contents, url);
+ } catch (Throwable t) {
+ Exceptions.propagateIfFatal(t);
+ throw new PropagatedRuntimeException("Unable to retrieve catalog from " + url + ": " + t, t);
+ }
+ }
+
+ /** @deprecated since 0.7.0 the xml format is deprecated; use YAML parse routines on BasicBrooklynCatalog */
+ @Deprecated
+ public static CatalogDto newDtoFromXmlContents(String xmlContents, String originDescription) {
+ CatalogDto result = (CatalogDto) new CatalogXmlSerializer().deserialize(new StringReader(xmlContents));
+ result.contentsDescription = originDescription;
+
+ if (LOG.isDebugEnabled()) LOG.debug("Retrieved catalog from: {}", originDescription);
+ return result;
+ }
+
+ /**
+ * Creates a DTO.
+ * <p>
+ * The way contents is treated may change; thus this (and much of catalog) should be treated as beta.
+ *
+ * @param name
+ * @param description
+ * @param optionalContentsDescription optional description of contents; if null, we normally expect source 'contents' to be set later;
+ * if the DTO has no 'contents' (ie XML source) then a description should be supplied so we know who is populating it
+ * (e.g. manual additions); without this, warnings may be generated
+ *
+ * @return a new Catalog DTO
+ */
+ public static CatalogDto newNamedInstance(String name, String description, String optionalContentsDescription) {
+ CatalogDto result = new CatalogDto();
+ result.name = name;
+ result.description = description;
+ if (optionalContentsDescription!=null) result.contentsDescription = optionalContentsDescription;
+ return result;
+ }
+
+ /** Used when caller wishes to create an explicitly empty catalog */
+ public static CatalogDto newEmptyInstance(String optionalContentsDescription) {
+ CatalogDto result = new CatalogDto();
+ if (optionalContentsDescription!=null) result.contentsDescription = optionalContentsDescription;
+ return result;
+ }
+
+ public static CatalogDto newLinkedInstance(String url) {
+ CatalogDto result = new CatalogDto();
+ result.contentsDescription = url;
+ result.contents = ResourceUtils.create().getResourceAsString(url);
+ return result;
+ }
+
+ /** @deprecated since 0.7.0 use {@link #newDtoFromCatalogItems(Collection, String)}, supplying a description for tracking */
+ @Deprecated
+ public static CatalogDto newDtoFromCatalogItems(Collection<CatalogItem<?, ?>> entries) {
+ return newDtoFromCatalogItems(entries, null);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static CatalogDto newDtoFromCatalogItems(Collection<CatalogItem<?, ?>> entries, String description) {
+ CatalogDto result = new CatalogDto();
+ result.contentsDescription = description;
+ // Weird casts because compiler does not seem to like
+ // .copyInto(Lists.<CatalogItemDtoAbstract<?, ?>>newArrayListWithExpectedSize(entries.size()));
+ result.entries = (List<CatalogItemDtoAbstract<?, ?>>) (List) FluentIterable.from(entries)
+ .filter(CatalogItemDtoAbstract.class)
+ .copyInto(Lists.newArrayListWithExpectedSize(entries.size()));
+ return result;
+ }
+
+ void populate() {
+ if (contents==null) {
+ if (url != null) {
+ contents = ResourceUtils.create().getResourceAsString(url);
+ contentsDescription = url;
+ } else if (contentsDescription==null) {
+ LOG.debug("Catalog DTO has no contents and no description; ignoring call to populate it. Description should be set to suppress this message.");
+ return;
+ } else {
+ LOG.trace("Nothing needs doing (no contents or URL) for catalog with contents described as "+contentsDescription+".");
+ return;
+ }
+ }
+
+ CatalogDto remoteDto = newDtoFromXmlContents(contents, contentsDescription);
+ try {
+ copyFrom(remoteDto, true);
+ } catch (Exception e) {
+ Exceptions.propagate(e);
+ }
+ }
+
+ /**
+ * @throws NullPointerException If source is null (and !skipNulls)
+ */
+ void copyFrom(CatalogDto source, boolean skipNulls) throws IllegalAccessException {
+ if (source==null) {
+ if (skipNulls) return;
+ throw new NullPointerException("source DTO is null, when copying to "+this);
+ }
+
+ if (!skipNulls || source.id != null) id = source.id;
+ if (!skipNulls || source.contentsDescription != null) contentsDescription = source.contentsDescription;
+ if (!skipNulls || source.contents != null) contents = source.contents;
+ if (!skipNulls || source.name != null) name = source.name;
+ if (!skipNulls || source.description != null) description = source.description;
+ if (!skipNulls || source.classpath != null) classpath = source.classpath;
+ if (!skipNulls || source.entries != null) entries = source.entries;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .omitNullValues()
+ .add("name", name)
+ .add("id", id)
+ .add("contentsDescription", contentsDescription)
+ .toString();
+ }
+
+ // temporary fix for issue where entries might not be unique
+ Iterable<CatalogItemDtoAbstract<?, ?>> getUniqueEntries() {
+ if (entries==null) return null;
+ Map<String, CatalogItemDtoAbstract<?, ?>> result = getEntriesMap();
+ return result.values();
+ }
+
+ private Map<String, CatalogItemDtoAbstract<?, ?>> getEntriesMap() {
+ if (entries==null) return null;
+ Map<String,CatalogItemDtoAbstract<?, ?>> result = MutableMap.of();
+ for (CatalogItemDtoAbstract<?,?> entry: entries) {
+ result.put(entry.getId(), entry);
+ }
+ return result;
+ }
+
+ void removeEntry(CatalogItemDtoAbstract<?, ?> entry) {
+ if (entries!=null)
+ entries.remove(entry);
+ }
+
+ void addEntry(CatalogItemDtoAbstract<?, ?> entry) {
+ if (entries == null) entries = MutableList.of();
+ CatalogItemDtoAbstract<?, ?> oldEntry = getEntriesMap().get(entry.getId());
+ entries.add(entry);
+ if (oldEntry!=null)
+ removeEntry(oldEntry);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java
new file mode 100644
index 0000000..e2df123
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogDtoUtils.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.exceptions.Exceptions;
+
+public class CatalogDtoUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(CatalogDtoUtils.class);
+
+ public static CatalogDto newDefaultLocalScanningDto(CatalogScanningModes scanMode) {
+ return CatalogDto.newDefaultLocalScanningDto(scanMode);
+ }
+
+ /** throws if there are any problems in retrieving or copying */
+ public static void populateFromUrl(CatalogDto dto, String url) {
+ CatalogDto remoteDto = newDtoFromUrl(url);
+ try {
+ copyDto(remoteDto, dto, true);
+ } catch (Exception e) {
+ Exceptions.propagate(e);
+ }
+ }
+
+ /** does a shallow copy.
+ * "skipNulls" means not to copy any fields from the source which are null */
+ static void copyDto(CatalogDto source, CatalogDto target, boolean skipNulls) throws IllegalArgumentException, IllegalAccessException {
+ target.copyFrom(source, skipNulls);
+ }
+
+ public static CatalogDto newDtoFromUrl(String url) {
+ if (log.isDebugEnabled()) log.debug("Retrieving catalog from: {}", url);
+ try {
+ InputStream source = ResourceUtils.create().getResourceFromUrl(url);
+ CatalogDto result = (CatalogDto) new CatalogXmlSerializer().deserialize(new InputStreamReader(source));
+ if (log.isDebugEnabled()) log.debug("Retrieved catalog from: {}", url);
+ return result;
+ } catch (Throwable t) {
+ log.debug("Unable to retrieve catalog from: "+url+" ("+t+")");
+ throw Exceptions.propagate(t);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogEntityItemDto.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogEntityItemDto.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogEntityItemDto.java
new file mode 100644
index 0000000..ec7cd90
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogEntityItemDto.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+
+
+public class CatalogEntityItemDto extends CatalogItemDtoAbstract<Entity,EntitySpec<?>> {
+
+ @Override
+ public CatalogItemType getCatalogItemType() {
+ return CatalogItemType.ENTITY;
+ }
+
+ @Override
+ public Class<Entity> getCatalogItemJavaType() {
+ return Entity.class;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Class<EntitySpec<?>> getSpecType() {
+ return (Class)EntitySpec.class;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
new file mode 100644
index 0000000..047a168
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
@@ -0,0 +1,449 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.FatalRuntimeException;
+import brooklyn.util.exceptions.RuntimeInterruptedException;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Strings;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+@Beta
+public class CatalogInitialization implements ManagementContextInjectable {
+
+ /*
+
+ A1) if not persisting, go to B1
+ A2) if --catalog-reset, delete persisted catalog items
+ A3) if there is a persisted catalog (and it wasn't not deleted by A2), read it and go to C1
+ A4) go to B1
+
+ B1) look for --catalog-initial, if so read it, then go to C1
+ B2) look for BrooklynServerConfig.BROOKLYN_CATALOG_URL, if so, read it, supporting YAML or XML (warning if XML), then go to C1
+ B3) look for ~/.brooklyn/catalog.bom, if exists, read it then go to C1
+ B4) look for ~/.brooklyn/brooklyn.xml, if exists, warn, read it then go to C1
+ B5) read all classpath://brooklyn/default.catalog.bom items, if they exist (and for now they will)
+ B6) go to C1
+
+ C1) if --catalog-add, read and add those items
+
+ D1) if persisting, read the rest of the persisted items (entities etc)
+
+ */
+
+ private static final Logger log = LoggerFactory.getLogger(CatalogInitialization.class);
+
+ private String initialUri;
+ private boolean reset;
+ private String additionsUri;
+ private boolean force;
+
+ private boolean disallowLocal = false;
+ private List<Function<CatalogInitialization, Void>> callbacks = MutableList.of();
+ private boolean
+ /** has run an unofficial initialization (i.e. an early load, triggered by an early read of the catalog) */
+ hasRunUnofficialInitialization = false,
+ /** has run an official initialization, but it is not a permanent one (e.g. during a hot standby mode, or a run failed) */
+ hasRunTransientOfficialInitialization = false,
+ /** has run an official initialization which is permanent (node is master, and the new catalog is now set) */
+ hasRunFinalInitialization = false;
+ /** is running a populate method; used to prevent recursive loops */
+ private boolean isPopulating = false;
+
+ private ManagementContext managementContext;
+ private boolean isStartingUp = false;
+ private boolean failOnStartupErrors = false;
+
+ private Object populatingCatalogMutex = new Object();
+
+ public CatalogInitialization(String initialUri, boolean reset, String additionUri, boolean force) {
+ this.initialUri = initialUri;
+ this.reset = reset;
+ this.additionsUri = additionUri;
+ this.force = force;
+ }
+
+ public CatalogInitialization() {
+ this(null, false, null, false);
+ }
+
+ @Override
+ public void injectManagementContext(ManagementContext managementContext) {
+ Preconditions.checkNotNull(managementContext, "management context");
+ if (this.managementContext!=null && managementContext!=this.managementContext)
+ throw new IllegalStateException("Cannot switch management context, from "+this.managementContext+" to "+managementContext);
+ this.managementContext = managementContext;
+ }
+
+ /** Called by the framework to set true while starting up, and false afterwards,
+ * in order to assist in appropriate logging and error handling. */
+ public void setStartingUp(boolean isStartingUp) {
+ this.isStartingUp = isStartingUp;
+ }
+
+ public void setFailOnStartupErrors(boolean startupFailOnCatalogErrors) {
+ this.failOnStartupErrors = startupFailOnCatalogErrors;
+ }
+
+ public CatalogInitialization addPopulationCallback(Function<CatalogInitialization, Void> callback) {
+ callbacks.add(callback);
+ return this;
+ }
+
+ public ManagementContext getManagementContext() {
+ return Preconditions.checkNotNull(managementContext, "management context has not been injected into "+this);
+ }
+
+ public boolean isInitialResetRequested() {
+ return reset;
+ }
+
+ /** Returns true if the canonical initialization has completed,
+ * that is, an initialization which is done when a node is rebinded as master
+ * (or an initialization done by the startup routines when not running persistence);
+ * see also {@link #hasRunAnyInitialization()}. */
+ public boolean hasRunFinalInitialization() { return hasRunFinalInitialization; }
+ /** Returns true if an official initialization has run,
+ * even if it was a transient run, e.g. so that the launch sequence can tell whether rebind has triggered initialization */
+ public boolean hasRunOfficialInitialization() { return hasRunFinalInitialization || hasRunTransientOfficialInitialization; }
+ /** Returns true if the initializer has run at all,
+ * including transient initializations which might be needed before a canonical becoming-master rebind,
+ * for instance because the catalog is being accessed before loading rebind information
+ * (done by {@link #populateUnofficial(BasicBrooklynCatalog)}) */
+ public boolean hasRunAnyInitialization() { return hasRunFinalInitialization || hasRunTransientOfficialInitialization || hasRunUnofficialInitialization; }
+
+ /** makes or updates the mgmt catalog, based on the settings in this class
+ * @param nodeState the management node for which this is being read; if master, then we expect this run to be the last one,
+ * and so subsequent applications should ignore any initialization data (e.g. on a subsequent promotion to master,
+ * after a master -> standby -> master cycle)
+ * @param needsInitialItemsLoaded whether the catalog needs the initial items loaded
+ * @param needsAdditionalItemsLoaded whether the catalog needs the additions loaded
+ * @param optionalExcplicitItemsForResettingCatalog
+ * if supplied, the catalog is reset to contain only these items, before calling any other initialization
+ * for use primarily when rebinding
+ */
+ public void populateCatalog(ManagementNodeState nodeState, boolean needsInitialItemsLoaded, boolean needsAdditionsLoaded, Collection<CatalogItem<?, ?>> optionalExcplicitItemsForResettingCatalog) {
+ if (log.isDebugEnabled()) {
+ String message = "Populating catalog for "+nodeState+", needsInitial="+needsInitialItemsLoaded+", needsAdditional="+needsAdditionsLoaded+", explicitItems="+(optionalExcplicitItemsForResettingCatalog==null ? "null" : optionalExcplicitItemsForResettingCatalog.size())+"; from "+JavaClassNames.callerNiceClassAndMethod(1);
+ if (!ManagementNodeState.isHotProxy(nodeState)) {
+ log.debug(message);
+ } else {
+ // in hot modes, make this message trace so we don't get too much output then
+ log.trace(message);
+ }
+ }
+ synchronized (populatingCatalogMutex) {
+ try {
+ if (hasRunFinalInitialization() && (needsInitialItemsLoaded || needsAdditionsLoaded)) {
+ // if we have already run "final" then we should only ever be used to reset the catalog,
+ // not to initialize or add; e.g. we are being given a fixed list on a subsequent master rebind after the initial master rebind
+ log.warn("Catalog initialization called to populate initial, even though it has already run the final official initialization");
+ }
+ isPopulating = true;
+ BasicBrooklynCatalog catalog = (BasicBrooklynCatalog) managementContext.getCatalog();
+ if (!catalog.getCatalog().isLoaded()) {
+ catalog.load();
+ } else {
+ if (needsInitialItemsLoaded && hasRunAnyInitialization()) {
+ // an indication that something caused it to load early; not severe, but unusual
+ if (hasRunTransientOfficialInitialization) {
+ log.debug("Catalog initialization now populating, but has noted a previous official run which was not final (probalby loaded while in a standby mode, or a previous run failed); overwriting any items installed earlier");
+ } else {
+ log.warn("Catalog initialization now populating, but has noted a previous unofficial run (it may have been an early web request); overwriting any items installed earlier");
+ }
+ catalog.reset(ImmutableList.<CatalogItem<?,?>>of());
+ }
+ }
+
+ populateCatalogImpl(catalog, needsInitialItemsLoaded, needsAdditionsLoaded, optionalExcplicitItemsForResettingCatalog);
+ if (nodeState == ManagementNodeState.MASTER) {
+ // TODO ideally this would remain false until it has *persisted* the changed catalog;
+ // if there is a subsequent startup failure the forced additions will not be persisted,
+ // but nor will they be loaded on a subsequent run.
+ // callers will have to restart a brooklyn, or reach into this class to change this field,
+ // or (recommended) manually adjust the catalog.
+ // TODO also, if a node comes up in standby, the addition might not take effector for a while
+ //
+ // however since these options are mainly for use on the very first brooklyn run, it's not such a big deal;
+ // once up and running the typical way to add items is via the REST API
+ hasRunFinalInitialization = true;
+ }
+ } finally {
+ if (!hasRunFinalInitialization) {
+ hasRunTransientOfficialInitialization = true;
+ }
+ isPopulating = false;
+ }
+ }
+ }
+
+ private void populateCatalogImpl(BasicBrooklynCatalog catalog, boolean needsInitialItemsLoaded, boolean needsAdditionsLoaded, Collection<CatalogItem<?, ?>> optionalItemsForResettingCatalog) {
+ applyCatalogLoadMode();
+
+ if (optionalItemsForResettingCatalog!=null) {
+ catalog.reset(optionalItemsForResettingCatalog);
+ }
+
+ if (needsInitialItemsLoaded) {
+ populateInitial(catalog);
+ }
+
+ if (needsAdditionsLoaded) {
+ populateAdditions(catalog);
+ populateViaCallbacks(catalog);
+ }
+ }
+
+ private enum PopulateMode { YAML, XML, AUTODETECT }
+
+ protected void populateInitial(BasicBrooklynCatalog catalog) {
+ if (disallowLocal) {
+ if (!hasRunFinalInitialization()) {
+ log.debug("CLI initial catalog not being read when local catalog load mode is disallowed.");
+ }
+ return;
+ }
+
+// B1) look for --catalog-initial, if so read it, then go to C1
+// B2) look for BrooklynServerConfig.BROOKLYN_CATALOG_URL, if so, read it, supporting YAML or XML (warning if XML), then go to C1
+// B3) look for ~/.brooklyn/catalog.bom, if exists, read it then go to C1
+// B4) look for ~/.brooklyn/brooklyn.xml, if exists, warn, read it then go to C1
+// B5) read all classpath://brooklyn/default.catalog.bom items, if they exist (and for now they will)
+// B6) go to C1
+
+ if (initialUri!=null) {
+ populateInitialFromUri(catalog, initialUri, PopulateMode.AUTODETECT);
+ return;
+ }
+
+ String catalogUrl = managementContext.getConfig().getConfig(BrooklynServerConfig.BROOKLYN_CATALOG_URL);
+ if (Strings.isNonBlank(catalogUrl)) {
+ populateInitialFromUri(catalog, catalogUrl, PopulateMode.AUTODETECT);
+ return;
+ }
+
+ catalogUrl = Os.mergePaths(BrooklynServerConfig.getMgmtBaseDir( managementContext.getConfig() ), "catalog.bom");
+ if (new File(catalogUrl).exists()) {
+ populateInitialFromUri(catalog, new File(catalogUrl).toURI().toString(), PopulateMode.YAML);
+ return;
+ }
+
+ catalogUrl = Os.mergePaths(BrooklynServerConfig.getMgmtBaseDir( managementContext.getConfig() ), "catalog.xml");
+ if (new File(catalogUrl).exists()) {
+ populateInitialFromUri(catalog, new File(catalogUrl).toURI().toString(), PopulateMode.XML);
+ return;
+ }
+
+ // otherwise look for for classpath:/brooklyn/default.catalog.bom --
+ // there is one on the classpath which says to scan, and provides a few templates;
+ // if one is supplied by user in the conf/ dir that will override the item from the classpath
+ // (TBD - we might want to scan for all such bom's?)
+
+ catalogUrl = "classpath:/brooklyn/default.catalog.bom";
+ if (new ResourceUtils(this).doesUrlExist(catalogUrl)) {
+ populateInitialFromUri(catalog, catalogUrl, PopulateMode.YAML);
+ return;
+ }
+
+ log.info("No catalog found on classpath or specified; catalog will not be initialized.");
+ return;
+ }
+
+ private void populateInitialFromUri(BasicBrooklynCatalog catalog, String catalogUrl, PopulateMode mode) {
+ log.debug("Loading initial catalog from {}", catalogUrl);
+
+ Exception problem = null;
+ Object result = null;
+
+ String contents = null;
+ try {
+ contents = new ResourceUtils(this).getResourceAsString(catalogUrl);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ if (problem==null) problem = e;
+ }
+
+ if (contents!=null && (mode==PopulateMode.YAML || mode==PopulateMode.AUTODETECT)) {
+ // try YAML first
+ try {
+ catalog.reset(MutableList.<CatalogItem<?,?>>of());
+ result = catalog.addItems(contents);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ if (problem==null) problem = e;
+ }
+ }
+
+ if (result==null && contents!=null && (mode==PopulateMode.XML || mode==PopulateMode.AUTODETECT)) {
+ // then try XML
+ try {
+ populateInitialFromUriXml(catalog, catalogUrl, contents);
+ // clear YAML problem
+ problem = null;
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ if (problem==null) problem = e;
+ }
+ }
+
+ if (result!=null) {
+ log.debug("Loaded initial catalog from {}: {}", catalogUrl, result);
+ }
+ if (problem!=null) {
+ log.warn("Error importing catalog from " + catalogUrl + ": " + problem, problem);
+ // TODO inform mgmt of error
+ }
+
+ }
+
+ // deprecated XML format
+ @SuppressWarnings("deprecation")
+ private void populateInitialFromUriXml(BasicBrooklynCatalog catalog, String catalogUrl, String contents) {
+ CatalogDto dto = CatalogDto.newDtoFromXmlContents(contents, catalogUrl);
+ if (dto!=null) {
+ catalog.reset(dto);
+ }
+ }
+
+ boolean hasRunAdditions = false;
+ protected void populateAdditions(BasicBrooklynCatalog catalog) {
+ if (Strings.isNonBlank(additionsUri)) {
+ if (disallowLocal) {
+ if (!hasRunAdditions) {
+ log.warn("CLI additions supplied but not supported when catalog load mode disallows local loads; ignoring.");
+ }
+ return;
+ }
+ if (!hasRunAdditions) {
+ log.debug("Adding to catalog from CLI: "+additionsUri+" (force: "+force+")");
+ }
+ Iterable<? extends CatalogItem<?, ?>> items = catalog.addItems(
+ new ResourceUtils(this).getResourceAsString(additionsUri), force);
+
+ if (!hasRunAdditions)
+ log.debug("Added to catalog from CLI: "+items);
+ else
+ log.debug("Added to catalog from CLI: count "+Iterables.size(items));
+
+ hasRunAdditions = true;
+ }
+ }
+
+ protected void populateViaCallbacks(BasicBrooklynCatalog catalog) {
+ for (Function<CatalogInitialization, Void> callback: callbacks)
+ callback.apply(this);
+ }
+
+ private Object setFromCLMMutex = new Object();
+ private boolean setFromCatalogLoadMode = false;
+
+ /** @deprecated since introduced in 0.7.0, only for legacy compatibility with
+ * {@link CatalogLoadMode} {@link BrooklynServerConfig#CATALOG_LOAD_MODE},
+ * allowing control of catalog loading from a brooklyn property */
+ @Deprecated
+ public void applyCatalogLoadMode() {
+ synchronized (setFromCLMMutex) {
+ if (setFromCatalogLoadMode) return;
+ setFromCatalogLoadMode = true;
+ Maybe<Object> clmm = ((ManagementContextInternal)managementContext).getConfig().getConfigRaw(BrooklynServerConfig.CATALOG_LOAD_MODE, false);
+ if (clmm.isAbsent()) return;
+ org.apache.brooklyn.core.catalog.CatalogLoadMode clm = TypeCoercions.coerce(clmm.get(), org.apache.brooklyn.core.catalog.CatalogLoadMode.class);
+ log.warn("Legacy CatalogLoadMode "+clm+" set: applying, but this should be changed to use new CLI --catalogXxx commands");
+ switch (clm) {
+ case LOAD_BROOKLYN_CATALOG_URL:
+ reset = true;
+ break;
+ case LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE:
+ // now the default
+ break;
+ case LOAD_PERSISTED_STATE:
+ disallowLocal = true;
+ break;
+ }
+ }
+ }
+
+ /** Creates the catalog based on parameters set here, if not yet loaded,
+ * but ignoring persisted state and warning if persistence is on and we are starting up
+ * (because the official persistence is preferred and the catalog will be subsequently replaced);
+ * for use when the catalog is accessed before persistence is completed.
+ * <p>
+ * This method is primarily used during testing, which in many cases does not enforce the full startup order
+ * and which wants a local catalog in any case. It may also be invoked if a client requests the catalog
+ * while the server is starting up. */
+ public void populateUnofficial(BasicBrooklynCatalog catalog) {
+ synchronized (populatingCatalogMutex) {
+ // check isPopulating in case this method gets called from inside another populate call
+ if (hasRunAnyInitialization() || isPopulating) return;
+ log.debug("Populating catalog unofficially ("+catalog+")");
+ isPopulating = true;
+ try {
+ if (isStartingUp) {
+ log.warn("Catalog access requested when not yet initialized; populating best effort rather than through recommended pathway. Catalog data may be replaced subsequently.");
+ }
+ populateCatalogImpl(catalog, true, true, null);
+ } finally {
+ hasRunUnofficialInitialization = true;
+ isPopulating = false;
+ }
+ }
+ }
+
+ public void handleException(Throwable throwable, Object details) {
+ if (throwable instanceof InterruptedException)
+ throw new RuntimeInterruptedException((InterruptedException) throwable);
+ if (throwable instanceof RuntimeInterruptedException)
+ throw (RuntimeInterruptedException) throwable;
+
+ log.error("Error loading catalog item '"+details+"': "+throwable);
+ log.debug("Trace for error loading catalog item '"+details+"': "+throwable, throwable);
+
+ // TODO give more detail when adding
+ ((ManagementContextInternal)getManagementContext()).errors().add(throwable);
+
+ if (isStartingUp && failOnStartupErrors) {
+ throw new FatalRuntimeException("Unable to load catalog item '"+details+"': "+throwable, throwable);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
new file mode 100644
index 0000000..e157a51
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemBuilder.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+
+import com.google.common.base.Preconditions;
+
+public class CatalogItemBuilder<CatalogItemType extends CatalogItemDtoAbstract<?, ?>> {
+ private CatalogItemType dto;
+
+ public static CatalogItemBuilder<CatalogEntityItemDto> newEntity(String symbolicName, String version) {
+ return new CatalogItemBuilder<CatalogEntityItemDto>(new CatalogEntityItemDto())
+ .symbolicName(symbolicName)
+ .version(version);
+ }
+
+ public static CatalogItemBuilder<CatalogTemplateItemDto> newTemplate(String symbolicName, String version) {
+ return new CatalogItemBuilder<CatalogTemplateItemDto>(new CatalogTemplateItemDto())
+ .symbolicName(symbolicName)
+ .version(version);
+ }
+
+ public static CatalogItemBuilder<CatalogPolicyItemDto> newPolicy(String symbolicName, String version) {
+ return new CatalogItemBuilder<CatalogPolicyItemDto>(new CatalogPolicyItemDto())
+ .symbolicName(symbolicName)
+ .version(version);
+ }
+
+ public static CatalogItemBuilder<CatalogLocationItemDto> newLocation(String symbolicName, String version) {
+ return new CatalogItemBuilder<CatalogLocationItemDto>(new CatalogLocationItemDto())
+ .symbolicName(symbolicName)
+ .version(version);
+ }
+
+ public CatalogItemBuilder(CatalogItemType dto) {
+ this.dto = dto;
+ this.dto.setLibraries(Collections.<CatalogBundle>emptyList());
+ }
+
+ public CatalogItemBuilder<CatalogItemType> symbolicName(String symbolicName) {
+ dto.setSymbolicName(symbolicName);
+ return this;
+ }
+
+ @Deprecated
+ public CatalogItemBuilder<CatalogItemType> javaType(String javaType) {
+ dto.setJavaType(javaType);
+ return this;
+ }
+
+ /** @deprecated since 0.7.0 use {@link #displayName}*/
+ @Deprecated
+ public CatalogItemBuilder<CatalogItemType> name(String name) {
+ return displayName(name);
+ }
+
+ public CatalogItemBuilder<CatalogItemType> displayName(String displayName) {
+ dto.setDisplayName(displayName);
+ return this;
+ }
+
+ public CatalogItemBuilder<CatalogItemType> description(String description) {
+ dto.setDescription(description);
+ return this;
+ }
+
+ public CatalogItemBuilder<CatalogItemType> iconUrl(String iconUrl) {
+ dto.setIconUrl(iconUrl);
+ return this;
+ }
+
+ public CatalogItemBuilder<CatalogItemType> version(String version) {
+ dto.setVersion(version);
+ return this;
+ }
+
+ public CatalogItemBuilder<CatalogItemType> deprecated(boolean deprecated) {
+ dto.setDeprecated(deprecated);
+ return this;
+ }
+
+ public CatalogItemBuilder<CatalogItemType> libraries(Collection<CatalogBundle> libraries) {
+ dto.setLibraries(libraries);
+ return this;
+ }
+
+ public CatalogItemBuilder<CatalogItemType> plan(String yaml) {
+ dto.setPlanYaml(yaml);
+ return this;
+ }
+
+ public CatalogItemType build() {
+ Preconditions.checkNotNull(dto.getSymbolicName());
+ Preconditions.checkNotNull(dto.getVersion());
+
+ if (dto.getLibraries() == null) {
+ dto.setLibraries(Collections.<CatalogBundle>emptyList());
+ }
+
+ CatalogItemType ret = dto;
+
+ //prevent mutations through the builder
+ dto = null;
+
+ return ret;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6caee589/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemComparator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemComparator.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemComparator.java
new file mode 100644
index 0000000..6832503
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemComparator.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.catalog.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+
+import brooklyn.util.text.NaturalOrderComparator;
+
+/**
+ * Largest version first order.
+ *
+ * When using the comparator to sort - first using symbolicName
+ * and if equal puts larger versions first, snapshots at the back.
+ */
+public class CatalogItemComparator<T,SpecT> implements Comparator<CatalogItem<T, SpecT>> {
+ private static final String SNAPSHOT = "SNAPSHOT";
+
+ public static final CatalogItemComparator<?, ?> INSTANCE = new CatalogItemComparator<Object, Object>();
+
+ @SuppressWarnings("unchecked")
+ public static <T,SpecT> CatalogItemComparator<T,SpecT> getInstance() {
+ return (CatalogItemComparator<T, SpecT>) INSTANCE;
+ }
+
+ @Override
+ public int compare(CatalogItem<T, SpecT> o1, CatalogItem<T, SpecT> o2) {
+ int symbolicNameComparison = o1.getSymbolicName().compareTo(o2.getSymbolicName());
+ if (symbolicNameComparison != 0) {
+ return symbolicNameComparison;
+ } else {
+ String v1 = o1.getVersion();
+ String v2 = o2.getVersion();
+
+ boolean isV1Snapshot = v1.toUpperCase().contains(SNAPSHOT);
+ boolean isV2Snapshot = v2.toUpperCase().contains(SNAPSHOT);
+ if (isV1Snapshot == isV2Snapshot) {
+ String[] v1Parts = split(v1);
+ String[] v2Parts = split(v2);
+ return -compare(v1Parts, v2Parts);
+ } else if (isV1Snapshot) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ private String[] split(String v) {
+ Collection<String> parts = new ArrayList<String>();
+ int startPos = 0;
+ int delimPos;
+ while ((delimPos = v.indexOf('.', startPos)) != -1) {
+ String part = v.substring(startPos, delimPos);
+ if (parse(part) != -1) {
+ parts.add(part);
+ } else {
+ break;
+ }
+ startPos = delimPos+1;
+ }
+ String remaining = v.substring(startPos);
+ parts.addAll(Arrays.asList(remaining.split("[^\\d]", 2)));
+ return parts.toArray(new String[parts.size()]);
+ }
+
+ private int compare(String[] v1Parts, String[] v2Parts) {
+ int len = Math.max(v1Parts.length, v2Parts.length);
+ for (int i = 0; i < len; i++) {
+ if (i == v1Parts.length) {
+ return isNumber(v2Parts[i]) ? -1 : 1;
+ }
+ if (i == v2Parts.length) {
+ return isNumber(v1Parts[i]) ? 1 : -1;
+ }
+
+ String p1 = v1Parts[i];
+ String p2 = v2Parts[i];
+ int n1 = parse(p1);
+ int n2 = parse(p2);
+ if (n1 != -1 && n2 != -1) {
+ if (n1 != n2) {
+ return compare(n1, n2);
+ }
+ } else if (n1 == -1 && n2 != -1) {
+ return -1;
+ } else if (n1 != -1 && n2 == -1) {
+ return 1;
+ } else {
+ int cmp = NaturalOrderComparator.INSTANCE.compare(p1, p2);
+ if (cmp < 0) {
+ return -1;
+ } else if (cmp > 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+ }
+
+ private boolean isNumber(String v) {
+ return parse(v) != -1;
+ }
+
+ //Replace with Integer.compare in J7
+ private int compare(int n1, int n2) {
+ if (n1 == n2) {
+ return 0;
+ } else if (n1 < n2) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ private int parse(String p) {
+ try {
+ return Integer.parseInt(p);
+ } catch (NumberFormatException e) {
+ return -1;
+ }
+ }
+}
[10/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java
new file mode 100644
index 0000000..9d98792
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentManagementContext.java
@@ -0,0 +1,639 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.api.basic.BrooklynObject;
+import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.drivers.EntityDriverManager;
+import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager;
+import org.apache.brooklyn.api.entity.rebind.ChangeListener;
+import org.apache.brooklyn.api.entity.rebind.PersistenceExceptionHandler;
+import org.apache.brooklyn.api.entity.rebind.RebindExceptionHandler;
+import org.apache.brooklyn.api.entity.rebind.RebindManager;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationRegistry;
+import org.apache.brooklyn.api.management.AccessController;
+import org.apache.brooklyn.api.management.EntityManager;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.api.management.LocationManager;
+import org.apache.brooklyn.api.management.SubscriptionContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityManager;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
+import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.ha.OsgiManager;
+
+import brooklyn.catalog.internal.CatalogInitialization;
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.StringConfigMap;
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.proxying.InternalEntityFactory;
+import brooklyn.entity.proxying.InternalLocationFactory;
+import brooklyn.entity.proxying.InternalPolicyFactory;
+import brooklyn.internal.storage.BrooklynStorage;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Objects;
+
+public class NonDeploymentManagementContext implements ManagementContextInternal {
+
+ private static final Logger log = LoggerFactory.getLogger(NonDeploymentManagementContext.class);
+
+ public enum NonDeploymentManagementContextMode {
+ PRE_MANAGEMENT,
+ MANAGEMENT_REBINDING,
+ MANAGEMENT_STARTING,
+ MANAGEMENT_STARTED,
+ MANAGEMENT_STOPPING,
+ MANAGEMENT_STOPPED;
+
+ public boolean isPreManaged() {
+ return this == PRE_MANAGEMENT || this == MANAGEMENT_REBINDING;
+ }
+ }
+
+ private final AbstractEntity entity;
+ private NonDeploymentManagementContextMode mode;
+ private ManagementContextInternal initialManagementContext;
+
+ private final QueueingSubscriptionManager qsm;
+ private final BasicSubscriptionContext subscriptionContext;
+ private NonDeploymentEntityManager entityManager;
+ private NonDeploymentLocationManager locationManager;
+ private NonDeploymentAccessManager accessManager;
+ private NonDeploymentUsageManager usageManager;
+ private EntitlementManager entitlementManager;;
+
+ public NonDeploymentManagementContext(AbstractEntity entity, NonDeploymentManagementContextMode mode) {
+ this.entity = checkNotNull(entity, "entity");
+ this.mode = checkNotNull(mode, "mode");
+ qsm = new QueueingSubscriptionManager();
+ subscriptionContext = new BasicSubscriptionContext(qsm, entity);
+ entityManager = new NonDeploymentEntityManager(null);
+ locationManager = new NonDeploymentLocationManager(null);
+ accessManager = new NonDeploymentAccessManager(null);
+ usageManager = new NonDeploymentUsageManager(null);
+
+ // TODO might need to be some kind of "system" which can see that the system is running at this point
+ // though quite possibly we are entirely behind the auth-wall at this point
+ entitlementManager = Entitlements.minimal();
+ }
+
+ @Override
+ public String getManagementPlaneId() {
+ return (initialManagementContext == null) ? null : initialManagementContext.getManagementPlaneId();
+ }
+
+ @Override
+ public String getManagementNodeId() {
+ return (initialManagementContext == null) ? null : initialManagementContext.getManagementNodeId();
+ }
+
+ @Override
+ public Maybe<URI> getManagementNodeUri() {
+ return (initialManagementContext == null) ? Maybe.<URI>absent() : initialManagementContext.getManagementNodeUri();
+ }
+
+ public void setManagementContext(ManagementContextInternal val) {
+ this.initialManagementContext = checkNotNull(val, "initialManagementContext");
+ this.entityManager = new NonDeploymentEntityManager(val);
+ this.locationManager = new NonDeploymentLocationManager(val);
+ this.accessManager = new NonDeploymentAccessManager(val);
+ this.usageManager = new NonDeploymentUsageManager(val);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).add("entity", entity.getId()).add("mode", mode).toString();
+ }
+
+ public void setMode(NonDeploymentManagementContextMode mode) {
+ this.mode = checkNotNull(mode, "mode");
+ }
+ public NonDeploymentManagementContextMode getMode() {
+ return mode;
+ }
+
+ @Override
+ public Collection<Application> getApplications() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isRunning() {
+ // Assume that the real management context has not been terminated, so always true
+ return true;
+ }
+
+ @Override
+ public boolean isStartupComplete() {
+ // This mgmt context is only used by items who are not yet fully started.
+ // It's slightly misleading as this does not refer to the main mgmt context.
+ // OTOH it probably won't be used. TBC. -Alex, Apr 2015
+ return false;
+ }
+
+ @Override
+ public InternalEntityFactory getEntityFactory() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getEntityFactory();
+ }
+
+ @Override
+ public InternalLocationFactory getLocationFactory() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getLocationFactory();
+ }
+
+ @Override
+ public InternalPolicyFactory getPolicyFactory() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getPolicyFactory();
+ }
+
+ @Override
+ public EntityManager getEntityManager() {
+ return entityManager;
+ }
+
+ @Override
+ public LocationManager getLocationManager() {
+ return locationManager;
+ }
+
+ @Override
+ public AccessManager getAccessManager() {
+ return accessManager;
+ }
+
+ @Override
+ public UsageManager getUsageManager() {
+ return usageManager;
+ }
+
+ @Override
+ public Maybe<OsgiManager> getOsgiManager() {
+ return Maybe.absent();
+ }
+
+ @Override
+ public AccessController getAccessController() {
+ return getAccessManager().getAccessController();
+ }
+
+ @Override
+ public ExecutionManager getExecutionManager() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getExecutionManager();
+ }
+
+ @Override
+ public QueueingSubscriptionManager getSubscriptionManager() {
+ return qsm;
+ }
+
+ @Override
+ public synchronized SubscriptionContext getSubscriptionContext(Entity entity) {
+ if (!this.entity.equals(entity)) throw new IllegalStateException("Non-deployment context "+this+" can only use a single Entity: has "+this.entity+", but passed "+entity);
+ if (mode==NonDeploymentManagementContextMode.MANAGEMENT_STOPPED)
+ throw new IllegalStateException("Entity "+entity+" is no longer managed; subscription context not available");
+ return subscriptionContext;
+ }
+
+ @Override
+ public ExecutionContext getExecutionContext(Entity entity) {
+ if (!this.entity.equals(entity)) throw new IllegalStateException("Non-deployment context "+this+" can only use a single Entity: has "+this.entity+", but passed "+entity);
+ if (mode==NonDeploymentManagementContextMode.MANAGEMENT_STOPPED)
+ throw new IllegalStateException("Entity "+entity+" is no longer managed; execution context not available");
+ checkInitialManagementContextReal();
+ return initialManagementContext.getExecutionContext(entity);
+ }
+
+ @Override
+ public ExecutionContext getServerExecutionContext() {
+ return initialManagementContext.getServerExecutionContext();
+ }
+
+ // TODO the methods below should delegate to the application?
+ @Override
+ public EntityDriverManager getEntityDriverManager() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getEntityDriverManager();
+ }
+
+ @Override
+ public DownloadResolverManager getEntityDownloadsManager() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getEntityDownloadsManager();
+ }
+
+ @Override
+ public StringConfigMap getConfig() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getConfig();
+ }
+
+ @Override
+ public BrooklynProperties getBrooklynProperties() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getBrooklynProperties();
+ }
+
+ @Override
+ public BrooklynStorage getStorage() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getStorage();
+ }
+
+ @Override
+ public RebindManager getRebindManager() {
+ // There was a race where EffectorUtils on invoking an effector calls:
+ // mgmtSupport.getEntityChangeListener().onEffectorCompleted(eff);
+ // but where the entity/app may be being unmanaged concurrently (e.g. calling app.stop()).
+ // So now we allow the change-listener to be called.
+
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getRebindManager();
+ } else {
+ return new NonDeploymentRebindManager();
+ }
+ }
+
+ @Override
+ public HighAvailabilityManager getHighAvailabilityManager() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getHighAvailabilityManager();
+ } else {
+ return new NonDeploymentHighAvailabilityManager();
+ }
+ }
+
+ @Override
+ public LocationRegistry getLocationRegistry() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getLocationRegistry();
+ }
+
+ @Override
+ public BrooklynCatalog getCatalog() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getCatalog();
+ }
+
+ @Override
+ public ClassLoader getCatalogClassLoader() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getCatalogClassLoader();
+ }
+
+ @Override
+ public EntitlementManager getEntitlementManager() {
+ return entitlementManager;
+ }
+
+ @Override
+ public <T> T invokeEffectorMethodSync(final Entity entity, final Effector<T> eff, final Object args) throws ExecutionException {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot invoke effector "+eff+" on entity "+entity);
+ }
+
+ @Override
+ public <T> Task<T> invokeEffector(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters) {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot invoke effector "+eff+" on entity "+entity);
+ }
+
+ @Override
+ public ClassLoader getBaseClassLoader() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getBaseClassLoader();
+ }
+
+ @Override
+ public Iterable<URL> getBaseClassPathForScanning() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getBaseClassPathForScanning();
+ }
+
+ @Override
+ public void addEntitySetListener(CollectionChangeListener<Entity> listener) {
+ checkInitialManagementContextReal();
+ initialManagementContext.addEntitySetListener(listener);
+ }
+
+ @Override
+ public void removeEntitySetListener(CollectionChangeListener<Entity> listener) {
+ checkInitialManagementContextReal();
+ initialManagementContext.removeEntitySetListener(listener);
+ }
+
+ @Override
+ public void terminate() {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.terminate();
+ } else {
+ // no-op; the non-deployment management context has nothing needing terminated
+ }
+ }
+
+ @Override
+ public long getTotalEffectorInvocations() {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getTotalEffectorInvocations();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public void setBaseClassPathForScanning(Iterable<URL> urls) {
+ checkInitialManagementContextReal();
+ initialManagementContext.setBaseClassPathForScanning(urls);
+ }
+
+ @Override
+ public void setManagementNodeUri(URI uri) {
+ checkInitialManagementContextReal();
+ initialManagementContext.setManagementNodeUri(uri);
+ }
+
+ @Override
+ public void prePreManage(Entity entity) {
+ // should throw? but in 0.7.0-SNAPSHOT it was no-op
+ log.warn("Ignoring call to prePreManage("+entity+") on "+this);
+ }
+
+ @Override
+ public void prePreManage(Location location) {
+ // should throw? but in 0.7.0-SNAPSHOT it was no-op
+ log.warn("Ignoring call to prePreManage("+location+") on "+this);
+ }
+
+ private boolean isInitialManagementContextReal() {
+ return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
+ }
+
+ private void checkInitialManagementContextReal() {
+ if (!isInitialManagementContextReal()) {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation.");
+ }
+ }
+
+ @Override
+ public void reloadBrooklynProperties() {
+ checkInitialManagementContextReal();
+ initialManagementContext.reloadBrooklynProperties();
+ }
+
+ @Override
+ public void addPropertiesReloadListener(PropertiesReloadListener listener) {
+ checkInitialManagementContextReal();
+ initialManagementContext.addPropertiesReloadListener(listener);
+ }
+
+ @Override
+ public void removePropertiesReloadListener(PropertiesReloadListener listener) {
+ checkInitialManagementContextReal();
+ initialManagementContext.removePropertiesReloadListener(listener);
+ }
+
+ @Override
+ public BrooklynObject lookup(String id) {
+ checkInitialManagementContextReal();
+ return initialManagementContext.lookup(id);
+ }
+
+ @Override
+ public <T extends BrooklynObject> T lookup(String id, Class<T> type) {
+ checkInitialManagementContextReal();
+ return initialManagementContext.lookup(id, type);
+ }
+
+ @Override
+ public List<Throwable> errors() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.errors();
+ }
+
+ @Override
+ public CatalogInitialization getCatalogInitialization() {
+ checkInitialManagementContextReal();
+ return initialManagementContext.getCatalogInitialization();
+ }
+
+ @Override
+ public void setCatalogInitialization(CatalogInitialization catalogInitialization) {
+ checkInitialManagementContextReal();
+ initialManagementContext.setCatalogInitialization(catalogInitialization);
+ }
+
+ /**
+ * For when the initial management context is not "real"; the changeListener is a no-op, but everything else forbidden.
+ *
+ * @author aled
+ */
+ private class NonDeploymentRebindManager implements RebindManager {
+
+ @Override
+ public ChangeListener getChangeListener() {
+ return ChangeListener.NOOP;
+ }
+
+ @Override
+ public void setPersister(BrooklynMementoPersister persister) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public void setPersister(BrooklynMementoPersister persister, PersistenceExceptionHandler exceptionHandler) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public BrooklynMementoPersister getPersister() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public List<Application> rebind() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public List<Application> rebind(ClassLoader classLoader) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public List<Application> rebind(ClassLoader classLoader, RebindExceptionHandler exceptionHandler) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public List<Application> rebind(ClassLoader classLoader, RebindExceptionHandler exceptionHandler, ManagementNodeState mode) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public void startPersistence() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public void stopPersistence() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public void startReadOnly(ManagementNodeState state) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public void stopReadOnly() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public void start() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public void stop() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public void waitForPendingComplete(Duration timeout, boolean canTrigger) throws InterruptedException, TimeoutException {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public void forcePersistNow() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public void forcePersistNow(boolean full, PersistenceExceptionHandler exceptionHandler) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public BrooklynMementoRawData retrieveMementoRawData() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public boolean isAwaitingInitialRebind() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+
+ @Override
+ public Map<String, Object> getMetrics() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ }
+
+ /**
+ * For when the initial management context is not "real".
+ *
+ * @author aled
+ */
+ private class NonDeploymentHighAvailabilityManager implements HighAvailabilityManager {
+ @Override
+ public ManagementNodeState getNodeState() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public boolean isRunning() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public HighAvailabilityManager setPersister(ManagementPlaneSyncRecordPersister persister) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public void disabled() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public void start(HighAvailabilityMode startMode) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public void stop() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public ManagementPlaneSyncRecordPersister getPersister() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public ManagementPlaneSyncRecord getLastManagementPlaneSyncRecord() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public ManagementPlaneSyncRecord loadManagementPlaneSyncRecord(boolean x) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public void changeMode(HighAvailabilityMode startMode) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public void setPriority(long priority) {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public long getPriority() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public Map<String, Object> getMetrics() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public void publishClearNonMaster() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ @Override
+ public long getLastStateChange() {
+ throw new IllegalStateException("Non-deployment context "+NonDeploymentManagementContext.this+" is not valid for this operation.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentUsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentUsageManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentUsageManager.java
new file mode 100644
index 0000000..55a4a78
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/NonDeploymentUsageManager.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage;
+import org.apache.brooklyn.core.management.usage.LocationUsage;
+
+import brooklyn.entity.basic.Lifecycle;
+
+import com.google.common.base.Predicate;
+
+
+public class NonDeploymentUsageManager implements UsageManager {
+
+ // TODO All the `isInitialManagementContextReal()` code-checks is a code-smell.
+ // Expect we can delete a lot of this once we guarantee that all entities are
+ // instantiated via EntitySpec / EntityManager. Until then, we'll live with this.
+
+ private final ManagementContextInternal initialManagementContext;
+
+ public NonDeploymentUsageManager(ManagementContextInternal initialManagementContext) {
+ this.initialManagementContext = initialManagementContext;
+ }
+
+ private boolean isInitialManagementContextReal() {
+ return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
+ }
+
+ @Override
+ public void recordApplicationEvent(Application app, Lifecycle state) {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.getUsageManager().recordApplicationEvent(app, state);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public void recordLocationEvent(Location loc, Lifecycle state) {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.getUsageManager().recordLocationEvent(loc, state);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public LocationUsage getLocationUsage(String locationId) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getUsageManager().getLocationUsage(locationId);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public Set<LocationUsage> getLocationUsage(Predicate<? super LocationUsage> filter) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getUsageManager().getLocationUsage(filter);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public ApplicationUsage getApplicationUsage(String appId) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getUsageManager().getApplicationUsage(appId);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public Set<ApplicationUsage> getApplicationUsage(Predicate<? super ApplicationUsage> filter) {
+ if (isInitialManagementContextReal()) {
+ return initialManagementContext.getUsageManager().getApplicationUsage(filter);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ @Deprecated
+ public void addUsageListener(org.apache.brooklyn.core.management.internal.UsageManager.UsageListener listener) {
+ addUsageListener(new org.apache.brooklyn.core.management.internal.UsageManager.UsageListener.UsageListenerAdapter(listener));
+ }
+
+ @Override
+ @Deprecated
+ public void removeUsageListener(org.apache.brooklyn.core.management.internal.UsageManager.UsageListener listener) {
+ removeUsageListener(new org.apache.brooklyn.core.management.internal.UsageManager.UsageListener.UsageListenerAdapter(listener));
+ }
+
+ @Override
+ public void addUsageListener(org.apache.brooklyn.core.management.internal.UsageListener listener) {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.getUsageManager().addUsageListener(listener);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+
+ @Override
+ public void removeUsageListener(org.apache.brooklyn.core.management.internal.UsageListener listener) {
+ if (isInitialManagementContextReal()) {
+ initialManagementContext.getUsageManager().removeUsageListener(listener);
+ } else {
+ throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/QueueingSubscriptionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/QueueingSubscriptionManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/QueueingSubscriptionManager.java
new file mode 100644
index 0000000..8f54d95
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/QueueingSubscriptionManager.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+
+import com.google.common.base.Objects;
+
+@SuppressWarnings("rawtypes")
+public class QueueingSubscriptionManager extends AbstractSubscriptionManager {
+
+ static class QueuedSubscription<T> {
+ Map<String, Object> flags;
+ Subscription<T> s;
+ }
+
+ public AbstractSubscriptionManager delegate = null;
+ public boolean useDelegateForSubscribing = false;
+ public boolean useDelegateForPublishing = false;
+
+ List<QueuedSubscription> queuedSubscriptions = new ArrayList<QueuedSubscription>();
+ List<SensorEvent> queuedSensorEvents = new ArrayList<SensorEvent>();
+
+ @Override
+ protected synchronized <T> SubscriptionHandle subscribe(Map<String, Object> flags, Subscription<T> s) {
+ if (useDelegateForSubscribing)
+ return delegate.subscribe(flags, s);
+
+ QueuedSubscription<T> qs = new QueuedSubscription<T>();
+ qs.flags = flags;
+ s.subscriber = getSubscriber(flags, s);
+ qs.s = s;
+ queuedSubscriptions.add(qs);
+ return s;
+ }
+
+ @Override
+ public synchronized <T> void publish(SensorEvent<T> event) {
+ if (useDelegateForPublishing) {
+ delegate.publish(event);
+ return;
+ }
+
+ queuedSensorEvents.add(event);
+ }
+
+ public void setDelegate(AbstractSubscriptionManager delegate) {
+ this.delegate = delegate;
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized void startDelegatingForSubscribing() {
+ assert delegate!=null;
+ for (QueuedSubscription s: queuedSubscriptions) {
+ delegate.subscribe(s.flags, s.s);
+ }
+ queuedSubscriptions.clear();
+ useDelegateForSubscribing = true;
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized void startDelegatingForPublishing() {
+ assert delegate!=null;
+ for (SensorEvent evt: queuedSensorEvents) {
+ delegate.publish(evt);
+ }
+ queuedSensorEvents.clear();
+ useDelegateForPublishing = true;
+ }
+
+ public synchronized void stopDelegatingForSubscribing() {
+ useDelegateForSubscribing = false;
+ }
+
+ public synchronized void stopDelegatingForPublishing() {
+ useDelegateForPublishing = false;
+ }
+
+ @Override
+ public synchronized boolean unsubscribe(SubscriptionHandle subscriptionId) {
+ if (useDelegateForSubscribing)
+ return delegate.unsubscribe(subscriptionId);
+
+ Iterator<QueuedSubscription> qi = queuedSubscriptions.iterator();
+ while (qi.hasNext()) {
+ QueuedSubscription q = qi.next();
+ if (Objects.equal(subscriptionId, q.s)) {
+ qi.remove();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public synchronized Set<SubscriptionHandle> getSubscriptionsForSubscriber(Object subscriber) {
+ if (useDelegateForSubscribing)
+ return delegate.getSubscriptionsForSubscriber(subscriber);
+
+ Set<SubscriptionHandle> result = new LinkedHashSet<SubscriptionHandle>();
+ for (QueuedSubscription q: queuedSubscriptions) {
+ if (Objects.equal(subscriber, getSubscriber(q.flags, q.s))) result.add(q.s);
+ }
+ return result;
+ }
+
+ @Override
+ public synchronized Set<SubscriptionHandle> getSubscriptionsForEntitySensor(Entity source, Sensor<?> sensor) {
+ if (useDelegateForSubscribing)
+ return delegate.getSubscriptionsForEntitySensor(source, sensor);
+
+ Set<SubscriptionHandle> result = new LinkedHashSet<SubscriptionHandle>();
+ for (QueuedSubscription q: queuedSubscriptions) {
+ if ((q.s.sensor==null || Objects.equal(q.s.sensor, sensor)) &&
+ (q.s.producer==null || Objects.equal(q.s.producer, sensor)))
+ result.add(q.s);
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/Subscription.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/Subscription.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/Subscription.java
new file mode 100644
index 0000000..acd30c3
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/Subscription.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+
+import brooklyn.util.text.Identifiers;
+
+import com.google.common.base.Predicate;
+
+class Subscription<T> implements SubscriptionHandle {
+ public final String id = Identifiers.makeRandomId(8);
+
+ public Object subscriber;
+ public Object subscriberExecutionManagerTag;
+ /** whether the tag was supplied by user, in which case we should not clear execution semantics */
+ public boolean subscriberExecutionManagerTagSupplied;
+ public final Entity producer;
+ public final Sensor<T> sensor;
+ public final SensorEventListener<? super T> listener;
+ public Map<String,Object> flags;
+ public Predicate<SensorEvent<T>> eventFilter;
+
+ public Subscription(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ this.producer = producer;
+ this.sensor = sensor;
+ this.listener = listener;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return (other instanceof Subscription && ((Subscription<?>)other).id==id);
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "Subscription["+id+";"+subscriber+"@"+LocalSubscriptionManager.makeEntitySensorToken(producer,sensor)+"]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/SubscriptionTracker.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/SubscriptionTracker.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/SubscriptionTracker.java
new file mode 100644
index 0000000..acc0cb6
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/SubscriptionTracker.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.Collection;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.api.management.SubscriptionContext;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.SetMultimap;
+
+/**
+ * Tracks subscriptions associated that are registered with particular entities. Gives utilities for unsubscribing from all
+ * subscriptions on a given entity, etc.
+ */
+public class SubscriptionTracker {
+
+ // This class is thread-safe. All modifications to subscriptions are synchronized on the
+ // "subscriptions" field. However, calls to alien code (i.e. context.subscribe etc) is
+ // done without holding the lock.
+ //
+ // If two threads do subscribe() and unsubscribeAll() concurrently, then it's non-derministic
+ // whether the subscription will be in place at the end (but that's unavoidable). However, it
+ // is guaranteed that the internal state of the SubscriptionTracker will be consistent: if
+ // the "subscriptions" includes the new subscription then that subscription will really exist,
+ // and vice versa.
+
+ protected SubscriptionContext context;
+
+ private final SetMultimap<Entity, SubscriptionHandle> subscriptions = HashMultimap.create();
+
+ public SubscriptionTracker(SubscriptionContext subscriptionContext) {
+ this.context = subscriptionContext;
+ }
+
+ /** @see SubscriptionContext#subscribe(Entity, Sensor, SensorEventListener) */
+ public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ SubscriptionHandle handle = context.subscribe(producer, sensor, listener);
+ synchronized (subscriptions) {
+ subscriptions.put(producer, handle);
+ }
+ return handle;
+ }
+
+ /** @see SubscriptionContext#subscribeToChildren(Entity, Sensor, SensorEventListener) */
+ public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ SubscriptionHandle handle = context.subscribeToChildren(parent, sensor, listener);
+ synchronized (subscriptions) {
+ subscriptions.put(parent, handle);
+ }
+ return handle;
+ }
+
+ /**
+ * @see SubscriptionContext#subscribeToMembers(Group, Sensor, SensorEventListener)
+ */
+ public <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ SubscriptionHandle handle = context.subscribeToMembers(parent, sensor, listener);
+ synchronized (subscriptions) {
+ subscriptions.put(parent, handle);
+ }
+ return handle;
+ }
+
+ /**
+ * Unsubscribes the given producer.
+ *
+ * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+ */
+ public boolean unsubscribe(Entity producer) {
+ Collection<SubscriptionHandle> handles;
+ synchronized (subscriptions) {
+ handles = subscriptions.removeAll(producer);
+ }
+ if (handles != null) {
+ for (SubscriptionHandle handle : handles) {
+ context.unsubscribe(handle);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Unsubscribes the given producer.
+ *
+ * @see SubscriptionContext#unsubscribe(SubscriptionHandle)
+ */
+ public boolean unsubscribe(Entity producer, SubscriptionHandle handle) {
+ synchronized (subscriptions) {
+ subscriptions.remove(producer, handle);
+ }
+ return context.unsubscribe(handle);
+ }
+
+ /**
+ * @return an ordered list of all subscription handles
+ */
+ public Collection<SubscriptionHandle> getAllSubscriptions() {
+ synchronized (subscriptions) {
+ return ImmutableList.copyOf(subscriptions.values());
+ }
+ }
+
+ public void unsubscribeAll() {
+ Collection<SubscriptionHandle> subscriptionsSnapshot;
+ synchronized (subscriptions) {
+ subscriptionsSnapshot = ImmutableList.copyOf(subscriptions.values());
+ subscriptions.clear();
+ }
+ for (SubscriptionHandle s: subscriptionsSnapshot) {
+ context.unsubscribe(s);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/UsageListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/UsageListener.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/UsageListener.java
new file mode 100644
index 0000000..566c0f0
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/UsageListener.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage.ApplicationEvent;
+import org.apache.brooklyn.core.management.usage.LocationUsage.LocationEvent;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public interface UsageListener {
+
+ /**
+ * A no-op implementation of {@link UsageListener}, for users to extend.
+ *
+ * Users are encouraged to extend this class, which will shield the user
+ * from the addition of other usage event methods being added. If additional
+ * methods are added in a future release, a no-op implementation will be
+ * added to this class.
+ */
+ @Beta
+ public static class BasicUsageListener implements UsageListener {
+ @Override
+ public void onApplicationEvent(ApplicationMetadata app, ApplicationEvent event) {
+ }
+
+ @Override public void onLocationEvent(LocationMetadata loc, LocationEvent event) {
+ }
+ }
+
+ /**
+ * Users should never implement this interface directly; methods may be added in future releases
+ * without notice.
+ */
+ @Beta
+ public interface ApplicationMetadata {
+ /**
+ * Access the application directly with caution: by the time the listener fires,
+ * the application may no longer be managed.
+ */
+ @Beta
+ Application getApplication();
+
+ String getApplicationId();
+
+ String getApplicationName();
+
+ String getEntityType();
+
+ String getCatalogItemId();
+
+ Map<String, String> getMetadata();
+ }
+
+ /**
+ * Users should never implement this interface directly; methods may be added in future releases
+ * without notice.
+ */
+ @Beta
+ public interface LocationMetadata {
+ /**
+ * Access the location directly with caution: by the time the listener fires,
+ * the location may no longer be managed.
+ */
+ @Beta
+ Location getLocation();
+
+ String getLocationId();
+
+ Map<String, String> getMetadata();
+ }
+
+ public static final UsageListener NOOP = new UsageListener() {
+ @Override public void onApplicationEvent(ApplicationMetadata app, ApplicationEvent event) {}
+ @Override public void onLocationEvent(LocationMetadata loc, LocationEvent event) {}
+ };
+
+ @Beta
+ void onApplicationEvent(ApplicationMetadata app, ApplicationEvent event);
+
+ @Beta
+ void onLocationEvent(LocationMetadata loc, LocationEvent event);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/UsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/UsageManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/UsageManager.java
new file mode 100644
index 0000000..75c242a
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/UsageManager.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage;
+import org.apache.brooklyn.core.management.usage.LocationUsage;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage.ApplicationEvent;
+import org.apache.brooklyn.core.management.usage.LocationUsage.LocationEvent;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.TypeToken;
+
+@Beta
+public interface UsageManager {
+
+ @SuppressWarnings("serial")
+ public static final ConfigKey<List<org.apache.brooklyn.core.management.internal.UsageListener>> USAGE_LISTENERS = ConfigKeys.newConfigKey(
+ new TypeToken<List<org.apache.brooklyn.core.management.internal.UsageListener>>() {},
+ "brooklyn.usageManager.listeners", "Optional usage listeners (i.e. for metering)",
+ ImmutableList.<org.apache.brooklyn.core.management.internal.UsageListener>of());
+
+ public static final ConfigKey<Duration> USAGE_LISTENER_TERMINATION_TIMEOUT = ConfigKeys.newConfigKey(
+ Duration.class,
+ "brooklyn.usageManager.listeners.timeout",
+ "Timeout on termination, to wait for queue of usage listener events to be processed",
+ Duration.TEN_SECONDS);
+
+ /**
+ * @since 0.7.0
+ * @deprecated since 0.7.0; use {@link org.apache.brooklyn.core.management.internal.UsageListener}; see {@link UsageListenerAdapter}
+ */
+ public interface UsageListener {
+ public static final UsageListener NOOP = new UsageListener() {
+ @Override public void onApplicationEvent(String applicationId, String applicationName, String entityType,
+ String catalogItemId, Map<String, String> metadata, ApplicationEvent event) {}
+ @Override public void onLocationEvent(String locationId, Map<String, String> metadata, LocationEvent event) {}
+ };
+
+ public static class UsageListenerAdapter implements org.apache.brooklyn.core.management.internal.UsageListener {
+ private final UsageListener listener;
+
+ public UsageListenerAdapter(UsageListener listener) {
+ this.listener = checkNotNull(listener, "listener");
+ }
+
+ @Override
+ public void onApplicationEvent(ApplicationMetadata app, ApplicationEvent event) {
+ listener.onApplicationEvent(app.getApplicationId(), app.getApplicationName(), app.getEntityType(), app.getCatalogItemId(), app.getMetadata(), event);
+ }
+
+ @Override
+ public void onLocationEvent(LocationMetadata loc, LocationEvent event) {
+ listener.onLocationEvent(loc.getLocationId(), loc.getMetadata(), event);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return (obj instanceof UsageListenerAdapter) && listener.equals(((UsageListenerAdapter)obj).listener);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(listener);
+ }
+ }
+
+ void onApplicationEvent(String applicationId, String applicationName, String entityType, String catalogItemId,
+ Map<String, String> metadata, ApplicationEvent event);
+
+ void onLocationEvent(String locationId, Map<String, String> metadata, LocationEvent event);
+ }
+
+ /**
+ * Adds this application event to the usage record for the given app (creating the usage
+ * record if one does not already exist).
+ */
+ void recordApplicationEvent(Application app, Lifecycle state);
+
+ /**
+ * Adds this location event to the usage record for the given location (creating the usage
+ * record if one does not already exist).
+ */
+ void recordLocationEvent(Location loc, Lifecycle state);
+
+ /**
+ * Returns the usage info for the location with the given id, or null if unknown.
+ */
+ LocationUsage getLocationUsage(String locationId);
+
+ /**
+ * Returns the usage info that matches the given predicate.
+ * For example, could be used to find locations used within a given time period.
+ */
+ Set<LocationUsage> getLocationUsage(Predicate<? super LocationUsage> filter);
+
+ /**
+ * Returns the usage info for the application with the given id, or null if unknown.
+ */
+ ApplicationUsage getApplicationUsage(String appId);
+
+ /**
+ * Returns the usage info that matches the given predicate.
+ * For example, could be used to find applications used within a given time period.
+ */
+ Set<ApplicationUsage> getApplicationUsage(Predicate<? super ApplicationUsage> filter);
+
+ /**
+ * @since 0.7.0
+ * @deprecated since 0.7.0; use {@link #removeUsageListener(org.apache.brooklyn.core.management.internal.UsageListener)};
+ * see {@link org.apache.brooklyn.core.management.internal.UsageManager.UsageListener.UsageListenerAdapter}
+ */
+ void addUsageListener(org.apache.brooklyn.core.management.internal.UsageManager.UsageListener listener);
+
+ /**
+ * @since 0.7.0
+ * @deprecated since 0.7.0; use {@link #removeUsageListener(org.apache.brooklyn.core.management.internal.UsageListener)}
+ */
+ @Deprecated
+ void removeUsageListener(org.apache.brooklyn.core.management.internal.UsageManager.UsageListener listener);
+
+ /**
+ * Adds the given listener, to be notified on recording of application/location events.
+ * The listener notifications may be asynchronous.
+ *
+ * As of 0.7.0, the listener is not persisted so will be lost on restart/rebind. This
+ * behaviour may change in a subsequent release.
+ */
+ void addUsageListener(org.apache.brooklyn.core.management.internal.UsageListener listener);
+
+ /**
+ * Removes the given listener.
+ */
+ void removeUsageListener(org.apache.brooklyn.core.management.internal.UsageListener listener);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/usage/ApplicationUsage.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/usage/ApplicationUsage.java b/core/src/main/java/org/apache/brooklyn/core/management/usage/ApplicationUsage.java
new file mode 100644
index 0000000..8260923
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/usage/ApplicationUsage.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.usage;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import brooklyn.entity.basic.Lifecycle;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ */
+public class ApplicationUsage {
+
+ public static class ApplicationEvent {
+ private final Date date;
+ private final Lifecycle state;
+ private final String user;
+
+ public ApplicationEvent(Lifecycle state, String user) {
+ this(new Date(), state, user);
+ }
+
+ public ApplicationEvent(Date date, Lifecycle state) {
+ this(date,state, null);
+ }
+
+ public ApplicationEvent(Date date, Lifecycle state, String user) {
+ this.date = checkNotNull(date, "date");
+ this.state = checkNotNull(state, "state");
+ this.user = user;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public Lifecycle getState() {
+ return state;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof ApplicationEvent)) return false;
+ ApplicationEvent o = (ApplicationEvent) other;
+ return Objects.equal(date, o.date) && Objects.equal(state, o.state) && Objects.equal(user, o.user);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(date, state, user);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).add("date", date).add("state", state).add("entitlementContext", user).toString();
+ }
+ }
+
+ private final String applicationId;
+ private final String applicationName;
+ private final String entityType;
+ private final Map<String, String> metadata;
+ private final List<ApplicationEvent> events = Collections.synchronizedList(Lists.<ApplicationEvent>newArrayList());
+
+ public ApplicationUsage(String applicationId, String applicationName, String entityType, Map<String, String> metadata) {
+ this.applicationId = checkNotNull(applicationId, "applicationId");
+ // allow name to be null, happens in certain failed rebind cases
+ this.applicationName = applicationName;
+ this.entityType = checkNotNull(entityType, "entityType");
+ this.metadata = checkNotNull(metadata, "metadata");
+ }
+
+ public String getApplicationId() {
+ return applicationId;
+ }
+
+ public String getApplicationName() {
+ return applicationName;
+ }
+
+ public String getEntityType() {
+ return entityType;
+ }
+
+ public Map<String, String> getMetadata() {
+ return metadata;
+ }
+
+ public List<ApplicationEvent> getEvents() {
+ synchronized (events) {
+ return ImmutableList.copyOf(events);
+ }
+ }
+
+ public void addEvent(ApplicationEvent event) {
+ events.add(checkNotNull(event, "event"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/usage/LocationUsage.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/usage/LocationUsage.java b/core/src/main/java/org/apache/brooklyn/core/management/usage/LocationUsage.java
new file mode 100644
index 0000000..32bd03b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/usage/LocationUsage.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.usage;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import brooklyn.entity.basic.Lifecycle;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+/**
+ */
+public class LocationUsage {
+
+ public static class LocationEvent {
+ private final Date date;
+ private final Lifecycle state;
+ private final String entityId;
+ private final String entityType;
+ private final String applicationId;
+ private final String user;
+
+ public LocationEvent(Lifecycle state, String entityId, String entityType, String applicationId, String user) {
+ this(new Date(), state, entityId, entityType, applicationId, user);
+ }
+
+ public LocationEvent(Date date, Lifecycle state, String entityId, String entityType, String applicationId, String user) {
+ this.date = checkNotNull(date, "date");
+ this.state = checkNotNull(state, "state");
+ this.entityId = checkNotNull(entityId, "entityId");
+ this.entityType = checkNotNull(entityType, "entityType");
+ this.applicationId = checkNotNull(applicationId, "applicationId (entity "+entityId+")");
+ this.user = user;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public Lifecycle getState() {
+ return state;
+ }
+
+ public String getEntityId() {
+ return entityId;
+ }
+
+ public String getEntityType() {
+ return entityType;
+ }
+
+ public String getApplicationId() {
+ return applicationId;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof LocationEvent)) return false;
+ LocationEvent o = (LocationEvent) other;
+ return Objects.equal(date, o.date) && Objects.equal(state, o.state)
+ && Objects.equal(entityId, o.entityId) && Objects.equal(entityType, o.entityType)
+ && Objects.equal(applicationId, o.applicationId) && Objects.equal(user, o.user);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(date, state, entityId, entityType, applicationId, user);
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("date", date)
+ .add("state", state)
+ .add("entityId", entityId)
+ .add("appId", applicationId)
+ .add("user", user)
+ .toString();
+ }
+ }
+
+ private final String locationId;
+ private final Map<String, String> metadata;
+ private final List<LocationEvent> events = Collections.synchronizedList(Lists.<LocationEvent>newArrayList());
+
+ public LocationUsage(String locationId, Map<String, String> metadata) {
+ this.locationId = checkNotNull(locationId, "locationId");
+ this.metadata = checkNotNull(metadata, "metadata");
+ }
+
+ public String getLocationId() {
+ return locationId;
+ }
+
+ public Map<String, String> getMetadata() {
+ return metadata;
+ }
+
+ public List<LocationEvent> getEvents() {
+ synchronized (events) {
+ return ImmutableList.copyOf(events);
+ }
+ }
+
+ public void addEvent(LocationEvent event) {
+ events.add(checkNotNull(event, "event"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
index 47dca3e..c5a74a0 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
@@ -35,6 +35,8 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.mementos.LocationMemento;
+import org.apache.brooklyn.core.management.internal.LocalLocationManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,8 +55,6 @@ import brooklyn.internal.storage.impl.BasicReference;
import org.apache.brooklyn.location.geo.HasHostGeoInfo;
import org.apache.brooklyn.location.geo.HostGeoInfo;
-import brooklyn.management.internal.LocalLocationManager;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.SetFromLiveMap;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.flags.FlagUtils;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java b/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
index 490335a..9a6466e 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/BasicLocationRegistry.java
@@ -40,12 +40,12 @@ import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationResolver;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalLocationManager;
import brooklyn.catalog.CatalogPredicates;
import brooklyn.config.ConfigMap;
import brooklyn.config.ConfigPredicates;
import brooklyn.config.ConfigUtils;
-import brooklyn.management.internal.LocalLocationManager;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java b/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java
index 127a665..70735e5 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/ByonLocationResolver.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.core.management.internal.LocalLocationManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +41,6 @@ import com.google.common.net.HostAndPort;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Sanitizer;
-import brooklyn.management.internal.LocalLocationManager;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.flags.TypeCoercions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/BrooklynVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/BrooklynVersionTest.java b/core/src/test/java/brooklyn/BrooklynVersionTest.java
index 7fbe976..179e698 100644
--- a/core/src/test/java/brooklyn/BrooklynVersionTest.java
+++ b/core/src/test/java/brooklyn/BrooklynVersionTest.java
@@ -37,8 +37,9 @@ import com.google.common.collect.Lists;
import brooklyn.catalog.internal.CatalogEntityItemDto;
import brooklyn.catalog.internal.CatalogItemBuilder;
import brooklyn.catalog.internal.CatalogItemDtoAbstract;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.osgi.OsgiTestResources;
+
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
import org.apache.brooklyn.test.TestResourceUnavailableException;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
index 0917b0e..73cf5ce 100644
--- a/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
+++ b/core/src/test/java/brooklyn/camp/lite/CampYamlLiteTest.java
@@ -49,6 +49,8 @@ import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
import brooklyn.catalog.CatalogPredicates;
import brooklyn.catalog.internal.BasicBrooklynCatalog;
@@ -59,8 +61,6 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.effector.AddChildrenEffector;
import brooklyn.entity.effector.Effectors;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.osgi.OsgiStandaloneTest;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.config.ConfigBag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
index 731a2d8..25a050e 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogDtoTest.java
@@ -28,13 +28,13 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.BrooklynMavenArtifacts;
import brooklyn.util.maven.MavenRetriever;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
index 8630430..c417421 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogScanTest.java
@@ -30,13 +30,13 @@ import org.apache.brooklyn.api.catalog.BrooklynCatalog;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import brooklyn.catalog.CatalogPredicates;
import brooklyn.catalog.internal.MyCatalogItems.MySillyAppTemplate;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.ResourceUtils;
import brooklyn.util.net.Urls;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java b/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java
index 53a0b9c..78c11ea 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogVersioningTest.java
@@ -28,11 +28,11 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.apache.brooklyn.api.catalog.BrooklynCatalog;
import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import brooklyn.catalog.CatalogPredicates;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/BrooklynAppLiveTestSupport.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/BrooklynAppLiveTestSupport.java b/core/src/test/java/brooklyn/entity/BrooklynAppLiveTestSupport.java
index 668a788..626a035 100644
--- a/core/src/test/java/brooklyn/entity/BrooklynAppLiveTestSupport.java
+++ b/core/src/test/java/brooklyn/entity/BrooklynAppLiveTestSupport.java
@@ -18,6 +18,7 @@
*/
package brooklyn.entity;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
@@ -28,7 +29,6 @@ import org.testng.annotations.BeforeMethod;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.ManagementContextInternal;
/**
* To be extended by live tests.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java b/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java
index 4e23de0..bb7beaf 100644
--- a/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java
+++ b/core/src/test/java/brooklyn/entity/BrooklynAppUnitTestSupport.java
@@ -19,6 +19,7 @@
package brooklyn.entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
@@ -29,7 +30,6 @@ import org.testng.annotations.BeforeMethod;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.BrooklynConfigKeys;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.ManagementContextInternal;
/**
* To be extended by unit/integration tests.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/EffectorMetadataTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/EffectorMetadataTest.java b/core/src/test/java/brooklyn/entity/EffectorMetadataTest.java
index 66daf0b..337cbfd 100644
--- a/core/src/test/java/brooklyn/entity/EffectorMetadataTest.java
+++ b/core/src/test/java/brooklyn/entity/EffectorMetadataTest.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.entity.ParameterType;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -39,7 +40,6 @@ import brooklyn.entity.basic.BasicParameterType;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.trait.Startable;
-import brooklyn.management.internal.EffectorUtils;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/EffectorSayHiGroovyTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/EffectorSayHiGroovyTest.groovy b/core/src/test/java/brooklyn/entity/EffectorSayHiGroovyTest.groovy
index 5ce49a2..57362f2 100644
--- a/core/src/test/java/brooklyn/entity/EffectorSayHiGroovyTest.groovy
+++ b/core/src/test/java/brooklyn/entity/EffectorSayHiGroovyTest.groovy
@@ -42,7 +42,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext
import org.apache.brooklyn.api.management.Task
-import brooklyn.management.internal.EffectorUtils
+import org.apache.brooklyn.core.management.internal.EffectorUtils
import org.apache.brooklyn.test.entity.TestApplication
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java b/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java
index 0505456..62579e3 100644
--- a/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java
+++ b/core/src/test/java/brooklyn/entity/EffectorSayHiTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.entity.proxying.ImplementedBy;
import org.apache.brooklyn.api.management.ExecutionContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.BeforeMethod;
@@ -43,7 +44,6 @@ import brooklyn.entity.basic.AbstractEntity;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.trait.Startable;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.task.BasicTask;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/drivers/downloads/BasicDownloadsRegistryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/drivers/downloads/BasicDownloadsRegistryTest.java b/core/src/test/java/brooklyn/entity/drivers/downloads/BasicDownloadsRegistryTest.java
index 64bfcd4..472b3d9 100644
--- a/core/src/test/java/brooklyn/entity/drivers/downloads/BasicDownloadsRegistryTest.java
+++ b/core/src/test/java/brooklyn/entity/drivers/downloads/BasicDownloadsRegistryTest.java
@@ -24,6 +24,7 @@ import static org.testng.Assert.fail;
import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolver;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.annotations.AfterMethod;
@@ -38,8 +39,6 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.management.internal.LocalManagementContext;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromLocalRepoTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromLocalRepoTest.java b/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromLocalRepoTest.java
index 2ed52e4..afda43a 100644
--- a/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromLocalRepoTest.java
+++ b/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromLocalRepoTest.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager.
import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager.DownloadTargets;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.annotations.AfterMethod;
@@ -39,8 +40,6 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.management.internal.LocalManagementContext;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
[13/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynObjectManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynObjectManagerInternal.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynObjectManagerInternal.java
new file mode 100644
index 0000000..d22ffae
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynObjectManagerInternal.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import org.apache.brooklyn.api.basic.BrooklynObject;
+
+public interface BrooklynObjectManagerInternal<T extends BrooklynObject> {
+
+ ManagementTransitionMode getLastManagementTransitionMode(String itemId);
+ void setManagementTransitionMode(T item, ManagementTransitionMode mode);
+
+ /**
+ * Begins management for the given rebinded root, recursively;
+ * if rebinding as a read-only copy, {@link #setReadOnly(T, boolean)} should be called prior to this.
+ */
+ void manageRebindedRoot(T item);
+
+ void unmanage(final T e, final ManagementTransitionMode info);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/CollectionChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/CollectionChangeListener.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/CollectionChangeListener.java
new file mode 100644
index 0000000..45fa765
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/CollectionChangeListener.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+public interface CollectionChangeListener<Item> {
+ void onItemAdded(Item item);
+ void onItemRemoved(Item item);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java
new file mode 100644
index 0000000..028f2d2
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/EffectorUtils.java
@@ -0,0 +1,356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static brooklyn.util.GroovyJavaMethods.truth;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.ParameterType;
+import org.apache.brooklyn.api.management.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.BasicParameterType;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.PropagatedRuntimeException;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+/**
+ * Utility methods for invoking effectors.
+ */
+public class EffectorUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(EffectorUtils.class);
+
+ /** prepares arguments for an effector either accepting:
+ * an array, which should contain the arguments in order, optionally omitting those which have defaults defined;
+ * or a map, which should contain the arguments by name, again optionally omitting those which have defaults defined,
+ * and in this case also performing type coercion.
+ */
+ public static Object[] prepareArgsForEffector(Effector<?> eff, Object args) {
+ if (args != null && args.getClass().isArray()) {
+ return prepareArgsForEffectorFromArray(eff, (Object[]) args);
+ }
+ if (args instanceof Map) {
+ return prepareArgsForEffectorFromMap(eff, (Map) args);
+ }
+ log.warn("Deprecated effector invocation style for call to "+eff+", expecting a map or an array, got: "+args);
+ if (log.isDebugEnabled()) {
+ log.debug("Deprecated effector invocation style for call to "+eff+", expecting a map or an array, got: "+args,
+ new Throwable("Trace for deprecated effector invocation style"));
+ }
+ return oldPrepareArgsForEffector(eff, args);
+ }
+
+ /** method used for calls such as entity.effector(arg1, arg2)
+ * get routed here from AbstractEntity.invokeMethod */
+ private static Object[] prepareArgsForEffectorFromArray(Effector<?> eff, Object args[]) {
+ int newArgsNeeded = eff.getParameters().size();
+ if (args.length==1 && args[0] instanceof Map) {
+ if (newArgsNeeded!=1 || !eff.getParameters().get(0).getParameterClass().isAssignableFrom(args[0].getClass())) {
+ // treat a map in an array as a map passed directly (unless the method takes a single-arg map)
+ // this is to support effector(param1: val1)
+ return prepareArgsForEffectorFromMap(eff, (Map) args[0]);
+ }
+ }
+ return prepareArgsForEffectorAsMapFromArray(eff, args).values().toArray(new Object[0]);
+ }
+
+ public static Map prepareArgsForEffectorAsMapFromArray(Effector<?> eff, Object args[]) {
+ int newArgsNeeded = eff.getParameters().size();
+ List l = Lists.newArrayList();
+ l.addAll(Arrays.asList(args));
+ Map newArgs = new LinkedHashMap();
+
+ for (int index = 0; index < eff.getParameters().size(); index++) {
+ ParameterType<?> it = eff.getParameters().get(index);
+
+ if (l.size() >= newArgsNeeded) {
+ //all supplied (unnamed) arguments must be used; ignore map
+ newArgs.put(it.getName(), l.remove(0));
+ // TODO do we ignore arguments in the same order that groovy does?
+ } else if (!l.isEmpty() && it.getParameterClass().isInstance(l.get(0))) {
+ //if there are parameters supplied, and type is correct, they get applied before default values
+ //(this is akin to groovy)
+ newArgs.put(it.getName(), l.remove(0));
+ } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) {
+ //finally, default values are used to make up for missing parameters
+ newArgs.put(it.getName(), ((BasicParameterType)it).getDefaultValue());
+ } else {
+ throw new IllegalArgumentException("Invalid arguments (count mismatch) for effector "+eff+": "+args);
+ }
+
+ newArgsNeeded--;
+ }
+ if (newArgsNeeded > 0) {
+ throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+args);
+ }
+ if (!l.isEmpty()) {
+ throw new IllegalArgumentException("Invalid arguments ("+l.size()+" extra) for effector "+eff+": "+args);
+ }
+ return newArgs;
+ }
+
+ private static Object[] prepareArgsForEffectorFromMap(Effector<?> eff, Map m) {
+ m = Maps.newLinkedHashMap(m); //make editable copy
+ List newArgs = Lists.newArrayList();
+ int newArgsNeeded = eff.getParameters().size();
+
+ for (int index = 0; index < eff.getParameters().size(); index++) {
+ ParameterType<?> it = eff.getParameters().get(index);
+ Object v;
+ if (truth(it.getName()) && m.containsKey(it.getName())) {
+ // argument is in the map
+ v = m.remove(it.getName());
+ } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) {
+ //finally, default values are used to make up for missing parameters
+ v = ((BasicParameterType)it).getDefaultValue();
+ } else {
+ throw new IllegalArgumentException("Invalid arguments (missing argument "+it+") for effector "+eff+": "+m);
+ }
+
+ newArgs.add(TypeCoercions.coerce(v, it.getParameterClass()));
+ newArgsNeeded--;
+ }
+ if (newArgsNeeded>0)
+ throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+m);
+ return newArgs.toArray(new Object[newArgs.size()]);
+ }
+
+ /**
+ * Takes arguments, and returns an array of arguments suitable for use by the Effector
+ * according to the ParameterTypes it exposes.
+ * <p>
+ * The args can be:
+ * <ol>
+ * <li>an array of ordered arguments
+ * <li>a collection (which will be automatically converted to an array)
+ * <li>a single argument (which will then be wrapped in an array)
+ * <li>a map containing the (named) arguments
+ * <li>an array or collection single entry of a map (treated same as 5 above)
+ * <li>a semi-populated array or collection that also containing a map as first arg -
+ * uses ordered args in array, but uses named values from map in preference.
+ * <li>semi-populated array or collection, where default values will otherwise be used.
+ * </ol>
+ */
+ public static Object[] oldPrepareArgsForEffector(Effector<?> eff, Object args) {
+ //attempt to coerce unexpected types
+ Object[] argsArray;
+ if (args==null) {
+ argsArray = new Object[0];
+ } else if (args.getClass().isArray()) {
+ argsArray = (Object[]) args;
+ } else {
+ if (args instanceof Collection) {
+ argsArray = ((Collection) args).toArray(new Object[((Collection) args).size()]);
+ } else {
+ argsArray = new Object[] { args };
+ }
+ }
+
+ //if args starts with a map, assume it contains the named arguments
+ //(but only use it when we have insufficient supplied arguments)
+ List l = Lists.newArrayList();
+ l.addAll(Arrays.asList(argsArray));
+ Map m = (argsArray.length > 0 && argsArray[0] instanceof Map ? Maps.newLinkedHashMap((Map) l.remove(0)) : null);
+ List newArgs = Lists.newArrayList();
+ int newArgsNeeded = eff.getParameters().size();
+ boolean mapUsed = false;
+
+ for (int index = 0; index < eff.getParameters().size(); index++) {
+ ParameterType<?> it = eff.getParameters().get(index);
+
+ if (l.size() >= newArgsNeeded) {
+ //all supplied (unnamed) arguments must be used; ignore map
+ newArgs.add(l.remove(0));
+ } else if (truth(m) && truth(it.getName()) && m.containsKey(it.getName())) {
+ //some arguments were not supplied, and this one is in the map
+ newArgs.add(m.remove(it.getName()));
+ } else if (index == 0 && Map.class.isAssignableFrom(it.getParameterClass())) {
+ //if first arg is a map it takes the supplied map
+ newArgs.add(m);
+ mapUsed = true;
+ } else if (!l.isEmpty() && it.getParameterClass().isInstance(l.get(0))) {
+ //if there are parameters supplied, and type is correct, they get applied before default values
+ //(this is akin to groovy)
+ newArgs.add(l.remove(0));
+ } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) {
+ //finally, default values are used to make up for missing parameters
+ newArgs.add(((BasicParameterType)it).getDefaultValue());
+ } else {
+ throw new IllegalArgumentException("Invalid arguments (count mismatch) for effector "+eff+": "+args);
+ }
+
+ newArgsNeeded--;
+ }
+ if (newArgsNeeded > 0) {
+ throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+args);
+ }
+ if (!l.isEmpty()) {
+ throw new IllegalArgumentException("Invalid arguments ("+l.size()+" extra) for effector "+eff+": "+args);
+ }
+ if (truth(m) && !mapUsed) {
+ throw new IllegalArgumentException("Invalid arguments ("+m.size()+" extra named) for effector "+eff+": "+args);
+ }
+ return newArgs.toArray(new Object[newArgs.size()]);
+ }
+
+ /**
+ * Invokes a method effector so that its progress is tracked. For internal use only, when we know the effector is backed by a method which is local.
+ */
+ public static <T> T invokeMethodEffector(Entity entity, Effector<T> eff, Object[] args) {
+ String name = eff.getName();
+
+ try {
+ if (log.isDebugEnabled()) log.debug("Invoking effector {} on {}", new Object[] {name, entity});
+ if (log.isTraceEnabled()) log.trace("Invoking effector {} on {} with args {}", new Object[] {name, entity, args});
+ EntityManagementSupport mgmtSupport = ((EntityInternal)entity).getManagementSupport();
+ if (!mgmtSupport.isDeployed()) {
+ mgmtSupport.attemptLegacyAutodeployment(name);
+ }
+ ManagementContextInternal mgmtContext = (ManagementContextInternal) ((EntityInternal) entity).getManagementContext();
+
+ mgmtSupport.getEntityChangeListener().onEffectorStarting(eff, args);
+ try {
+ return mgmtContext.invokeEffectorMethodSync(entity, eff, args);
+ } finally {
+ mgmtSupport.getEntityChangeListener().onEffectorCompleted(eff);
+ }
+ } catch (Exception e) {
+ handleEffectorException(entity, eff, e);
+ // (won't return below)
+ return null;
+ }
+ }
+
+ public static void handleEffectorException(Entity entity, Effector<?> effector, Throwable throwable) {
+ String message = "Error invoking " + effector.getName() + " at " + entity;
+ // Avoid throwing a PropagatedRuntimeException that just repeats the last PropagatedRuntimeException.
+ if (throwable instanceof PropagatedRuntimeException &&
+ throwable.getMessage() != null &&
+ throwable.getMessage().startsWith(message)) {
+ throw PropagatedRuntimeException.class.cast(throwable);
+ } else {
+ log.warn(message + ": " + Exceptions.collapseText(throwable));
+ throw new PropagatedRuntimeException(message, throwable);
+ }
+ }
+
+ public static <T> Task<T> invokeEffectorAsync(Entity entity, Effector<T> eff, Map<String,?> parameters) {
+ String name = eff.getName();
+
+ if (log.isDebugEnabled()) log.debug("Invoking-async effector {} on {}", new Object[] { name, entity });
+ if (log.isTraceEnabled()) log.trace("Invoking-async effector {} on {} with args {}", new Object[] { name, entity, parameters });
+ EntityManagementSupport mgmtSupport = ((EntityInternal)entity).getManagementSupport();
+ if (!mgmtSupport.isDeployed()) {
+ mgmtSupport.attemptLegacyAutodeployment(name);
+ }
+ ManagementContextInternal mgmtContext = (ManagementContextInternal) ((EntityInternal)entity).getManagementContext();
+
+ // FIXME seems brittle to have the listeners in the Utils method; better to move into the context.invokeEff
+ // (or whatever the last mile before invoking the effector is - though currently there is not such a canonical place!)
+ mgmtSupport.getEntityChangeListener().onEffectorStarting(eff, parameters);
+ try {
+ return mgmtContext.invokeEffector(entity, eff, parameters);
+ } finally {
+ // FIXME this is really Effector submitted
+ mgmtSupport.getEntityChangeListener().onEffectorCompleted(eff);
+ }
+ }
+
+ /** @deprecated since 0.7.0, not used */
+ @Deprecated
+ public static Effector<?> findEffectorMatching(Entity entity, Method method) {
+ outer: for (Effector<?> effector : entity.getEntityType().getEffectors()) {
+ if (!effector.getName().equals(entity)) continue;
+ if (effector.getParameters().size() != method.getParameterTypes().length) continue;
+ for (int i = 0; i < effector.getParameters().size(); i++) {
+ if (effector.getParameters().get(i).getParameterClass() != method.getParameterTypes()[i]) continue outer;
+ }
+ return effector;
+ }
+ return null;
+ }
+
+ /** @deprecated since 0.7.0, expects parameters but does not use them! */
+ @Deprecated
+ public static Effector<?> findEffectorMatching(Set<Effector<?>> effectors, String effectorName, Map<String, ?> parameters) {
+ // TODO Support overloading: check parameters as well
+ for (Effector<?> effector : effectors) {
+ if (effector.getName().equals(effectorName)) {
+ return effector;
+ }
+ }
+ return null;
+ }
+
+ /** matches effectors by name only (not parameters) */
+ public static Maybe<Effector<?>> findEffector(Collection<? extends Effector<?>> effectors, String effectorName) {
+ for (Effector<?> effector : effectors) {
+ if (effector.getName().equals(effectorName)) {
+ return Maybe.<Effector<?>>of(effector);
+ }
+ }
+ return Maybe.absent(new NoSuchElementException("No effector with name "+effectorName+" (contenders "+effectors+")"));
+ }
+
+ /** matches effectors by name only (not parameters), based on what is declared on the entity static type */
+ public static Maybe<Effector<?>> findEffectorDeclared(Entity entity, String effectorName) {
+ return findEffector(entity.getEntityType().getEffectors(), effectorName);
+ }
+
+ /** @deprecated since 0.7.0 use {@link #getTaskFlagsForEffectorInvocation(Entity, Effector, ConfigBag)} */
+ public static Map<Object,Object> getTaskFlagsForEffectorInvocation(Entity entity, Effector<?> effector) {
+ return getTaskFlagsForEffectorInvocation(entity, effector, null);
+ }
+
+ /** returns a (mutable) map of the standard flags which should be placed on an effector */
+ public static Map<Object,Object> getTaskFlagsForEffectorInvocation(Entity entity, Effector<?> effector, ConfigBag parameters) {
+ return MutableMap.builder()
+ .put("description", "Invoking effector "+effector.getName()
+ +" on "+entity.getDisplayName()
+ +(parameters!=null ? " with parameters "+parameters.getAllConfig() : ""))
+ .put("displayName", effector.getName())
+ .put("tags", MutableList.of(
+ BrooklynTaskTags.EFFECTOR_TAG,
+ BrooklynTaskTags.tagForEffectorCall(entity, effector.getName(), parameters),
+ BrooklynTaskTags.tagForTargetEntity(entity)))
+ .build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityChangeListener.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityChangeListener.java
new file mode 100644
index 0000000..d6552ff
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityChangeListener.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.api.entity.Feed;
+import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.api.policy.Enricher;
+import org.apache.brooklyn.api.policy.Policy;
+
+import brooklyn.config.ConfigKey;
+
+public interface EntityChangeListener {
+
+ // TODO for testing only!
+ public static final EntityChangeListener NOOP = new EntityChangeListener() {
+ @Override public void onChanged() {}
+ @Override public void onAttributeChanged(AttributeSensor<?> attribute) {}
+ @Override public void onConfigChanged(ConfigKey<?> key) {}
+ @Override public void onLocationsChanged() {}
+ @Override public void onMembersChanged() {}
+ @Override public void onTagsChanged() {}
+ @Override public void onChildrenChanged() {}
+ @Override public void onPolicyAdded(Policy policy) {}
+ @Override public void onPolicyRemoved(Policy policy) {}
+ @Override public void onEnricherAdded(Enricher enricher) {}
+ @Override public void onEnricherRemoved(Enricher enricher) {}
+ @Override public void onFeedAdded(Feed feed) {}
+ @Override public void onFeedRemoved(Feed feed) {}
+ @Override public void onEffectorStarting(Effector<?> effector, Object parameters) {}
+ @Override public void onEffectorCompleted(Effector<?> effector) {}
+ };
+
+ void onChanged();
+
+ void onAttributeChanged(AttributeSensor<?> attribute);
+
+ void onConfigChanged(ConfigKey<?> key);
+
+ void onLocationsChanged();
+
+ void onTagsChanged();
+
+ void onMembersChanged();
+
+ void onChildrenChanged();
+
+ void onPolicyAdded(Policy policy);
+
+ void onPolicyRemoved(Policy policy);
+
+ void onEnricherAdded(Enricher enricher);
+
+ void onEnricherRemoved(Enricher enricher);
+
+ void onFeedAdded(Feed feed);
+
+ void onFeedRemoved(Feed feed);
+
+ void onEffectorStarting(Effector<?> effector, Object parameters);
+
+ void onEffectorCompleted(Effector<?> effector);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementSupport.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementSupport.java
new file mode 100644
index 0000000..dbba29c
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementSupport.java
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Feed;
+import org.apache.brooklyn.api.event.AttributeSensor;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.SubscriptionContext;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+import org.apache.brooklyn.api.policy.Enricher;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.management.internal.NonDeploymentManagementContext.NonDeploymentManagementContextMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Stopwatch;
+
+/**
+ * Encapsulates management activities at an entity.
+ * <p>
+ * On entity deployment, ManagementContext.manage(entity) causes
+ * <p>
+ * * onManagementStarting(ManagementContext)
+ * * onManagementStartingSubscriptions()
+ * * onManagementStartingSensorEmissions()
+ * * onManagementStartingExecutions()
+ * * onManagementStarted() - when all the above is said and done
+ * * onManagementStartingHere();
+ * <p>
+ * on unmanage it hits onManagementStoppingHere() then onManagementStopping().
+ * <p>
+ * When an entity's management migrates, it invoked onManagementStoppingHere() at the old location,
+ * then onManagementStartingHere() at the new location.
+ */
+public class EntityManagementSupport {
+
+ private static final Logger log = LoggerFactory.getLogger(EntityManagementSupport.class);
+
+ public EntityManagementSupport(AbstractEntity entity) {
+ this.entity = entity;
+ nonDeploymentManagementContext = new NonDeploymentManagementContext(entity, NonDeploymentManagementContextMode.PRE_MANAGEMENT);
+ }
+
+ protected transient AbstractEntity entity;
+ NonDeploymentManagementContext nonDeploymentManagementContext;
+
+ protected transient ManagementContext initialManagementContext;
+ protected transient ManagementContext managementContext;
+ protected transient SubscriptionContext subscriptionContext;
+ protected transient ExecutionContext executionContext;
+
+ // TODO the application
+ // (elaborate or remove ^^^ ? -AH, Sept 2014)
+
+ protected final AtomicBoolean managementContextUsable = new AtomicBoolean(false);
+ protected final AtomicBoolean currentlyDeployed = new AtomicBoolean(false);
+ protected final AtomicBoolean everDeployed = new AtomicBoolean(false);
+ protected Boolean readOnly = null;
+ protected final AtomicBoolean managementFailed = new AtomicBoolean(false);
+
+ private volatile EntityChangeListener entityChangeListener = EntityChangeListener.NOOP;
+
+ /**
+ * Whether this entity is managed (i.e. "onManagementStarting" has been called, so the framework knows about it,
+ * and it has not been unmanaged).
+ */
+ public boolean isDeployed() { return currentlyDeployed.get(); }
+ public boolean isNoLongerManaged() {
+ return wasDeployed() && !isDeployed();
+ }
+ /** whether entity has ever been deployed (managed) */
+ public boolean wasDeployed() { return everDeployed.get(); }
+
+ @Beta
+ public void setReadOnly(boolean isReadOnly) {
+ if (isDeployed())
+ throw new IllegalStateException("Cannot set read only after deployment");
+ this.readOnly = isReadOnly;
+ }
+
+ /** Whether the entity and its adjuncts should be treated as read-only;
+ * may be null briefly when initializing if RO status is unknown. */
+ @Beta
+ public Boolean isReadOnlyRaw() {
+ return readOnly;
+ }
+
+ /** Whether the entity and its adjuncts should be treated as read-only;
+ * error if initializing and RO status is unknown. */
+ @Beta
+ public boolean isReadOnly() {
+ Preconditions.checkNotNull(readOnly, "Read-only status of %s not yet known", entity);
+ return readOnly;
+ }
+
+ /**
+ * Whether the entity's management lifecycle is complete (i.e. both "onManagementStarting" and "onManagementStarted" have
+ * been called, and it is has not been unmanaged).
+ */
+ public boolean isFullyManaged() {
+ return (nonDeploymentManagementContext == null) && currentlyDeployed.get();
+ }
+
+ public synchronized void setManagementContext(ManagementContextInternal val) {
+ if (initialManagementContext != null) {
+ throw new IllegalStateException("Initial management context is already set for "+entity+"; cannot change");
+ }
+ if (managementContext != null && !managementContext.equals(val)) {
+ throw new IllegalStateException("Management context is already set for "+entity+"; cannot change");
+ }
+
+ this.initialManagementContext = checkNotNull(val, "managementContext");
+ if (nonDeploymentManagementContext != null) {
+ nonDeploymentManagementContext.setManagementContext(val);
+ }
+ }
+
+ public void onRebind(ManagementTransitionInfo info) {
+ nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_REBINDING);
+ }
+
+ public void onManagementStarting(ManagementTransitionInfo info) {
+ try {
+ synchronized (this) {
+ boolean alreadyManaging = isDeployed();
+
+ if (alreadyManaging) {
+ log.warn("Already managed: "+entity+" ("+nonDeploymentManagementContext+"); onManagementStarting is no-op");
+ } else if (nonDeploymentManagementContext == null || !nonDeploymentManagementContext.getMode().isPreManaged()) {
+ throw new IllegalStateException("Not in expected pre-managed state: "+entity+" ("+nonDeploymentManagementContext+")");
+ }
+ if (managementContext != null && !managementContext.equals(info.getManagementContext())) {
+ throw new IllegalStateException("Already has management context: "+managementContext+"; can't set "+info.getManagementContext());
+ }
+ if (initialManagementContext != null && !initialManagementContext.equals(info.getManagementContext())) {
+ throw new IllegalStateException("Already has different initial management context: "+initialManagementContext+"; can't set "+info.getManagementContext());
+ }
+ if (alreadyManaging) {
+ return;
+ }
+
+ this.managementContext = info.getManagementContext();
+ nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STARTING);
+
+ if (!isReadOnly()) {
+ nonDeploymentManagementContext.getSubscriptionManager().setDelegate((AbstractSubscriptionManager) managementContext.getSubscriptionManager());
+ nonDeploymentManagementContext.getSubscriptionManager().startDelegatingForSubscribing();
+ }
+
+ managementContextUsable.set(true);
+ currentlyDeployed.set(true);
+ everDeployed.set(true);
+
+ entityChangeListener = new EntityChangeListenerImpl();
+ }
+
+ /*
+ * TODO framework starting events - phase 1, including rebind
+ * - establish hierarchy (child, groups, etc; construction if necessary on rebind)
+ * - set location
+ * - set local config values
+ * - set saved sensor values
+ * - register subscriptions -- BUT nothing is allowed to execute
+ * [these operations may be done before we invoke starting also; above can happen in any order;
+ * sensor _publications_ and executor submissions are queued]
+ * then: set the management context and the entity is "managed" from the perspective of external viewers (ManagementContext.isManaged(entity) returns true)
+ */
+
+ if (!isReadOnly()) {
+ entity.onManagementStarting();
+ }
+ } catch (Throwable t) {
+ managementFailed.set(true);
+ throw Exceptions.propagate(t);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void onManagementStarted(ManagementTransitionInfo info) {
+ try {
+ synchronized (this) {
+ boolean alreadyManaged = isFullyManaged();
+
+ if (alreadyManaged) {
+ log.warn("Already managed: "+entity+" ("+nonDeploymentManagementContext+"); onManagementStarted is no-op");
+ } else if (nonDeploymentManagementContext == null || nonDeploymentManagementContext.getMode() != NonDeploymentManagementContextMode.MANAGEMENT_STARTING) {
+ throw new IllegalStateException("Not in expected \"management starting\" state: "+entity+" ("+nonDeploymentManagementContext+")");
+ }
+ if (managementContext != info.getManagementContext()) {
+ throw new IllegalStateException("Already has management context: "+managementContext+"; can't set "+info.getManagementContext());
+ }
+ if (alreadyManaged) {
+ return;
+ }
+
+ nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STARTED);
+
+ /*
+ * - set derived/inherited config values
+ * - publish all queued sensors
+ * - start all queued executions (e.g. subscription delivery)
+ * [above happens in exactly this order, at each entity]
+ * then: the entity internally knows it fully managed (ManagementSupport.isManaged() returns true -- though not sure we need that);
+ * subsequent sensor events and executions occur directly (no queueing)
+ */
+
+ if (!isReadOnly()) {
+ nonDeploymentManagementContext.getSubscriptionManager().startDelegatingForPublishing();
+ }
+
+ // TODO more of the above
+ // TODO custom started activities
+ // (elaborate or remove ^^^ ? -AH, Sept 2014)
+ }
+
+ if (!isReadOnly()) {
+ entity.onManagementBecomingMaster();
+ entity.onManagementStarted();
+ }
+
+ synchronized (this) {
+ nonDeploymentManagementContext = null;
+ }
+ } catch (Throwable t) {
+ managementFailed.set(true);
+ throw Exceptions.propagate(t);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void onManagementStopping(ManagementTransitionInfo info) {
+ synchronized (this) {
+ if (managementContext != info.getManagementContext()) {
+ throw new IllegalStateException("onManagementStopping encountered different management context for "+entity+
+ (!wasDeployed() ? " (wasn't deployed)" : !isDeployed() ? " (no longer deployed)" : "")+
+ ": "+managementContext+"; expected "+info.getManagementContext()+" (may be a pre-registered entity which was never properly managed)");
+ }
+ Stopwatch startTime = Stopwatch.createStarted();
+ while (!managementFailed.get() && nonDeploymentManagementContext!=null &&
+ nonDeploymentManagementContext.getMode()==NonDeploymentManagementContextMode.MANAGEMENT_STARTING) {
+ // still becoming managed
+ try {
+ if (startTime.elapsed(TimeUnit.SECONDS) > 30) {
+ // emergency fix, 30s timeout for management starting
+ log.error("Management stopping event "+info+" in "+this+" timed out waiting for start; proceeding to stopping");
+ break;
+ }
+ wait(100);
+ } catch (InterruptedException e) {
+ Exceptions.propagate(e);
+ }
+ }
+ if (nonDeploymentManagementContext==null) {
+ nonDeploymentManagementContext = new NonDeploymentManagementContext(entity, NonDeploymentManagementContextMode.MANAGEMENT_STOPPING);
+ } else {
+ // already stopped? or not started?
+ nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STOPPING);
+ }
+ }
+ // TODO custom stopping activities
+ // TODO framework stopping events - no more sensors, executions, etc
+ // (elaborate or remove ^^^ ? -AH, Sept 2014)
+
+ if (!isReadOnly() && info.getMode().isDestroying()) {
+ // if we support remote parent of local child, the following call will need to be properly remoted
+ if (entity.getParent()!=null) entity.getParent().removeChild(entity.getProxyIfAvailable());
+ }
+ // new subscriptions will be queued / not allowed
+ nonDeploymentManagementContext.getSubscriptionManager().stopDelegatingForSubscribing();
+ // new publications will be queued / not allowed
+ nonDeploymentManagementContext.getSubscriptionManager().stopDelegatingForPublishing();
+
+ if (!isReadOnly()) {
+ entity.onManagementNoLongerMaster();
+ entity.onManagementStopped();
+ }
+ }
+
+ public void onManagementStopped(ManagementTransitionInfo info) {
+ synchronized (this) {
+ if (managementContext == null && nonDeploymentManagementContext.getMode() == NonDeploymentManagementContextMode.MANAGEMENT_STOPPED) {
+ return;
+ }
+ if (managementContext != info.getManagementContext()) {
+ throw new IllegalStateException("Has different management context: "+managementContext+"; expected "+info.getManagementContext());
+ }
+ getSubscriptionContext().unsubscribeAll();
+ entityChangeListener = EntityChangeListener.NOOP;
+ managementContextUsable.set(false);
+ currentlyDeployed.set(false);
+ executionContext = null;
+ subscriptionContext = null;
+ }
+
+ // TODO framework stopped activities, e.g. serialize state ?
+ entity.invalidateReferences();
+
+ synchronized (this) {
+ managementContext = null;
+ nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STOPPED);
+ }
+ }
+
+ @VisibleForTesting
+ @Beta
+ public boolean isManagementContextReal() {
+ return managementContextUsable.get();
+ }
+
+ public synchronized ManagementContext getManagementContext() {
+ return (managementContextUsable.get()) ? managementContext : nonDeploymentManagementContext;
+ }
+
+ public synchronized ExecutionContext getExecutionContext() {
+ if (executionContext!=null) return executionContext;
+ if (managementContextUsable.get()) {
+ executionContext = managementContext.getExecutionContext(entity);
+ return executionContext;
+ }
+ return nonDeploymentManagementContext.getExecutionContext(entity);
+ }
+ public synchronized SubscriptionContext getSubscriptionContext() {
+ if (subscriptionContext!=null) return subscriptionContext;
+ if (managementContextUsable.get()) {
+ subscriptionContext = managementContext.getSubscriptionContext(entity);
+ return subscriptionContext;
+ }
+ return nonDeploymentManagementContext.getSubscriptionContext(entity);
+ }
+ public synchronized EntitlementManager getEntitlementManager() {
+ return getManagementContext().getEntitlementManager();
+ }
+
+ public void attemptLegacyAutodeployment(String effectorName) {
+ synchronized (this) {
+ if (managementContext != null) {
+ log.warn("Autodeployment suggested but not required for " + entity + "." + effectorName);
+ return;
+ }
+ if (entity instanceof Application) {
+ log.warn("Autodeployment with new management context triggered for " + entity + "." + effectorName + " -- will not be supported in future. Explicit manage call required.");
+ if (initialManagementContext != null) {
+ initialManagementContext.getEntityManager().manage(entity);
+ } else {
+ Entities.startManagement(entity);
+ }
+ return;
+ }
+ }
+ if ("start".equals(effectorName)) {
+ Entity e=entity;
+ if (e.getParent()!=null && ((EntityInternal)e.getParent()).getManagementSupport().isDeployed()) {
+ log.warn("Autodeployment in parent's management context triggered for "+entity+"."+effectorName+" -- will not be supported in future. Explicit manage call required.");
+ ((EntityInternal)e.getParent()).getManagementContext().getEntityManager().manage(entity);
+ return;
+ }
+ }
+ log.warn("Autodeployment not available for "+entity+"."+effectorName);
+ }
+
+ public EntityChangeListener getEntityChangeListener() {
+ return entityChangeListener;
+ }
+
+ private class EntityChangeListenerImpl implements EntityChangeListener {
+ @Override
+ public void onChanged() {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ }
+ @Override
+ public void onChildrenChanged() {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ }
+ @Override
+ public void onLocationsChanged() {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ }
+ @Override
+ public void onTagsChanged() {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ }
+ @Override
+ public void onMembersChanged() {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ }
+ @Override
+ public void onPolicyAdded(Policy policy) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ getManagementContext().getRebindManager().getChangeListener().onManaged(policy);
+ }
+ @Override
+ public void onEnricherAdded(Enricher enricher) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ getManagementContext().getRebindManager().getChangeListener().onManaged(enricher);
+ }
+ @Override
+ public void onFeedAdded(Feed feed) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ getManagementContext().getRebindManager().getChangeListener().onManaged(feed);
+ }
+ @Override
+ public void onPolicyRemoved(Policy policy) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ getManagementContext().getRebindManager().getChangeListener().onUnmanaged(policy);
+ }
+ @Override
+ public void onEnricherRemoved(Enricher enricher) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ getManagementContext().getRebindManager().getChangeListener().onUnmanaged(enricher);
+ }
+ @Override
+ public void onFeedRemoved(Feed feed) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ getManagementContext().getRebindManager().getChangeListener().onUnmanaged(feed);
+ }
+ @Override
+ public void onAttributeChanged(AttributeSensor<?> attribute) {
+ // TODO Could make this more efficient by inspecting the attribute to decide if needs persisted
+ // immediately, or not important, or transient (e.g. do we really need to persist
+ // request-per-second count for rebind purposes?!)
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ }
+ @Override
+ public void onConfigChanged(ConfigKey<?> key) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ }
+ @Override
+ public void onEffectorStarting(Effector<?> effector, Object parameters) {
+ Entitlements.checkEntitled(getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(entity, StringAndArgument.of(effector.getName(), parameters)));
+ }
+ @Override
+ public void onEffectorCompleted(Effector<?> effector) {
+ getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()+"["+(entity==null ? "null" : entity.getId())+"]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java
new file mode 100644
index 0000000..3f59774
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagementUtils.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+
+import java.io.StringReader;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityFunctions;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.trait.Startable;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.task.TaskBuilder;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+/** Utility methods for working with entities and applications */
+public class EntityManagementUtils {
+
+ private static final Logger log = LoggerFactory.getLogger(EntityManagementUtils.class);
+
+ /**
+ * A marker config value which indicates that an application was created automatically
+ * to allow the management of a non-app entity.
+ */
+ public static final ConfigKey<Boolean> WRAPPER_APP_MARKER = ConfigKeys.newBooleanConfigKey("brooklyn.wrapper_app");
+
+ /** creates an application from the given app spec, managed by the given management context */
+ public static <T extends Application> T createUnstarted(ManagementContext mgmt, EntitySpec<T> spec) {
+ T app = mgmt.getEntityManager().createEntity(spec);
+ Entities.startManagement(app, mgmt);
+ return app;
+ }
+
+ /** convenience for accessing camp */
+ public static Maybe<CampPlatform> getCampPlatform(ManagementContext mgmt) {
+ return BrooklynServerConfig.getCampPlatform(mgmt);
+ }
+
+ /** as {@link #createApplication(ManagementContext, EntitySpec)} but for a YAML spec */
+ public static <T extends Application> T createUnstarted(ManagementContext mgmt, String yaml) {
+ AssemblyTemplate at = getCampPlatform(mgmt).get().pdp().registerDeploymentPlan( new StringReader(yaml) );
+ return createUnstarted(mgmt, at);
+ }
+
+ /** as {@link #createApplication(ManagementContext, EntitySpec)} but for an assembly template */
+ @SuppressWarnings("unchecked")
+ public static <T extends Application> T createUnstarted(ManagementContext mgmt, AssemblyTemplate at) {
+ CampPlatform camp = getCampPlatform(mgmt).get();
+ AssemblyTemplateInstantiator instantiator;
+ try {
+ instantiator = at.getInstantiator().newInstance();
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ Assembly assembly;
+ if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+ BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
+
+ EntitySpec<?> spec = ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, true);
+ Entity app = mgmt.getEntityManager().createEntity(spec);
+ Entities.startManagement((Application)app, mgmt);
+ return (T) app;
+ } else {
+ // currently, all brooklyn plans should produce the above; currently this will always throw Unsupported
+ try {
+ assembly = instantiator.instantiate(at, camp);
+ return (T) mgmt.getEntityManager().getEntity(assembly.getId());
+ } catch (UnsupportedOperationException e) {
+ if (at.getPlatformComponentTemplates()==null || at.getPlatformComponentTemplates().isEmpty()) {
+ if (at.getCustomAttributes().containsKey("brooklyn.catalog"))
+ throw new IllegalArgumentException("Unrecognized application blueprint format: expected an application, not a brooklyn.catalog");
+ throw new IllegalArgumentException("Unrecognized application blueprint format: no services defined");
+ }
+ // map this (expected) error to a nicer message
+ throw new IllegalArgumentException("Unrecognized application blueprint format");
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalArgumentException("Invalid plan: "+at, e);
+ }
+ }
+ }
+
+ /** container for operation which creates something and which wants to return both
+ * the items created and any pending create/start task */
+ public static class CreationResult<T,U> {
+ private final T thing;
+ @Nullable private final Task<U> task;
+ public CreationResult(T thing, Task<U> task) {
+ super();
+ this.thing = thing;
+ this.task = task;
+ }
+
+ protected static <T,U> CreationResult<T,U> of(T thing, @Nullable Task<U> task) {
+ return new CreationResult<T,U>(thing, task);
+ }
+
+ /** returns the thing/things created */
+ @Nullable public T get() { return thing; }
+ /** associated task, ie the one doing the creation/starting */
+ public Task<U> task() { return task; }
+ public CreationResult<T,U> blockUntilComplete(Duration timeout) { if (task!=null) task.blockUntilEnded(timeout); return this; }
+ public CreationResult<T,U> blockUntilComplete() { if (task!=null) task.blockUntilEnded(); return this; }
+ }
+
+ public static <T extends Application> CreationResult<T,Void> createStarting(ManagementContext mgmt, EntitySpec<T> appSpec) {
+ return start(createUnstarted(mgmt, appSpec));
+ }
+
+ public static CreationResult<? extends Application,Void> createStarting(ManagementContext mgmt, String appSpec) {
+ return start(createUnstarted(mgmt, appSpec));
+ }
+
+ public static CreationResult<? extends Application,Void> createStarting(ManagementContext mgmt, AssemblyTemplate at) {
+ return start(createUnstarted(mgmt, at));
+ }
+
+ public static <T extends Application> CreationResult<T,Void> start(T app) {
+ Task<Void> task = Entities.invokeEffector((EntityLocal)app, app, Startable.START,
+ // locations already set in the entities themselves;
+ // TODO make it so that this arg does not have to be supplied to START !
+ MutableMap.of("locations", MutableList.of()));
+ return CreationResult.of(app, task);
+ }
+
+ public static CreationResult<List<Entity>, List<String>> addChildren(final EntityLocal parent, String yaml, Boolean start) {
+ if (Boolean.FALSE.equals(start))
+ return CreationResult.of(addChildrenUnstarted(parent, yaml), null);
+ return addChildrenStarting(parent, yaml);
+ }
+
+ /** adds entities from the given yaml, under the given parent; but does not start them */
+ public static List<Entity> addChildrenUnstarted(final EntityLocal parent, String yaml) {
+ log.debug("Creating child of "+parent+" from yaml:\n{}", yaml);
+
+ ManagementContext mgmt = parent.getApplication().getManagementContext();
+ CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
+
+ AssemblyTemplate at = camp.pdp().registerDeploymentPlan( new StringReader(yaml) );
+
+ AssemblyTemplateInstantiator instantiator;
+ try {
+ instantiator = at.getInstantiator().newInstance();
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+ BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
+ EntitySpec<?> specA = ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, false);
+
+ // see whether we can promote children
+ List<EntitySpec<?>> specs = MutableList.of();
+ if (hasNoNameOrCustomKeysOrRoot(at, specA)) {
+ // we can promote
+ for (EntitySpec<?> specC: specA.getChildren()) {
+ collapseSpec(specA, specC);
+ specs.add(specC);
+ }
+ } else {
+ // if not promoting, set a nice name if needed
+ if (Strings.isEmpty(specA.getDisplayName())) {
+ int size = specA.getChildren().size();
+ String childrenCountString = size+" "+(size!=1 ? "children" : "child");
+ specA.displayName("Dynamically added "+childrenCountString);
+ }
+ specs.add(specA);
+ }
+
+ final List<Entity> children = MutableList.of();
+ for (EntitySpec<?> spec: specs) {
+ Entity child = (Entity)parent.addChild(spec);
+ Entities.manage(child);
+ children.add(child);
+ }
+
+ return children;
+ } else {
+ throw new IllegalStateException("Spec could not be parsed to supply a compatible instantiator");
+ }
+ }
+
+ public static CreationResult<List<Entity>,List<String>> addChildrenStarting(final EntityLocal parent, String yaml) {
+ final List<Entity> children = addChildrenUnstarted(parent, yaml);
+ String childrenCountString;
+
+ int size = children.size();
+ childrenCountString = size+" "+(size!=1 ? "children" : "child");
+
+ TaskBuilder<List<String>> taskM = Tasks.<List<String>>builder().name("add children")
+ .dynamic(true)
+ .tag(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG)
+ .body(new Callable<List<String>>() {
+ @Override public List<String> call() throws Exception {
+ return ImmutableList.copyOf(Iterables.transform(children, EntityFunctions.id()));
+ }})
+ .description("Add and start "+childrenCountString);
+
+ TaskBuilder<?> taskS = Tasks.builder().parallel(true).name("add (parallel)").description("Start each new entity");
+
+ // autostart if requested
+ for (Entity child: children) {
+ if (child instanceof Startable) {
+ taskS.add(Effectors.invocation(child, Startable.START, ImmutableMap.of("locations", ImmutableList.of())));
+ } else {
+ // include a task, just to give feedback in the GUI
+ taskS.add(Tasks.builder().name("create").description("Skipping start (not a Startable Entity)")
+ .body(new Runnable() { public void run() {} })
+ .tag(BrooklynTaskTags.tagForTargetEntity(child))
+ .build());
+ }
+ }
+ taskM.add(taskS.build());
+ Task<List<String>> task = Entities.submit(parent, taskM.build());
+
+ return CreationResult.of(children, task);
+ }
+
+ /** worker method to combine specs */
+ @Beta //where should this live long-term?
+ public static void collapseSpec(EntitySpec<?> sourceToBeCollapsed, EntitySpec<?> targetToBeExpanded) {
+ if (Strings.isEmpty(targetToBeExpanded.getDisplayName()))
+ targetToBeExpanded.displayName(sourceToBeCollapsed.getDisplayName());
+ if (!sourceToBeCollapsed.getLocations().isEmpty())
+ targetToBeExpanded.locations(sourceToBeCollapsed.getLocations());
+
+ // NB: this clobbers child config; might prefer to deeply merge maps etc
+ // (but this should not be surprising, as unwrapping is often parameterising the nested blueprint, so outer config should dominate)
+ targetToBeExpanded.configure(sourceToBeCollapsed.getConfig());
+ targetToBeExpanded.configure(sourceToBeCollapsed.getFlags());
+
+ // TODO copying tags to all entities is not ideal;
+ // in particular the BrooklynTags.YAML_SPEC tag will show all entities if the root has multiple
+ targetToBeExpanded.tags(sourceToBeCollapsed.getTags());
+ }
+
+ /** worker method to help determine whether child/children can be promoted */
+ @Beta //where should this live long-term?
+ public static boolean hasNoNameOrCustomKeysOrRoot(AssemblyTemplate template, EntitySpec<?> spec) {
+ if (Strings.isNonEmpty(template.getName())) {
+ if (spec.getChildren().size()==1) {
+ String childName = Iterables.getOnlyElement(spec.getChildren()).getDisplayName();
+ if (Strings.isEmpty(childName) || childName.equals(template.getName())) {
+ // if child has no name, or it's the same, could still promote
+ } else {
+ return false;
+ }
+ } else {
+ // if name set at root and promoting children would be ambiguous, do not promote
+ return false;
+ }
+ } else if (spec.getChildren().size()>1) {
+ // don't allow multiple children if a name is specified as a root
+ return false;
+ }
+
+ Set<String> rootAttrs = template.getCustomAttributes().keySet();
+ for (String rootAttr: rootAttrs) {
+ if (rootAttr.equals("brooklyn.catalog") || rootAttr.equals("brooklyn.config")) {
+ // these do not block promotion
+ continue;
+ }
+ if (rootAttr.startsWith("brooklyn.")) {
+ // any others in 'brooklyn' namespace will block promotion
+ return false;
+ }
+ // location is allowed in both, and is copied on promotion
+ // (name also copied)
+ // others are root currently are ignored on promotion; they are usually metadata
+ // TODO might be nice to know what we are excluding
+ }
+
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagerInternal.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagerInternal.java
new file mode 100644
index 0000000..08f4069
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/EntityManagerInternal.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.management.EntityManager;
+
+public interface EntityManagerInternal extends EntityManager, BrooklynObjectManagerInternal<Entity> {
+
+ /** gets all entities currently known to the application, including entities that are not yet managed */
+ Iterable<Entity> getAllEntitiesInApplication(Application application);
+
+ public Iterable<String> getEntityIds();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java
new file mode 100644
index 0000000..4e74904
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import groovy.util.ObservableList;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+public class GroovyObservablesPropertyChangeToCollectionChangeAdapter implements PropertyChangeListener {
+ @SuppressWarnings("rawtypes")
+ private final CollectionChangeListener delegate;
+
+ public GroovyObservablesPropertyChangeToCollectionChangeAdapter(@SuppressWarnings("rawtypes") CollectionChangeListener delegate) {
+ this.delegate = delegate;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt instanceof ObservableList.ElementAddedEvent) {
+ delegate.onItemAdded(evt.getNewValue());
+ } else if (evt instanceof ObservableList.ElementRemovedEvent) {
+ delegate.onItemRemoved(evt.getOldValue());
+ } else if (evt instanceof ObservableList.ElementUpdatedEvent) {
+ delegate.onItemRemoved(evt.getOldValue());
+ delegate.onItemAdded(evt.getNewValue());
+ } else if (evt instanceof ObservableList.ElementClearedEvent) {
+ for (Object value : ((ObservableList.ElementClearedEvent) evt).getValues()) {
+ delegate.onItemAdded(value);
+ }
+ } else if(evt instanceof ObservableList.MultiElementAddedEvent ) {
+ for(Object value: ((ObservableList.MultiElementAddedEvent)evt).getValues()){
+ delegate.onItemAdded(value);
+ }
+ }
+ }
+
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ public boolean equals(Object other) {
+ if (other instanceof GroovyObservablesPropertyChangeToCollectionChangeAdapter)
+ return delegate.equals(((GroovyObservablesPropertyChangeToCollectionChangeAdapter) other).delegate);
+ if (other instanceof CollectionChangeListener)
+ return delegate.equals(other);
+ return false;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalAccessManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalAccessManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalAccessManager.java
new file mode 100644
index 0000000..2699676
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalAccessManager.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.AccessController;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public class LocalAccessManager implements AccessManager {
+
+ private volatile boolean locationProvisioningAllowed = true;
+ private volatile boolean locationManagementAllowed = true;
+ private volatile boolean entityManagementAllowed = true;
+
+ private final AtomicReference<AccessControllerImpl> controller = new AtomicReference<AccessControllerImpl>();
+
+ public LocalAccessManager() {
+ updateAccessController();
+ }
+
+ @Override
+ public AccessController getAccessController() {
+ return controller.get();
+ }
+
+ @Override
+ public boolean isLocationProvisioningAllowed() {
+ return locationProvisioningAllowed;
+ }
+
+ @Override
+ public boolean isLocationManagementAllowed() {
+ return locationManagementAllowed;
+ }
+
+ @Override
+ public boolean isEntityManagementAllowed() {
+ return entityManagementAllowed;
+ }
+
+ @Override
+ public void setLocationProvisioningAllowed(boolean allowed) {
+ locationProvisioningAllowed = allowed;
+ updateAccessController();
+ }
+
+ @Override
+ public void setLocationManagementAllowed(boolean allowed) {
+ locationManagementAllowed = allowed;
+ updateAccessController();
+ }
+
+ @Override
+ public void setEntityManagementAllowed(boolean allowed) {
+ entityManagementAllowed = allowed;
+ updateAccessController();
+ }
+
+ private void updateAccessController() {
+ controller.set(new AccessControllerImpl(locationProvisioningAllowed, locationManagementAllowed, entityManagementAllowed));
+ }
+
+ private static class AccessControllerImpl implements AccessController {
+ private final boolean locationProvisioningAllowed;
+ private final boolean locationManagementAllowed;
+ private final boolean entityManagementAllowed;
+
+ public AccessControllerImpl(boolean locationProvisioningAllowed, boolean locationManagementAllowed,
+ boolean entityManagementAllowed) {
+ this.locationProvisioningAllowed = locationProvisioningAllowed;
+ this.locationManagementAllowed = locationManagementAllowed;
+ this.entityManagementAllowed = entityManagementAllowed;
+ }
+
+ @Override
+ public Response canProvisionLocation(Location provisioner) {
+ return (locationProvisioningAllowed ? Response.allowed() : Response.disallowed("location provisioning disabled"));
+ }
+
+ @Override
+ public Response canManageLocation(Location loc) {
+ return (locationManagementAllowed ? Response.allowed() : Response.disallowed("location management disabled"));
+ }
+
+ @Override
+ public Response canManageEntity(Entity entity) {
+ return (entityManagementAllowed ? Response.allowed() : Response.disallowed("entity management disabled"));
+ }
+ }
+}
[23/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
deleted file mode 100644
index 32e5c1b..0000000
--- a/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.classloading;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.Enumeration;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-
-import com.google.common.base.Objects;
-
-public class JavaBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
-
- // on deserialization this loader is replaced with the catalog's root loader;
- // may cause problems for non-osgi catalog items, but that's a reasonable trade-off,
- // should this be serialized (e.g. in SpecialFlagsTransformer) in such a case!
- private final transient ClassLoader loader;
-
- /**
- * @deprecated since 0.7.0 only for legacy catalog items which provide a non-osgi loader; see {@link #newDefault(ManagementContext)}
- */ @Deprecated
- public static JavaBrooklynClassLoadingContext create(ClassLoader loader) {
- return new JavaBrooklynClassLoadingContext(null, checkNotNull(loader, "loader"));
- }
-
- /**
- * At least one of mgmt or loader must not be null.
- * @deprecated since 0.7.0 only for legacy catalog items which provide a non-osgi loader; see {@link #newDefault(ManagementContext)}
- */ @Deprecated
- public static JavaBrooklynClassLoadingContext create(ManagementContext mgmt, ClassLoader loader) {
- checkState(mgmt != null || loader != null, "mgmt and loader must not both be null");
- return new JavaBrooklynClassLoadingContext(mgmt, loader);
- }
-
- public static JavaBrooklynClassLoadingContext create(ManagementContext mgmt) {
- return new JavaBrooklynClassLoadingContext(checkNotNull(mgmt, "mgmt"), null);
- }
-
- @Deprecated /** @deprecated since 0.7.0 use {@link #create(ManagementContext)} */
- public static JavaBrooklynClassLoadingContext newDefault(ManagementContext mgmt) {
- return new JavaBrooklynClassLoadingContext(checkNotNull(mgmt, "mgmt"), null);
- }
-
- @Deprecated /** @deprecated since 0.7.0 will become private; use one of the static methods to instantiate */
- public JavaBrooklynClassLoadingContext(ManagementContext mgmt, ClassLoader loader) {
- super(mgmt);
- this.loader = loader;
- }
-
- private ClassLoader getClassLoader() {
- if (loader != null) return loader;
- if (mgmt!=null) return mgmt.getCatalogClassLoader();
- return JavaBrooklynClassLoadingContext.class.getClassLoader();
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public Maybe<Class<?>> tryLoadClass(String className) {
- try {
- return (Maybe) Maybe.of(getClassLoader().loadClass(className));
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- return Maybe.absent("Invalid class: "+className, e);
- }
- }
-
- @Override
- public String toString() {
- return "java:"+getClassLoader();
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(super.hashCode(), getClassLoader());
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!super.equals(obj)) return false;
- if (!(obj instanceof JavaBrooklynClassLoadingContext)) return false;
- if (!Objects.equal(getClassLoader(), ((JavaBrooklynClassLoadingContext)obj).getClassLoader())) return false;
- return true;
- }
-
- @Override
- public URL getResource(String name) {
- return getClassLoader().getResource(name);
- }
-
- @Override
- public Iterable<URL> getResources(String name) {
- Enumeration<URL> resources;
- try {
- resources = getClassLoader().getResources(name);
- } catch (IOException e) {
- throw Exceptions.propagate(e);
- }
- return Collections.list(resources);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
deleted file mode 100644
index 027ccc3..0000000
--- a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.classloading;
-
-import java.net.URL;
-import java.util.Collection;
-import java.util.Collections;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
-
-import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.ha.OsgiManager;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.util.guava.Maybe;
-
-import com.google.common.base.Objects;
-
-public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
-
- private final String catalogItemId;
- private boolean hasBundles = false;
- private transient Collection<CatalogBundle> _bundles;
-
- public OsgiBrooklynClassLoadingContext(ManagementContext mgmt, String catalogItemId, Collection<CatalogBundle> bundles) {
- super(mgmt);
- this._bundles = bundles;
- this.hasBundles = bundles!=null && !bundles.isEmpty();
- this.catalogItemId = catalogItemId;
- }
-
- public Collection<CatalogBundle> getBundles() {
- if (_bundles!=null || !hasBundles) return _bundles;
- CatalogItem<?, ?> cat = CatalogUtils.getCatalogItemOptionalVersion(mgmt, catalogItemId);
- if (cat==null) {
- throw new IllegalStateException("Catalog item not found for "+catalogItemId+"; cannot create loading context");
- }
- _bundles = cat.getLibraries();
- return _bundles;
- }
-
- @Override
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public Maybe<Class<?>> tryLoadClass(String className) {
- Maybe<Class<Object>> clazz = null;
- Maybe<OsgiManager> osgi = null;
- if (mgmt!=null) {
- osgi = ((ManagementContextInternal)mgmt).getOsgiManager();
- if (osgi.isPresent() && getBundles()!=null && !getBundles().isEmpty()) {
- if (!Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_CATALOG_ITEM, catalogItemId))
- return Maybe.absent("Not entitled to use this catalog entry");
-
- clazz = osgi.get().tryResolveClass(className, getBundles());
- if (clazz.isPresent())
- return (Maybe)clazz;
- }
- }
-
- if (clazz!=null) {
- // if OSGi bundles were defined and failed, then use its error message
- return (Maybe)clazz;
- }
- // else determine best message
- if (mgmt==null) return Maybe.absent("No mgmt context available for loading "+className);
- if (osgi!=null && osgi.isAbsent()) return Maybe.absent("OSGi not available on mgmt for loading "+className);
- if (!hasBundles)
- return Maybe.absent("No bundles available for loading "+className);
- return Maybe.absent("Inconsistent state ("+mgmt+"/"+osgi+"/"+getBundles()+" loading "+className);
- }
-
- @Override
- public String toString() {
- return "OSGi:"+catalogItemId+"["+getBundles()+"]";
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(super.hashCode(), getBundles(), catalogItemId);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!super.equals(obj)) return false;
- if (!(obj instanceof OsgiBrooklynClassLoadingContext)) return false;
-
- OsgiBrooklynClassLoadingContext other = (OsgiBrooklynClassLoadingContext)obj;
- if (!catalogItemId.equals(other.catalogItemId)) return false;
- if (!Objects.equal(getBundles(), other.getBundles())) return false;
- return true;
- }
-
- @Override
- public URL getResource(String name) {
- if (mgmt != null && isEntitledToSeeCatalogItem()) {
- Maybe<OsgiManager> osgi = ((ManagementContextInternal) mgmt).getOsgiManager();
- if (osgi.isPresent() && hasBundles) {
- return osgi.get().getResource(name, getBundles());
- }
- }
- return null;
- }
-
- @Override
- public Iterable<URL> getResources(String name) {
- if (mgmt != null && isEntitledToSeeCatalogItem()) {
- Maybe<OsgiManager> osgi = ((ManagementContextInternal) mgmt).getOsgiManager();
- if (osgi.isPresent() && hasBundles) {
- return osgi.get().getResources(name, getBundles());
- }
- }
- return Collections.emptyList();
- }
-
- public String getCatalogItemId() {
- return catalogItemId;
- }
-
- /**
- * @return true if the current entitlement context may {@link Entitlements#SEE_CATALOG_ITEM see}
- * {@link #getCatalogItemId}.
- */
- private boolean isEntitledToSeeCatalogItem() {
- return Entitlements.isEntitled(mgmt.getEntitlementManager(),
- Entitlements.SEE_CATALOG_ITEM,
- catalogItemId);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/entitlement/BasicEntitlementClassDefinition.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/entitlement/BasicEntitlementClassDefinition.java b/core/src/main/java/brooklyn/management/entitlement/BasicEntitlementClassDefinition.java
deleted file mode 100644
index dc41aa3..0000000
--- a/core/src/main/java/brooklyn/management/entitlement/BasicEntitlementClassDefinition.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
-
-import com.google.common.base.Objects;
-import com.google.common.reflect.TypeToken;
-
-
-public class BasicEntitlementClassDefinition<T> implements EntitlementClass<T> {
-
- private final String identifier;
- private final TypeToken<T> argumentType;
-
- public BasicEntitlementClassDefinition(String identifier, TypeToken<T> argumentType) {
- this.identifier = identifier;
- this.argumentType = argumentType;
- }
-
- public BasicEntitlementClassDefinition(String identifier, Class<T> argumentType) {
- this.identifier = identifier;
- this.argumentType = TypeToken.of(argumentType);
- }
-
- @Override
- public String entitlementClassIdentifier() {
- return identifier;
- }
-
- @Override
- public TypeToken<T> entitlementClassArgumentType() {
- return argumentType;
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this).add("identitifier", identifier).add("argumentType", argumentType).toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/entitlement/EntitlementManagerAdapter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/entitlement/EntitlementManagerAdapter.java b/core/src/main/java/brooklyn/management/entitlement/EntitlementManagerAdapter.java
deleted file mode 100644
index 0eeb4ba..0000000
--- a/core/src/main/java/brooklyn/management/entitlement/EntitlementManagerAdapter.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
-import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.Beta;
-
-import brooklyn.management.entitlement.Entitlements.EntitlementClassesHandler;
-import brooklyn.management.entitlement.Entitlements.EntityAndItem;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
-
-/**
- * provides an easy entry point to supplying entitlements, by providing the dispatch and defining the additional methods
- * which have to be supplied.
- * <p>
- * note that this class may change as versions change, deliberately breaking backwards compatibility
- * to ensure all permissions are used.
- * <p>
- * @since 0.7.0 */
-@Beta
-public abstract class EntitlementManagerAdapter implements EntitlementManager {
-
- private static final Logger log = LoggerFactory.getLogger(EntitlementManagerAdapter.class);
-
- protected class Handler implements EntitlementClassesHandler<Boolean> {
- final EntitlementContext context;
- protected Handler(EntitlementContext context) {
- this.context = context;
- }
-
- @Override
- public Boolean handleSeeCatalogItem(String catalogItemId) {
- return isEntitledToSeeCatalogItem(context, catalogItemId);
- }
- @Override
- public Boolean handleAddCatalogItem(Object catalogItemBeingAdded) {
- return isEntitledToAddCatalogItem(context, catalogItemBeingAdded);
- }
- @Override
- public Boolean handleModifyCatalogItem(StringAndArgument catalogItemIdAndModification) {
- return isEntitledToModifyCatalogItem(context, catalogItemIdAndModification==null ? null : catalogItemIdAndModification.getString(),
- catalogItemIdAndModification==null ? null : catalogItemIdAndModification.getArgument());
- }
-
- @Override
- public Boolean handleSeeEntity(Entity entity) {
- return isEntitledToSeeEntity(context, entity);
- }
- @Override
- public Boolean handleSeeSensor(EntityAndItem<String> sensorInfo) {
- return isEntitledToSeeSensor(context, sensorInfo.getEntity(), sensorInfo.getItem());
- }
- @Override
- public Boolean handleInvokeEffector(EntityAndItem<StringAndArgument> effectorInfo) {
- StringAndArgument item = effectorInfo.getItem();
- return isEntitledToInvokeEffector(context, effectorInfo.getEntity(), item==null ? null : item.getString(), item==null ? null : item.getArgument());
- }
- @Override
- public Boolean handleModifyEntity(Entity entity) {
- return isEntitledToModifyEntity(context, entity);
- }
-
- @Override
- public Boolean handleDeployApplication(Object app) {
- return isEntitledToDeployApplication(context, app);
- }
-
- @Override
- public Boolean handleSeeAllServerInfo() {
- return isEntitledToSeeAllServerInfo(context);
- }
-
- @Override
- public Boolean handleSeeServerStatus() {
- return isEntitledToSeeServerStatus(context);
- }
-
- @Override
- public Boolean handleRoot() {
- return isEntitledToRoot(context);
- }
- }
-
- @Override
- public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
- if (log.isTraceEnabled()) {
- log.trace("Checking entitlement of "+context+" to "+entitlementClass+" "+entitlementClassArgument);
- }
-
- if (isEntitledToRoot( context )) return true;
-
- Handler handler = new Handler(context);
- return Entitlements.EntitlementClassesEnum.of(entitlementClass).handle(
- handler, entitlementClassArgument);
- }
-
- protected abstract boolean isEntitledToSeeCatalogItem(EntitlementContext context, String catalogItemId);
- /** passes item to be added, either yaml, or possibly null if any addition allowed (eg when resetting) */
- protected abstract boolean isEntitledToAddCatalogItem(EntitlementContext context, Object catalogItemBeingAdded);
- /** passes item being modified, as ID and description of modification, both possibly null if any modification is allowed (eg when resetting) */
- protected abstract boolean isEntitledToModifyCatalogItem(EntitlementContext context, String catalogItemId, Object catalogItemModification);
- protected abstract boolean isEntitledToSeeSensor(EntitlementContext context, Entity entity, String sensorName);
- protected abstract boolean isEntitledToSeeEntity(EntitlementContext context, Entity entity);
- /** arguments might be null, a map, or a list, depending how/where invoked */
- protected abstract boolean isEntitledToInvokeEffector(EntitlementContext context, Entity entity, String effectorName, Object arguments);
- protected abstract boolean isEntitledToModifyEntity(EntitlementContext context, Entity entity);
- protected abstract boolean isEntitledToDeployApplication(EntitlementContext context, Object app);
- protected abstract boolean isEntitledToSeeAllServerInfo(EntitlementContext context);
- protected abstract boolean isEntitledToSeeServerStatus(EntitlementContext context);
- protected abstract boolean isEntitledToRoot(EntitlementContext context);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/entitlement/EntitlementPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/entitlement/EntitlementPredicates.java b/core/src/main/java/brooklyn/management/entitlement/EntitlementPredicates.java
deleted file mode 100644
index 75bc5dd..0000000
--- a/core/src/main/java/brooklyn/management/entitlement/EntitlementPredicates.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-
-import com.google.common.base.Predicate;
-
-public class EntitlementPredicates {
-
- public static <T> Predicate<T> isEntitled(final EntitlementManager entitlementManager, final EntitlementClass<T> entitlementClass) {
-
- return new Predicate<T>() {
- @Override
- public boolean apply(@Nullable T t) {
- return Entitlements.isEntitled(entitlementManager, entitlementClass, t);
- }
- };
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/entitlement/Entitlements.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/entitlement/Entitlements.java b/core/src/main/java/brooklyn/management/entitlement/Entitlements.java
deleted file mode 100644
index 28a9a84..0000000
--- a/core/src/main/java/brooklyn/management/entitlement/Entitlements.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import java.util.Arrays;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
-import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Joiner;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.reflect.TypeToken;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.javalang.Reflections;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.Strings;
-
-/** @since 0.7.0 */
-@Beta
-public class Entitlements {
-
- private static final Logger log = LoggerFactory.getLogger(Entitlements.class);
-
- // ------------------- individual permissions
-
- public static EntitlementClass<String> SEE_CATALOG_ITEM = new BasicEntitlementClassDefinition<String>("catalog.see", String.class);
- public static EntitlementClass<Object> ADD_CATALOG_ITEM = new BasicEntitlementClassDefinition<Object>("catalog.add", Object.class);
- public static EntitlementClass<StringAndArgument> MODIFY_CATALOG_ITEM = new BasicEntitlementClassDefinition<StringAndArgument>("catalog.modify", StringAndArgument.class);
-
- public static EntitlementClass<Entity> SEE_ENTITY = new BasicEntitlementClassDefinition<Entity>("entity.see", Entity.class);
- public static EntitlementClass<EntityAndItem<String>> SEE_SENSOR = new BasicEntitlementClassDefinition<EntityAndItem<String>>("sensor.see", EntityAndItem. typeToken(String.class));
- // string is effector name; argument may be a map or a list, depending how the args were supplied
- public static EntitlementClass<EntityAndItem<StringAndArgument>> INVOKE_EFFECTOR = new BasicEntitlementClassDefinition<EntityAndItem<StringAndArgument>>("effector.invoke", EntityAndItem.typeToken(StringAndArgument.class));
- public static EntitlementClass<Entity> MODIFY_ENTITY = new BasicEntitlementClassDefinition<Entity>("entity.modify", Entity.class);
-
- /** the permission to deploy an application, where parameter is some representation of the app to be deployed (spec instance or yaml plan) */
- public static EntitlementClass<Object> DEPLOY_APPLICATION = new BasicEntitlementClassDefinition<Object>("app.deploy", Object.class);
-
- /** catch-all for catalog, locations, scripting, usage, etc - exporting persistence, shutting down, etc;
- * this is significantly more powerful than {@link #SERVER_STATUS}.
- * NB: this may be refactored and deprecated in future */
- public static EntitlementClass<Void> SEE_ALL_SERVER_INFO = new BasicEntitlementClassDefinition<Void>("server.info.all.see", Void.class);
-
- /** permission to see general server status info: basically HA status; not nearly as much as {@link #SEE_ALL_SERVER_INFO} */
- public static EntitlementClass<Void> SERVER_STATUS = new BasicEntitlementClassDefinition<Void>("server.status", Void.class);
-
- /** permission to run untrusted code or embedded scripts at the server;
- * secondary check required for any operation which could potentially grant root-level access */
- public static EntitlementClass<Void> ROOT = new BasicEntitlementClassDefinition<Void>("root", Void.class);
-
- @SuppressWarnings("unchecked")
- public static enum EntitlementClassesEnum {
- ENTITLEMENT_SEE_CATALOG_ITEM(SEE_CATALOG_ITEM) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeCatalogItem((String)argument); } },
- ENTITLEMENT_ADD_CATALOG_ITEM(ADD_CATALOG_ITEM) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleAddCatalogItem(argument); } },
- ENTITLEMENT_MODIFY_CATALOG_ITEM(MODIFY_CATALOG_ITEM) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleModifyCatalogItem((StringAndArgument)argument); } },
-
- ENTITLEMENT_SEE_ENTITY(SEE_ENTITY) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeEntity((Entity)argument); } },
- ENTITLEMENT_SEE_SENSOR(SEE_SENSOR) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeSensor((EntityAndItem<String>)argument); } },
- ENTITLEMENT_INVOKE_EFFECTOR(INVOKE_EFFECTOR) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleInvokeEffector((EntityAndItem<StringAndArgument>)argument); } },
- ENTITLEMENT_MODIFY_ENTITY(MODIFY_ENTITY) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleModifyEntity((Entity)argument); } },
-
- ENTITLEMENT_DEPLOY_APPLICATION(DEPLOY_APPLICATION) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleDeployApplication(argument); } },
-
- ENTITLEMENT_SEE_ALL_SERVER_INFO(SEE_ALL_SERVER_INFO) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeAllServerInfo(); } },
- ENTITLEMENT_SERVER_STATUS(SERVER_STATUS) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleSeeServerStatus(); } },
- ENTITLEMENT_ROOT(ROOT) { public <T> T handle(EntitlementClassesHandler<T> handler, Object argument) { return handler.handleRoot(); } },
- ;
-
- private EntitlementClass<?> entitlementClass;
-
- private EntitlementClassesEnum(EntitlementClass<?> specificClass) {
- this.entitlementClass = specificClass;
- }
- public EntitlementClass<?> getEntitlementClass() {
- return entitlementClass;
- }
-
- public abstract <T> T handle(EntitlementClassesHandler<T> handler, Object argument);
-
- public static EntitlementClassesEnum of(EntitlementClass<?> entitlementClass) {
- for (EntitlementClassesEnum x: values()) {
- if (entitlementClass.equals(x.getEntitlementClass())) return x;
- }
- return null;
- }
- }
-
- public interface EntitlementClassesHandler<T> {
- public T handleSeeCatalogItem(String catalogItemId);
- public T handleSeeServerStatus();
- public T handleAddCatalogItem(Object catalogItemBeingAdded);
- public T handleModifyCatalogItem(StringAndArgument catalogItemIdAndModification);
- public T handleSeeEntity(Entity entity);
- public T handleSeeSensor(EntityAndItem<String> sensorInfo);
- public T handleInvokeEffector(EntityAndItem<StringAndArgument> effectorInfo);
- public T handleModifyEntity(Entity entity);
- public T handleDeployApplication(Object app);
- public T handleSeeAllServerInfo();
- public T handleRoot();
- }
-
- protected static class Pair<T1,T2> {
- protected final T1 p1;
- protected final T2 p2;
- protected Pair(T1 p1, T2 p2) { this.p1 = p1; this.p2 = p2; }
- }
- public static class EntityAndItem<T> extends Pair<Entity,T> {
- public static <TT> TypeToken<EntityAndItem<TT>> typeToken(Class<TT> type) {
- return new TypeToken<Entitlements.EntityAndItem<TT>>() {
- private static final long serialVersionUID = -738154831809025407L;
- };
- }
- public EntityAndItem(Entity entity, T item) { super (entity, item); }
- public Entity getEntity() { return p1; }
- public T getItem() { return p2; }
- public static <T> EntityAndItem<T> of(Entity entity, T item) {
- return new EntityAndItem<T>(entity, item);
- }
- }
-
- public static class StringAndArgument extends Pair<String,Object> {
- public StringAndArgument(String string, Object argument) { super(string, argument); }
- public String getString() { return p1; }
- public Object getArgument() { return p2; }
- public static StringAndArgument of(String string, Object argument) {
- return new StringAndArgument(string, argument);
- }
- }
-
- /**
- * These lifecycle operations are currently treated as effectors. This may change in the future.
- * @since 0.7.0 */
- @Beta
- public static class LifecycleEffectors {
- public static final String DELETE = "delete";
- }
-
- // ------------- permission sets -------------
-
- /** always ALLOW access to everything */
- public static EntitlementManager root() {
- return new EntitlementManager() {
- @Override
- public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
- return true;
- }
- @Override
- public String toString() {
- return "Entitlements.root";
- }
- };
- }
-
- /** always DENY access to anything which requires entitlements */
- public static EntitlementManager minimal() {
- return new EntitlementManager() {
- @Override
- public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
- return false;
- }
- @Override
- public String toString() {
- return "Entitlements.minimal";
- }
- };
- }
-
- public static class FineGrainedEntitlements {
-
- private static final Joiner COMMA_JOINER = Joiner.on(',');
-
- public static EntitlementManager anyOf(final EntitlementManager... checkers) {
- return anyOf(Arrays.asList(checkers));
- }
-
- public static EntitlementManager anyOf(final Iterable<? extends EntitlementManager> checkers) {
- return new EntitlementManager() {
- @Override
- public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
- for (EntitlementManager checker: checkers)
- if (checker.isEntitled(context, permission, typeArgument))
- return true;
- return false;
- }
- @Override
- public String toString() {
- return "Entitlements.anyOf(" + COMMA_JOINER.join(checkers) + ")";
- }
- };
- }
-
- public static EntitlementManager allOf(final EntitlementManager... checkers) {
- return allOf(Arrays.asList(checkers));
- }
-
- public static EntitlementManager allOf(final Iterable<? extends EntitlementManager> checkers) {
- return new EntitlementManager() {
- @Override
- public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
- for (EntitlementManager checker: checkers)
- if (checker.isEntitled(context, permission, typeArgument))
- return true;
- return false;
- }
- @Override
- public String toString() {
- return "Entitlements.allOf(" + COMMA_JOINER.join(checkers) + ")";
- }
- };
- }
-
- public static <U> EntitlementManager allowing(EntitlementClass<U> permission, Predicate<U> test) {
- return new SinglePermissionEntitlementChecker<U>(permission, test);
- }
-
- public static <U> EntitlementManager allowing(EntitlementClass<U> permission) {
- return new SinglePermissionEntitlementChecker<U>(permission, Predicates.<U>alwaysTrue());
- }
-
- public static class SinglePermissionEntitlementChecker<U> implements EntitlementManager {
- final EntitlementClass<U> permission;
- final Predicate<U> test;
-
- protected SinglePermissionEntitlementChecker(EntitlementClass<U> permission, Predicate<U> test) {
- this.permission = permission;
- this.test = test;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> permission, T typeArgument) {
- if (!Objects.equal(this.permission, permission)) return false;
- return test.apply((U)typeArgument);
- }
- @Override
- public String toString() {
- return "Entitlements.allowing(" + permission + " -> " + test + ")";
- }
- }
- public static EntitlementManager seeNonSecretSensors() {
- return allowing(SEE_SENSOR, new Predicate<EntityAndItem<String>>() {
- @Override
- public boolean apply(EntityAndItem<String> input) {
- if (input == null) return false;
- return !Entities.isSecret(input.getItem());
- }
- @Override
- public String toString() {
- return "Predicates.nonSecret";
- }
- });
- }
-
- }
-
- /** allow read-only */
- public static EntitlementManager readOnly() {
- return FineGrainedEntitlements.anyOf(
- FineGrainedEntitlements.allowing(SEE_ENTITY),
- FineGrainedEntitlements.seeNonSecretSensors()
- );
- }
-
- /** allow healthcheck */
- public static EntitlementManager serverStatusOnly() {
- return FineGrainedEntitlements.allowing(SERVER_STATUS);
- }
-
- // ------------- lookup conveniences -------------
-
- private static class PerThreadEntitlementContextHolder {
- public static final ThreadLocal<EntitlementContext> perThreadEntitlementsContextHolder = new ThreadLocal<EntitlementContext>();
- }
-
- /**
- * Finds the currently applicable {@link EntitlementContext} by examining the current thread
- * then by investigating the current task, its submitter, etc. */
- // NOTE: entitlements are propagated to tasks whenever they are created, as tags
- // (see BrooklynTaskTags.tagForEntitlement and BasicExecutionContext.submitInternal).
- // It might be cheaper to only do this lookup, not to propagate as tags, and to ensure
- // all entitlement operations are wrapped in a task at source; but currently we do not
- // do that so we need at least to set entitlement on the outermost task.
- // Setting it on tasks submitted by a task is not strictly necessary (i.e. in BasicExecutionContext)
- // but seems cheap enough, and means checking entitlements is fast, if we choose to do that more often.
- public static EntitlementContext getEntitlementContext() {
- EntitlementContext context;
- context = PerThreadEntitlementContextHolder.perThreadEntitlementsContextHolder.get();
- if (context!=null) return context;
-
- Task<?> task = Tasks.current();
- while (task!=null) {
- context = BrooklynTaskTags.getEntitlement(task);
- if (context!=null) return context;
- task = task.getSubmittedByTask();
- }
-
- // no entitlements set -- assume entitlements not used, or system internal
- return null;
- }
-
- public static void setEntitlementContext(EntitlementContext context) {
- EntitlementContext oldContext = PerThreadEntitlementContextHolder.perThreadEntitlementsContextHolder.get();
- if (oldContext!=null && context!=null) {
- log.warn("Changing entitlement context from "+oldContext+" to "+context+"; context should have been reset or extended, not replaced");
- log.debug("Trace for entitlement context duplicate overwrite", new Throwable("Trace for entitlement context overwrite"));
- }
- PerThreadEntitlementContextHolder.perThreadEntitlementsContextHolder.set(context);
- }
-
- public static void clearEntitlementContext() {
- PerThreadEntitlementContextHolder.perThreadEntitlementsContextHolder.set(null);
- }
-
- public static <T> boolean isEntitled(EntitlementManager checker, EntitlementClass<T> permission, T typeArgument) {
- return checker.isEntitled(getEntitlementContext(), permission, typeArgument);
- }
-
- /** throws {@link NotEntitledException} if entitlement not available for current {@link #getEntitlementContext()} */
- public static <T> void checkEntitled(EntitlementManager checker, EntitlementClass<T> permission, T typeArgument) {
- if (!isEntitled(checker, permission, typeArgument)) {
- throw new NotEntitledException(getEntitlementContext(), permission, typeArgument);
- }
- }
- /** throws {@link NotEntitledException} if entitlement not available for current {@link #getEntitlementContext()}
- * @since 0.7.0
- * @deprecated since 0.7.0, use {@link #checkEntitled(EntitlementManager, EntitlementClass, Object)};
- * kept briefly because there is some downstream usage*/
- public static <T> void requireEntitled(EntitlementManager checker, EntitlementClass<T> permission, T typeArgument) {
- checkEntitled(checker, permission, typeArgument);
- }
-
- // ----------------- initialization ----------------
-
- public final static String ENTITLEMENTS_CONFIG_PREFIX = "brooklyn.entitlements";
-
- public static ConfigKey<String> GLOBAL_ENTITLEMENT_MANAGER = ConfigKeys.newStringConfigKey(ENTITLEMENTS_CONFIG_PREFIX+".global",
- "Class for entitlements in effect globally; "
- + "short names 'minimal', 'readonly', or 'root' are permitted here, with the default 'root' giving full access to all declared users; "
- + "or supply the name of an "+EntitlementManager.class+" class to instantiate, taking a 1-arg BrooklynProperties constructor or a 0-arg constructor",
- "root");
-
- public static EntitlementManager newManager(ManagementContext mgmt, BrooklynProperties brooklynProperties) {
- return newGlobalManager(mgmt, brooklynProperties);
- }
- private static EntitlementManager newGlobalManager(ManagementContext mgmt, BrooklynProperties brooklynProperties) {
- return load(mgmt, brooklynProperties, brooklynProperties.getConfig(GLOBAL_ENTITLEMENT_MANAGER));
- }
-
- public static EntitlementManager load(@Nullable ManagementContext mgmt, BrooklynProperties brooklynProperties, String type) {
- if ("root".equalsIgnoreCase(type)) return root();
- if ("readonly".equalsIgnoreCase(type) || "read_only".equalsIgnoreCase(type)) return readOnly();
- if ("minimal".equalsIgnoreCase(type)) return minimal();
- if (Strings.isNonBlank(type)) {
- try {
- ClassLoader cl = mgmt==null ? null : ((ManagementContextInternal)mgmt).getCatalogClassLoader();
- if (cl==null) cl = Entitlements.class.getClassLoader();
- Class<?> clazz = cl.loadClass(type);
- return (EntitlementManager) instantiate(clazz, ImmutableList.of(
- new Object[] {mgmt, brooklynProperties},
- new Object[] {mgmt},
- new Object[] {brooklynProperties},
- new Object[0]));
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
- throw new IllegalStateException("Invalid entitlement manager specified: '"+type+"'");
- }
-
- private static Object instantiate(Class<?> clazz, List<Object[]> constructorArgOptions) {
- try {
- for (Object[] constructorArgOption : constructorArgOptions) {
- Optional<?> result = Reflections.invokeConstructorWithArgs(clazz, constructorArgOption);
- if (result.isPresent()) return result.get();
- }
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- throw new IllegalStateException("No matching constructor to instantiate "+clazz);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/entitlement/NotEntitledException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/entitlement/NotEntitledException.java b/core/src/main/java/brooklyn/management/entitlement/NotEntitledException.java
deleted file mode 100644
index f63b7e3..0000000
--- a/core/src/main/java/brooklyn/management/entitlement/NotEntitledException.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
-import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
-
-
-public class NotEntitledException extends RuntimeException {
-
- private static final long serialVersionUID = -4001882260980589181L;
-
- EntitlementContext entitlementContext;
- EntitlementClass<?> permission;
- Object typeArgument;
-
- public <T> NotEntitledException(EntitlementContext entitlementContext, EntitlementClass<T> permission, T typeArgument) {
- this.entitlementContext = entitlementContext;
- this.permission = permission;
- this.typeArgument = typeArgument;
- }
-
- @Override
- public String toString() {
- return super.toString()+"["+entitlementContext+":"+permission+(typeArgument!=null ? "("+typeArgument+")" : "")+"]";
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/entitlement/PerUserEntitlementManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/entitlement/PerUserEntitlementManager.java b/core/src/main/java/brooklyn/management/entitlement/PerUserEntitlementManager.java
deleted file mode 100644
index ab9a90f..0000000
--- a/core/src/main/java/brooklyn/management/entitlement/PerUserEntitlementManager.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
-import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigPredicates;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Preconditions;
-
-public class PerUserEntitlementManager implements EntitlementManager {
-
- private static final Logger log = LoggerFactory.getLogger(PerUserEntitlementManager.class);
-
- public final static String PER_USER_ENTITLEMENTS_CONFIG_PREFIX = Entitlements.ENTITLEMENTS_CONFIG_PREFIX+".perUser";
-
- public final static ConfigKey<String> DEFAULT_MANAGER = ConfigKeys.newStringConfigKey(PER_USER_ENTITLEMENTS_CONFIG_PREFIX+
- ".default", "Default entitlements manager for users without further specification", "minimal");
-
- protected final EntitlementManager defaultManager;
- protected final Map<String,EntitlementManager> perUserManagers = MutableMap.of();
-
- private final static ThreadLocal<Boolean> ACTIVE = new ThreadLocal<Boolean>();
-
- private static EntitlementManager load(BrooklynProperties properties, String type) {
- if (Boolean.TRUE.equals(ACTIVE.get())) {
- // prevent infinite loop
- throw new IllegalStateException("Cannot set "+PerUserEntitlementManager.class.getName()+" within config for itself");
- }
- try {
- ACTIVE.set(true);
- return Entitlements.load(null, properties, type);
- } finally {
- ACTIVE.remove();
- }
- }
-
- public PerUserEntitlementManager(BrooklynProperties properties) {
- this(load(properties, properties.getConfig(DEFAULT_MANAGER)));
-
- BrooklynProperties users = properties.submap(ConfigPredicates.startingWith(PER_USER_ENTITLEMENTS_CONFIG_PREFIX+"."));
- for (Map.Entry<ConfigKey<?>,?> key: users.getAllConfig().entrySet()) {
- if (key.getKey().getName().equals(DEFAULT_MANAGER.getName())) continue;
- String user = Strings.removeFromStart(key.getKey().getName(), PER_USER_ENTITLEMENTS_CONFIG_PREFIX+".");
- addUser(user, load(properties, Strings.toString(key.getValue())));
- }
-
- log.info(getClass().getSimpleName()+" created with "+perUserManagers.size()+" user"+Strings.s(perUserManagers)+" and "
- + "default "+defaultManager+" (users: "+perUserManagers+")");
- }
-
- public PerUserEntitlementManager(EntitlementManager defaultManager) {
- this.defaultManager = Preconditions.checkNotNull(defaultManager);
- }
-
- public void addUser(String user, EntitlementManager managerForThisUser) {
- perUserManagers.put(Preconditions.checkNotNull(user, "user"), Preconditions.checkNotNull(managerForThisUser, "managerForThisUser"));
- }
-
- @Override
- public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
- EntitlementManager entitlementInEffect = null;
- if (context==null || context.user()==null) {
- // no user means it is running as an internal process, always has root
- entitlementInEffect = Entitlements.root();
- } else {
- if (context!=null) entitlementInEffect = perUserManagers.get(context.user());
- if (entitlementInEffect==null) entitlementInEffect = defaultManager;
- }
- return entitlementInEffect.isEntitled(context, entitlementClass, entitlementClassArgument);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/entitlement/PerUserEntitlementManagerWithDefault.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/entitlement/PerUserEntitlementManagerWithDefault.java b/core/src/main/java/brooklyn/management/entitlement/PerUserEntitlementManagerWithDefault.java
deleted file mode 100644
index 95f254f..0000000
--- a/core/src/main/java/brooklyn/management/entitlement/PerUserEntitlementManagerWithDefault.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-
-@Deprecated
-/** @deprecated since 0.7.0 use {@link PerUserEntitlementManager} */
-public class PerUserEntitlementManagerWithDefault extends PerUserEntitlementManager {
-
- public PerUserEntitlementManagerWithDefault(EntitlementManager defaultManager) {
- super(defaultManager);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/entitlement/WebEntitlementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/entitlement/WebEntitlementContext.java b/core/src/main/java/brooklyn/management/entitlement/WebEntitlementContext.java
deleted file mode 100644
index f6db50d..0000000
--- a/core/src/main/java/brooklyn/management/entitlement/WebEntitlementContext.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
-
-import brooklyn.util.javalang.JavaClassNames;
-
-/**
- * Indicates an authenticated web request as the entitlements context;
- * note user may still be null if no authentication was requested
- */
-public class WebEntitlementContext implements EntitlementContext {
-
- final String user;
- final String sourceIp;
- final String requestUri;
-
- /**
- * A mostly-unique identifier for the inbound request, to distinguish
- * between duplicate requests and for cross-referencing with URIs
- */
- final String requestUniqueIdentifier;
-
- public WebEntitlementContext(String user, String sourceIp, String requestUri, String requestUniqueIdentifier) {
- this.user = user;
- this.sourceIp = sourceIp;
- this.requestUri = requestUri;
- this.requestUniqueIdentifier = requestUniqueIdentifier;
- }
-
- @Override public String user() { return user; }
- public String sourceIp() { return sourceIp; }
- public String requestUri() { return requestUri; }
- public String requestUniqueIdentifier() { return requestUniqueIdentifier; }
-
- @Override
- public String toString() {
- return JavaClassNames.simpleClassName(getClass())+"["+user+"@"+sourceIp+":"+requestUniqueIdentifier+"]";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/ha/BasicMasterChooser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/BasicMasterChooser.java b/core/src/main/java/brooklyn/management/ha/BasicMasterChooser.java
deleted file mode 100644
index a44c372..0000000
--- a/core/src/main/java/brooklyn/management/ha/BasicMasterChooser.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.brooklyn.api.entity.trait.Identifiable;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.text.NaturalOrderComparator;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ComparisonChain;
-import com.google.common.collect.Ordering;
-
-/**
- * @since 0.7.0
- *
- * @author aled
- */
-@Beta
-public abstract class BasicMasterChooser implements MasterChooser {
-
- private static final Logger LOG = LoggerFactory.getLogger(BasicMasterChooser.class);
-
- protected static class ScoredRecord<T extends Comparable<T>> implements Identifiable, Comparable<ScoredRecord<T>> {
- String id;
- ManagementNodeSyncRecord record;
- T score;
-
- @Override
- public String getId() {
- return id;
- }
-
- @Override
- public int compareTo(ScoredRecord<T> o) {
- return score.compareTo(o.score);
- }
- }
-
- public ManagementNodeSyncRecord choose(ManagementPlaneSyncRecord memento, Duration heartbeatTimeout, String ownNodeId) {
- if (LOG.isDebugEnabled()) LOG.debug("Choosing new master from "+memento.getManagementNodes());
- ManagementNodeSyncRecord me = memento.getManagementNodes().get(ownNodeId);
- if (me==null) {
- LOG.warn("Management node details not known when choosing new master: "+memento+" / "+ownNodeId);
- return null;
- }
- Long nowIsh = me.getRemoteTimestamp();
- if (nowIsh==null) {
- LOG.warn("Management node for self missing timestamp when choosing new master: "+memento);
- return null;
- }
-
- List<ScoredRecord<?>> contenders = filterHealthy(memento, heartbeatTimeout, nowIsh);
-
- if (!contenders.isEmpty()) {
- return pick(contenders);
- } else {
- LOG.info("No valid management node found for choosing new master: contender="+memento.getManagementNodes());
- return null;
- }
- }
-
- /** pick the best contender; argument guaranteed to be non-null and non-empty,
- * filtered for health reasons */
- @SuppressWarnings({ "rawtypes", "unchecked" })
- protected ManagementNodeSyncRecord pick(List<ScoredRecord<?>> contenders) {
- ScoredRecord min = null;
- for (ScoredRecord x: contenders) {
- if (min==null || x.score.compareTo(min.score)<0) min = x;
- }
- return min.record;
- }
-
- public static class AlphabeticChooserScore implements Comparable<AlphabeticChooserScore> {
- long priority;
- int versionBias;
- String brooklynVersion;
- int statePriority;
- String nodeId;
-
- @Override
- public int compareTo(AlphabeticChooserScore o) {
- if (o==null) return -1;
- return ComparisonChain.start()
- // invert the order where we prefer higher values
- .compare(o.priority, this.priority)
- .compare(o.versionBias, this.versionBias)
- .compare(o.brooklynVersion, this.brooklynVersion,
- Ordering.from(NaturalOrderComparator.INSTANCE).nullsFirst())
- .compare(o.statePriority, this.statePriority)
- .compare(this.nodeId, o.nodeId, Ordering.usingToString().nullsLast())
- .result();
- }
- }
-
- /** comparator which prefers, in order:
- * <li> higher explicit priority
- * <li> non-snapshot Brooklyn version, then any Brooklyn version, and lastly null version
- * (using {@link NaturalOrderComparator} so e.g. v10 > v3.20 > v3.9 )
- * <li> higher version (null last)
- * <li> node which reports it's master, hot standby, then standby
- * <li> finally (common case): lower (alphabetically) node id
- */
- public static class AlphabeticMasterChooser extends BasicMasterChooser {
- final boolean preferHotStandby;
- public AlphabeticMasterChooser(boolean preferHotStandby) { this.preferHotStandby = preferHotStandby; }
- public AlphabeticMasterChooser() { this.preferHotStandby = true; }
- @Override
- protected AlphabeticChooserScore score(ManagementNodeSyncRecord contender) {
- AlphabeticChooserScore score = new AlphabeticChooserScore();
- score.priority = contender.getPriority()!=null ? contender.getPriority() : 0;
- score.brooklynVersion = contender.getBrooklynVersion();
- score.versionBias = contender.getBrooklynVersion()==null ? -2 :
- contender.getBrooklynVersion().toLowerCase().indexOf("snapshot")>=0 ? -1 :
- 0;
- if (preferHotStandby) {
- // other master should be preferred before we get invoked, but including for good measure
- score.statePriority = contender.getStatus()==ManagementNodeState.MASTER ? 3 :
- contender.getStatus()==ManagementNodeState.HOT_STANDBY ? 2 :
- contender.getStatus()==ManagementNodeState.STANDBY ? 1 : -1;
- } else {
- score.statePriority = 0;
- }
- score.nodeId = contender.getNodeId();
- return score;
- }
- }
-
- /**
- * Filters the {@link ManagementPlaneSyncRecord#getManagementNodes()} to only those in an appropriate state,
- * and with heartbeats that have not timed out.
- */
- protected List<ScoredRecord<?>> filterHealthy(ManagementPlaneSyncRecord memento, Duration heartbeatTimeout, long nowIsh) {
- long oldestAcceptableTimestamp = nowIsh - heartbeatTimeout.toMilliseconds();
- List<ScoredRecord<?>> contenders = MutableList.of();
- for (ManagementNodeSyncRecord contender : memento.getManagementNodes().values()) {
- boolean statusOk = (contender.getStatus() == ManagementNodeState.STANDBY || contender.getStatus() == ManagementNodeState.HOT_STANDBY || contender.getStatus() == ManagementNodeState.MASTER);
- Long remoteTimestamp = contender.getRemoteTimestamp();
- boolean heartbeatOk;
- if (remoteTimestamp==null) {
- throw new IllegalStateException("Missing remote timestamp when performing master election: "+this+" / "+contender);
- // if the above exception happens in some contexts we could either fallback to local, or fail:
-// remoteTimestamp = contender.getLocalTimestamp();
- // or
-// heartbeatOk=false;
- } else {
- heartbeatOk = remoteTimestamp >= oldestAcceptableTimestamp;
- }
- if (statusOk && heartbeatOk) {
- contenders.add(newScoredRecord(contender));
- }
- if (LOG.isTraceEnabled()) LOG.trace("Filtering choices of new master: contender="+contender+"; statusOk="+statusOk+"; heartbeatOk="+heartbeatOk);
- }
- return contenders;
- }
-
- @VisibleForTesting
- //Java 6 compiler workaround, using parameterized types fails
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected List<ScoredRecord<?>> sort(List<ScoredRecord<?>> input) {
- ArrayList copy = new ArrayList<ScoredRecord<?>>(input);
- Collections.sort(copy);
- return copy;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected ScoredRecord<?> newScoredRecord(ManagementNodeSyncRecord contender) {
- ScoredRecord r = new ScoredRecord();
- r.id = contender.getNodeId();
- r.record = contender;
- r.score = score(contender);
- return r;
- }
-
- protected abstract Comparable<?> score(ManagementNodeSyncRecord contender);
-
-}
[08/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java
deleted file mode 100644
index e747a82..0000000
--- a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerSplitBrainTest.java
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
-import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
-import brooklyn.entity.rebind.persister.InMemoryObjectStore;
-import brooklyn.entity.rebind.persister.ListeningObjectStore;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.internal.BrooklynFeatureEnablement;
-import brooklyn.management.ha.TestEntityFailingRebind.RebindException;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.test.Asserts;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Ticker;
-import com.google.common.collect.ImmutableList;
-
-@Test
-public class HighAvailabilityManagerSplitBrainTest {
-
- private static final Logger log = LoggerFactory.getLogger(HighAvailabilityManagerSplitBrainTest.class);
-
- private List<HaMgmtNode> nodes = new MutableList<HighAvailabilityManagerSplitBrainTest.HaMgmtNode>();
- Map<String,String> sharedBackingStore = MutableMap.of();
- Map<String,Date> sharedBackingStoreDates = MutableMap.of();
- private AtomicLong sharedTime; // used to set the ticker's return value
- private ClassLoader classLoader = getClass().getClassLoader();
-
- public class HaMgmtNode {
- // TODO share with HotStandbyTest and WarmStandbyTest and a few others (minor differences but worth it ultimately)
-
- private ManagementContextInternal mgmt;
- private String ownNodeId;
- private String nodeName;
- private ListeningObjectStore objectStore;
- private ManagementPlaneSyncRecordPersister persister;
- private HighAvailabilityManagerImpl ha;
- private Ticker ticker;
- private AtomicLong currentTime; // used to set the ticker's return value
-
- public void setUp() throws Exception {
- if (sharedTime==null)
- currentTime = new AtomicLong(System.currentTimeMillis());
-
- ticker = new Ticker() {
- // strictly not a ticker because returns millis UTC, but it works fine even so
- @Override public long read() {
- if (sharedTime!=null) return sharedTime.get();
- return currentTime.get();
- }
- };
-
- nodeName = "node "+nodes.size();
- mgmt = newLocalManagementContext();
- ownNodeId = mgmt.getManagementNodeId();
- objectStore = new ListeningObjectStore(newPersistenceObjectStore());
- objectStore.injectManagementContext(mgmt);
- objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
- persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
- ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
- BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
- mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
- ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())
- .setPollPeriod(Duration.PRACTICALLY_FOREVER)
- .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
- .setLocalTicker(ticker)
- .setRemoteTicker(ticker)
- .setPersister(persister);
- log.info("Created "+nodeName+" "+ownNodeId);
- }
-
- public void tearDown() throws Exception {
- if (ha != null) ha.stop();
- if (mgmt != null) Entities.destroyAll(mgmt);
- if (objectStore != null) objectStore.deleteCompletely();
- }
-
- private long tickerCurrentMillis() {
- return ticker.read();
- }
-
- private long tickerAdvance(Duration duration) {
- if (sharedTime!=null)
- throw new IllegalStateException("Using shared ticker; cannot advance private node clock");
- currentTime.addAndGet(duration.toMilliseconds());
- return tickerCurrentMillis();
- }
-
- @Override
- public String toString() {
- return nodeName+" "+ownNodeId;
- }
- }
-
- private Boolean prevThrowOnRebind;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- prevThrowOnRebind = TestEntityFailingRebind.getThrowOnRebind();
- TestEntityFailingRebind.setThrowOnRebind(true);
- nodes.clear();
- sharedBackingStore.clear();
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- try {
- for (HaMgmtNode n: nodes)
- n.tearDown();
- } finally {
- if (prevThrowOnRebind != null) TestEntityFailingRebind.setThrowOnRebind(prevThrowOnRebind);
- }
- }
-
- public HaMgmtNode newNode() throws Exception {
- HaMgmtNode node = new HaMgmtNode();
- node.setUp();
- nodes.add(node);
- return node;
- }
-
- private void sharedTickerAdvance(Duration duration) {
- if (sharedTime==null) {
- for (HaMgmtNode n: nodes)
- n.tickerAdvance(duration);
- } else {
- sharedTime.addAndGet(duration.toMilliseconds());
- }
- }
-
- private long sharedTickerCurrentMillis() {
- return sharedTime.get();
- }
-
- protected void useSharedTime() {
- if (!nodes.isEmpty())
- throw new IllegalStateException("shared time must be set up before any nodes created");
- sharedTime = new AtomicLong(System.currentTimeMillis());
- }
-
- protected ManagementContextInternal newLocalManagementContext() {
- return new LocalManagementContextForTests();
- }
-
- protected PersistenceObjectStore newPersistenceObjectStore() {
- return new InMemoryObjectStore(sharedBackingStore, sharedBackingStoreDates);
- }
-
- @Test
- public void testDoubleRebindFails() throws Exception {
- useSharedTime();
- HaMgmtNode n1 = newNode();
- HaMgmtNode n2 = newNode();
-
- // first auto should become master
- n1.ha.start(HighAvailabilityMode.AUTO);
- n2.ha.start(HighAvailabilityMode.AUTO);
- assertEquals(n1.ha.getNodeState(), ManagementNodeState.MASTER);
-
- TestApplication app = ApplicationBuilder.newManagedApp(
- EntitySpec.create(TestApplication.class).impl(TestEntityFailingRebind.class), n1.mgmt);
- app.start(ImmutableList.<Location>of());
-
- n1.mgmt.getRebindManager().forcePersistNow(false, null);
-
- //don't publish state for a while (i.e. long store delays, failures)
- sharedTickerAdvance(Duration.ONE_MINUTE);
-
- try {
- n2.ha.publishAndCheck(false);
- fail("n2 rebind failure expected");
- } catch (Exception e) {
- assertNestedRebindException(e);
- }
-
- // re-check should re-assert successfully, no rebind expected as he was previously master
- n1.ha.publishAndCheck(false);
- ManagementPlaneSyncRecord memento;
- memento = n1.ha.loadManagementPlaneSyncRecord(true);
- assertEquals(memento.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.MASTER);
- assertEquals(memento.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.FAILED);
-
- // hot backup permitted by the TestEntityFailingRebind
- n1.ha.changeMode(HighAvailabilityMode.HOT_BACKUP);
- memento = n1.ha.loadManagementPlaneSyncRecord(true);
- assertEquals(memento.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.HOT_BACKUP);
- try {
- n1.ha.changeMode(HighAvailabilityMode.MASTER);
- fail("n1 rebind failure expected");
- } catch (Exception e) {
- assertNestedRebindException(e);
- }
-
- memento = n1.ha.loadManagementPlaneSyncRecord(true);
- assertEquals(memento.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.FAILED);
- assertEquals(memento.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.FAILED);
- }
-
- @Test
- public void testStandbyRebind() throws Exception {
- useSharedTime();
- HaMgmtNode n1 = newNode();
- HaMgmtNode n2 = newNode();
-
- // first auto should become master
- n1.ha.start(HighAvailabilityMode.AUTO);
- n2.ha.start(HighAvailabilityMode.AUTO);
-
- TestApplication app = ApplicationBuilder.newManagedApp(
- EntitySpec.create(TestApplication.class).impl(TestEntityFailingRebind.class), n1.mgmt);
- app.start(ImmutableList.<Location>of());
-
- n1.mgmt.getRebindManager().forcePersistNow(false, null);
-
- //don't publish state for a while (i.e. long store delays, failures)
- sharedTickerAdvance(Duration.ONE_MINUTE);
-
- try {
- n2.ha.publishAndCheck(false);
- fail("n2 rebind failure expected");
- } catch (Exception e) {
- assertNestedRebindException(e);
- }
-
- TestEntityFailingRebind.setThrowOnRebind(false);
- n1.ha.publishAndCheck(false);
-
- ManagementPlaneSyncRecord memento = n1.ha.loadManagementPlaneSyncRecord(true);
- assertEquals(memento.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.MASTER);
- assertEquals(memento.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.FAILED);
- }
-
- private void assertNestedRebindException(Throwable t) {
- Throwable ptr = t;
- while (ptr != null) {
- if (ptr instanceof RebindException) {
- return;
- }
- ptr = ptr.getCause();
- }
- Exceptions.propagate(t);
- }
-
- @Test
- public void testIfNodeStopsBeingAbleToWrite() throws Exception {
- useSharedTime();
- log.info("time at start "+sharedTickerCurrentMillis());
-
- HaMgmtNode n1 = newNode();
- HaMgmtNode n2 = newNode();
-
- // first auto should become master
- n1.ha.start(HighAvailabilityMode.AUTO);
- ManagementPlaneSyncRecord memento1 = n1.ha.loadManagementPlaneSyncRecord(true);
-
- log.info(n1+" HA: "+memento1);
- assertEquals(memento1.getMasterNodeId(), n1.ownNodeId);
- Long time0 = sharedTickerCurrentMillis();
- assertEquals(memento1.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time0);
- assertEquals(memento1.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.MASTER);
-
- // second - make explicit hot; that's a strictly more complex case than cold standby, so provides pretty good coverage
- n2.ha.start(HighAvailabilityMode.HOT_STANDBY);
- ManagementPlaneSyncRecord memento2 = n2.ha.loadManagementPlaneSyncRecord(true);
-
- log.info(n2+" HA: "+memento2);
- assertEquals(memento2.getMasterNodeId(), n1.ownNodeId);
- assertEquals(memento2.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.MASTER);
- assertEquals(memento2.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.HOT_STANDBY);
- assertEquals(memento2.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time0);
- assertEquals(memento2.getManagementNodes().get(n2.ownNodeId).getRemoteTimestamp(), time0);
-
- // and no entities at either
- assertEquals(n1.mgmt.getApplications().size(), 0);
- assertEquals(n2.mgmt.getApplications().size(), 0);
-
- // create
- TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class), n1.mgmt);
- app.start(ImmutableList.<Location>of());
- app.setAttribute(TestApplication.MY_ATTRIBUTE, "hello");
-
- assertEquals(n1.mgmt.getApplications().size(), 1);
- assertEquals(n2.mgmt.getApplications().size(), 0);
- log.info("persisting "+n1.ownNodeId);
- n1.mgmt.getRebindManager().forcePersistNow(false, null);
-
- n1.objectStore.setWritesFailSilently(true);
- log.info(n1+" writes off");
- sharedTickerAdvance(Duration.ONE_MINUTE);
- log.info("time now "+sharedTickerCurrentMillis());
- Long time1 = sharedTickerCurrentMillis();
-
- log.info("publish "+n2.ownNodeId);
- n2.ha.publishAndCheck(false);
- ManagementPlaneSyncRecord memento2b = n2.ha.loadManagementPlaneSyncRecord(true);
- log.info(n2+" HA now: "+memento2b);
-
- // n2 infers n1 as failed
- assertEquals(memento2b.getManagementNodes().get(n1.ownNodeId).getStatus(), ManagementNodeState.FAILED);
- assertEquals(memento2b.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.MASTER);
- assertEquals(memento2b.getMasterNodeId(), n2.ownNodeId);
- assertEquals(memento2b.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time0);
- assertEquals(memento2b.getManagementNodes().get(n2.ownNodeId).getRemoteTimestamp(), time1);
-
- assertEquals(n1.mgmt.getApplications().size(), 1);
- assertEquals(n2.mgmt.getApplications().size(), 1);
- assertEquals(n1.mgmt.getApplications().iterator().next().getAttribute(TestApplication.MY_ATTRIBUTE), "hello");
-
- n1.objectStore.setWritesFailSilently(false);
- log.info(n1+" writes on");
-
- sharedTickerAdvance(Duration.ONE_SECOND);
- log.info("time now "+sharedTickerCurrentMillis());
- Long time2 = sharedTickerCurrentMillis();
-
- log.info("publish "+n1.ownNodeId);
- n1.ha.publishAndCheck(false);
- ManagementPlaneSyncRecord memento1b = n1.ha.loadManagementPlaneSyncRecord(true);
- log.info(n1+" HA now: "+memento1b);
-
- ManagementNodeState expectedStateAfterDemotion = BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY) ?
- ManagementNodeState.HOT_STANDBY : ManagementNodeState.STANDBY;
-
- // n1 comes back and demotes himself
- assertEquals(memento1b.getManagementNodes().get(n1.ownNodeId).getStatus(), expectedStateAfterDemotion);
- assertEquals(memento1b.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.MASTER);
- assertEquals(memento1b.getMasterNodeId(), n2.ownNodeId);
- assertEquals(memento1b.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time2);
- assertEquals(memento1b.getManagementNodes().get(n2.ownNodeId).getRemoteTimestamp(), time1);
-
- // n2 now sees itself as master, with n1 in standby again
- ManagementPlaneSyncRecord memento2c = n2.ha.loadManagementPlaneSyncRecord(true);
- log.info(n2+" HA now: "+memento2c);
- assertEquals(memento2c.getManagementNodes().get(n1.ownNodeId).getStatus(), expectedStateAfterDemotion);
- assertEquals(memento2c.getManagementNodes().get(n2.ownNodeId).getStatus(), ManagementNodeState.MASTER);
- assertEquals(memento2c.getMasterNodeId(), n2.ownNodeId);
- assertEquals(memento2c.getManagementNodes().get(n1.ownNodeId).getRemoteTimestamp(), time2);
- assertEquals(memento2c.getManagementNodes().get(n2.ownNodeId).getRemoteTimestamp(), time2);
-
- // right number of entities at n2; n1 may or may not depending whether hot standby is default
- assertEquals(n2.mgmt.getApplications().size(), 1);
- assertEquals(n1.mgmt.getApplications().size(), BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY) ? 1 : 0);
- }
-
- @Test(invocationCount=50, groups="Integration")
- public void testIfNodeStopsBeingAbleToWriteManyTimes() throws Exception {
- testIfNodeStopsBeingAbleToWrite();
- }
-
- @Test
- public void testSimultaneousStartup() throws Exception {
- doTestConcurrentStartup(5, null);
- }
-
- @Test
- public void testNearSimultaneousStartup() throws Exception {
- doTestConcurrentStartup(20, Duration.millis(20));
- }
-
- @Test(invocationCount=50, groups="Integration")
- public void testNearSimultaneousStartupManyTimes() throws Exception {
- doTestConcurrentStartup(20, Duration.millis(20));
- }
-
- protected void doTestConcurrentStartup(int size, final Duration staggerStart) throws Exception {
- useSharedTime();
-
- List<Thread> spawned = MutableList.of();
- for (int i=0; i<size; i++) {
- final HaMgmtNode n = newNode();
- Thread t = new Thread() { public void run() {
- if (staggerStart!=null) Time.sleep(staggerStart.multiply(Math.random()));
- n.ha.start(HighAvailabilityMode.AUTO);
- n.ha.setPollPeriod(Duration.millis(20));
- } };
- spawned.add(t);
- t.start();
- }
-
- try {
- final Stopwatch timer = Stopwatch.createStarted();
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- ManagementPlaneSyncRecord memento = nodes.get(0).ha.loadManagementPlaneSyncRecord(true);
- List<ManagementNodeState> counts = MutableList.of(), savedCounts = MutableList.of();
- for (HaMgmtNode n: nodes) {
- counts.add(n.ha.getNodeState());
- ManagementNodeSyncRecord m = memento.getManagementNodes().get(n.ownNodeId);
- if (m!=null) {
- savedCounts.add(m.getStatus());
- }
- }
- log.info("while starting "+nodes.size()+" nodes: "
- +Collections.frequency(counts, ManagementNodeState.MASTER)+" M + "
- +Collections.frequency(counts, ManagementNodeState.HOT_STANDBY)+" hot + "
- +Collections.frequency(counts, ManagementNodeState.STANDBY)+" warm + "
- +Collections.frequency(counts, ManagementNodeState.INITIALIZING)+" init; "
- + memento.getManagementNodes().size()+" saved, "
- +Collections.frequency(savedCounts, ManagementNodeState.MASTER)+" M + "
- +Collections.frequency(savedCounts, ManagementNodeState.HOT_STANDBY)+" hot + "
- +Collections.frequency(savedCounts, ManagementNodeState.STANDBY)+" warm + "
- +Collections.frequency(savedCounts, ManagementNodeState.INITIALIZING)+" init");
-
- if (timer.isRunning() && Duration.of(timer).compareTo(Duration.TEN_SECONDS)>0) {
- log.warn("we seem to have a problem stabilizing"); //handy place to set a suspend-VM breakpoint!
- timer.stop();
- }
- assertEquals(Collections.frequency(counts, ManagementNodeState.MASTER), 1);
- assertEquals(Collections.frequency(counts, ManagementNodeState.HOT_STANDBY)+Collections.frequency(counts, ManagementNodeState.STANDBY), nodes.size()-1);
- assertEquals(Collections.frequency(savedCounts, ManagementNodeState.MASTER), 1);
- assertEquals(Collections.frequency(savedCounts, ManagementNodeState.HOT_STANDBY)+Collections.frequency(savedCounts, ManagementNodeState.STANDBY), nodes.size()-1);
- }});
- } catch (Throwable t) {
- log.warn("Failed to stabilize (rethrowing): "+t, t);
- throw Exceptions.propagate(t);
- }
-
- for (Thread t: spawned)
- t.join(Duration.THIRTY_SECONDS.toMilliseconds());
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java
deleted file mode 100644
index 57a5d2e..0000000
--- a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerTestFixture.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.BrooklynVersion;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
-import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
-import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord.Builder;
-import brooklyn.management.ha.HighAvailabilityManagerImpl.PromotionListener;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.test.Asserts;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Ticker;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-
-@Test
-public abstract class HighAvailabilityManagerTestFixture {
-
- @SuppressWarnings("unused")
- private static final Logger log = LoggerFactory.getLogger(HighAvailabilityManagerTestFixture.class);
-
- private ManagementPlaneSyncRecordPersister persister;
- protected ManagementContextInternal managementContext;
- private String ownNodeId;
- private HighAvailabilityManagerImpl manager;
- private Ticker ticker;
- private AtomicLong currentTime; // used to set the ticker's return value
- private RecordingPromotionListener promotionListener;
- private ClassLoader classLoader = getClass().getClassLoader();
- private PersistenceObjectStore objectStore;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- currentTime = new AtomicLong(1000000000L);
- ticker = new Ticker() {
- // strictly not a ticker because returns millis UTC, but it works fine even so
- @Override public long read() {
- return currentTime.get();
- }
- };
- promotionListener = new RecordingPromotionListener();
- managementContext = newLocalManagementContext();
- ownNodeId = managementContext.getManagementNodeId();
- objectStore = newPersistenceObjectStore();
- objectStore.injectManagementContext(managementContext);
- objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
- persister = new ManagementPlaneSyncRecordPersisterToObjectStore(managementContext, objectStore, classLoader);
- ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
- BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(
- objectStore,
- managementContext.getBrooklynProperties(),
- classLoader);
- managementContext.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
- manager = ((HighAvailabilityManagerImpl)managementContext.getHighAvailabilityManager())
- .setPollPeriod(getPollPeriod())
- .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
- .setPromotionListener(promotionListener)
- .setLocalTicker(ticker)
- .setRemoteTicker(getRemoteTicker())
- .setPersister(persister);
- persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
- .node(newManagerMemento(ownNodeId, ManagementNodeState.HOT_STANDBY))
- .build());
-
- }
-
- protected ManagementContextInternal newLocalManagementContext() {
- return LocalManagementContextForTests.newInstance();
- }
-
- protected abstract PersistenceObjectStore newPersistenceObjectStore();
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- if (manager != null) manager.stop();
- if (managementContext != null) Entities.destroyAll(managementContext);
- if (objectStore != null) objectStore.deleteCompletely();
- }
-
- // The web-console could still be polling (e.g. if have just restarted brooklyn), before the persister is set.
- // Must not throw NPE, but instead return something sensible (e.g. an empty state record).
- @Test
- public void testGetManagementPlaneSyncStateDoesNotThrowNpeBeforePersisterSet() throws Exception {
- HighAvailabilityManagerImpl manager2 = new HighAvailabilityManagerImpl(managementContext)
- .setPollPeriod(Duration.millis(10))
- .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
- .setPromotionListener(promotionListener)
- .setLocalTicker(ticker)
- .setRemoteTicker(ticker);
- try {
- ManagementPlaneSyncRecord state = manager2.loadManagementPlaneSyncRecord(true);
- assertNotNull(state);
- } finally {
- manager2.stop();
- }
-
- }
- // Can get a log.error about our management node's heartbeat being out of date. Caused by
- // poller first writing a heartbeat record, and then the clock being incremented. But the
- // next poll fixes it.
- public void testPromotes() throws Exception {
- persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
- .node(newManagerMemento(ownNodeId, ManagementNodeState.HOT_STANDBY))
- .node(newManagerMemento("node1", ManagementNodeState.MASTER))
- .setMaster("node1")
- .build());
-
- manager.start(HighAvailabilityMode.AUTO);
-
- // Simulate passage of time; ticker used by this HA-manager so it will "correctly" publish
- // its own heartbeat with the new time; but node1's record is now out-of-date.
- tickerAdvance(Duration.seconds(31));
-
- // Expect to be notified of our promotion, as the only other node
- promotionListener.assertCalledEventually();
- }
-
- @Test(groups="Integration") // because one second wait in succeedsContinually
- public void testDoesNotPromoteIfMasterTimeoutNotExpired() throws Exception {
- persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
- .node(newManagerMemento(ownNodeId, ManagementNodeState.HOT_STANDBY))
- .node(newManagerMemento("node1", ManagementNodeState.MASTER))
- .setMaster("node1")
- .build());
-
- manager.start(HighAvailabilityMode.AUTO);
-
- tickerAdvance(Duration.seconds(25));
-
- // Expect not to be notified, as 25s < 30s timeout
- // (it's normally a fake clock so won't hit 30, even waiting 1s below - but in "IntegrationTest" subclasses it is real!)
- Asserts.succeedsContinually(new Runnable() {
- @Override public void run() {
- assertTrue(promotionListener.callTimestamps.isEmpty(), "calls="+promotionListener.callTimestamps);
- }});
- }
-
- public void testGetManagementPlaneStatus() throws Exception {
- // with the name zzzzz the mgr created here should never be promoted by the alphabetical strategy!
-
- tickerAdvance(Duration.FIVE_SECONDS);
- persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
- .node(newManagerMemento(ownNodeId, ManagementNodeState.STANDBY))
- .node(newManagerMemento("zzzzzzz_node1", ManagementNodeState.STANDBY))
- .build());
- persister.loadSyncRecord();
- long zzzTime = tickerCurrentMillis();
- tickerAdvance(Duration.FIVE_SECONDS);
-
- manager.start(HighAvailabilityMode.AUTO);
- ManagementPlaneSyncRecord memento = manager.loadManagementPlaneSyncRecord(true);
-
- // Note can assert timestamp because not "real" time; it's using our own Ticker
- assertEquals(memento.getMasterNodeId(), ownNodeId);
- assertEquals(memento.getManagementNodes().keySet(), ImmutableSet.of(ownNodeId, "zzzzzzz_node1"));
- assertEquals(memento.getManagementNodes().get(ownNodeId).getNodeId(), ownNodeId);
- assertEquals(memento.getManagementNodes().get(ownNodeId).getStatus(), ManagementNodeState.MASTER);
- assertEquals(memento.getManagementNodes().get(ownNodeId).getLocalTimestamp(), tickerCurrentMillis());
- assertEquals(memento.getManagementNodes().get("zzzzzzz_node1").getNodeId(), "zzzzzzz_node1");
- assertEquals(memento.getManagementNodes().get("zzzzzzz_node1").getStatus(), ManagementNodeState.STANDBY);
- assertEquals(memento.getManagementNodes().get("zzzzzzz_node1").getLocalTimestamp(), zzzTime);
- }
-
- @Test(groups="Integration", invocationCount=50) //because we have had non-deterministic failures
- public void testGetManagementPlaneStatusManyTimes() throws Exception {
- testGetManagementPlaneStatus();
- }
-
- @Test
- public void testGetManagementPlaneSyncStateInfersTimedOutNodeAsFailed() throws Exception {
- persister.delta(ManagementPlaneSyncRecordDeltaImpl.builder()
- .node(newManagerMemento(ownNodeId, ManagementNodeState.HOT_STANDBY))
- .node(newManagerMemento("node1", ManagementNodeState.MASTER))
- .setMaster("node1")
- .build());
-
- manager.start(HighAvailabilityMode.HOT_STANDBY);
-
- ManagementPlaneSyncRecord state = manager.loadManagementPlaneSyncRecord(true);
- assertEquals(state.getManagementNodes().get("node1").getStatus(), ManagementNodeState.MASTER);
- assertEquals(state.getManagementNodes().get(ownNodeId).getStatus(), ManagementNodeState.HOT_STANDBY);
-
- // Simulate passage of time; ticker used by this HA-manager so it will "correctly" publish
- // its own heartbeat with the new time; but node1's record is now out-of-date.
- tickerAdvance(Duration.seconds(31));
-
- ManagementPlaneSyncRecord state2 = manager.loadManagementPlaneSyncRecord(true);
- assertEquals(state2.getManagementNodes().get("node1").getStatus(), ManagementNodeState.FAILED);
- assertNotEquals(state.getManagementNodes().get(ownNodeId).getStatus(), ManagementNodeState.FAILED);
- }
-
- protected Duration getPollPeriod() {
- return Duration.millis(10);
- }
-
- protected long tickerCurrentMillis() {
- return ticker.read();
- }
-
- protected long tickerAdvance(Duration duration) {
- currentTime.addAndGet(duration.toMilliseconds());
- return tickerCurrentMillis();
- }
-
- protected Ticker getRemoteTicker() {
- return ticker;
- }
-
- protected ManagementNodeSyncRecord newManagerMemento(String nodeId, ManagementNodeState status) {
- Builder rb = BasicManagementNodeSyncRecord.builder();
- rb.brooklynVersion(BrooklynVersion.get()).nodeId(nodeId).status(status);
- rb.localTimestamp(tickerCurrentMillis());
- if (getRemoteTicker()!=null)
- rb.remoteTimestamp(getRemoteTicker().read());
- return rb.build();
- }
-
- public static class RecordingPromotionListener implements PromotionListener {
- public final List<Long> callTimestamps = Lists.newCopyOnWriteArrayList();
-
- @Override
- public void promotingToMaster() {
- callTimestamps.add(System.currentTimeMillis());
- }
-
- public void assertNotCalled() {
- assertTrue(callTimestamps.isEmpty(), "calls="+callTimestamps);
- }
-
- public void assertCalled() {
- assertFalse(callTimestamps.isEmpty(), "calls="+callTimestamps);
- }
-
- public void assertCalledEventually() {
- Asserts.succeedsEventually(new Runnable() {
- @Override public void run() {
- assertCalled();
- }});
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/HotStandbyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HotStandbyTest.java b/core/src/test/java/brooklyn/management/ha/HotStandbyTest.java
deleted file mode 100644
index f061289..0000000
--- a/core/src/test/java/brooklyn/management/ha/HotStandbyTest.java
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import java.util.ArrayDeque;
-import java.util.Date;
-import java.util.Deque;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.Feed;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
-import org.apache.brooklyn.test.EntityTestUtils;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.apache.brooklyn.test.entity.TestEntity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
-import brooklyn.entity.rebind.RebindFeedTest.MyEntityWithFunctionFeedImpl;
-import brooklyn.entity.rebind.RebindFeedTest.MyEntityWithNewFeedsEachTimeImpl;
-import brooklyn.entity.rebind.RebindManagerImpl;
-import brooklyn.entity.rebind.RebindTestFixture;
-import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
-import brooklyn.entity.rebind.persister.InMemoryObjectStore;
-import brooklyn.entity.rebind.persister.ListeningObjectStore;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-
-import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation.LocalhostMachine;
-
-import brooklyn.management.internal.AbstractManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.repeat.Repeater;
-import brooklyn.util.text.ByteSizeStrings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.collect.Iterables;
-
-public class HotStandbyTest {
-
- private static final Logger log = LoggerFactory.getLogger(HotStandbyTest.class);
-
- private List<HaMgmtNode> nodes = new MutableList<HotStandbyTest.HaMgmtNode>();
- Map<String,String> sharedBackingStore = MutableMap.of();
- Map<String,Date> sharedBackingStoreDates = MutableMap.of();
- private ClassLoader classLoader = getClass().getClassLoader();
-
- public class HaMgmtNode {
- // TODO share with WarmStandbyTest and SplitBrainTest and a few others (minor differences but worth it ultimately)
-
- private ManagementContextInternal mgmt;
- private String ownNodeId;
- private String nodeName;
- private ListeningObjectStore objectStore;
- private ManagementPlaneSyncRecordPersister persister;
- private HighAvailabilityManagerImpl ha;
- private Duration persistOrRebindPeriod = Duration.ONE_SECOND;
-
- public void setUp() throws Exception {
- nodeName = "node "+nodes.size();
- mgmt = newLocalManagementContext();
- ownNodeId = mgmt.getManagementNodeId();
- objectStore = new ListeningObjectStore(newPersistenceObjectStore());
- objectStore.injectManagementContext(mgmt);
- objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
- persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
- ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
- BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
- ((RebindManagerImpl)mgmt.getRebindManager()).setPeriodicPersistPeriod(persistOrRebindPeriod);
- mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
- ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())
- .setPollPeriod(Duration.PRACTICALLY_FOREVER)
- .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
- .setPersister(persister);
- log.info("Created "+nodeName+" "+ownNodeId);
- }
-
- public void tearDownThisOnly() throws Exception {
- if (ha != null) ha.stop();
- if (mgmt!=null) mgmt.getRebindManager().stop();
- if (mgmt != null) Entities.destroyAll(mgmt);
- }
-
- public void tearDownAll() throws Exception {
- tearDownThisOnly();
- // can't delete the object store until all being torn down
- if (objectStore != null) objectStore.deleteCompletely();
- }
-
- @Override
- public String toString() {
- return nodeName+" "+ownNodeId;
- }
-
- public RebindManagerImpl rebinder() {
- return (RebindManagerImpl)mgmt.getRebindManager();
- }
- }
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- nodes.clear();
- sharedBackingStore.clear();
- }
-
- public HaMgmtNode newNode(Duration persistOrRebindPeriod) throws Exception {
- HaMgmtNode node = new HaMgmtNode();
- node.persistOrRebindPeriod = persistOrRebindPeriod;
- node.setUp();
- nodes.add(node);
- return node;
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- for (HaMgmtNode n: nodes)
- n.tearDownAll();
- }
-
- protected ManagementContextInternal newLocalManagementContext() {
- return new LocalManagementContextForTests();
- }
-
- protected PersistenceObjectStore newPersistenceObjectStore() {
- return new InMemoryObjectStore(sharedBackingStore, sharedBackingStoreDates);
- }
-
- private HaMgmtNode createMaster(Duration persistOrRebindPeriod) throws Exception {
- HaMgmtNode n1 = newNode(persistOrRebindPeriod);
- n1.ha.start(HighAvailabilityMode.AUTO);
- assertEquals(n1.ha.getNodeState(), ManagementNodeState.MASTER);
- return n1;
- }
-
- private HaMgmtNode createHotStandby(Duration rebindPeriod) throws Exception {
- HaMgmtNode n2 = newNode(rebindPeriod);
- n2.ha.start(HighAvailabilityMode.HOT_STANDBY);
- assertEquals(n2.ha.getNodeState(), ManagementNodeState.HOT_STANDBY);
- return n2;
- }
-
- private TestApplication createFirstAppAndPersist(HaMgmtNode n1) throws Exception {
- TestApplication app = TestApplication.Factory.newManagedInstanceForTests(n1.mgmt);
- // for testing without enrichers, if desired:
-// TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).impl(TestApplicationNoEnrichersImpl.class), n1.mgmt);
- app.setDisplayName("First App");
- app.start(MutableList.<Location>of());
- app.config().set(TestEntity.CONF_NAME, "first-app");
- app.setAttribute(TestEntity.SEQUENCE, 3);
-
- forcePersistNow(n1);
- return app;
- }
-
- protected void forcePersistNow(HaMgmtNode n1) {
- n1.mgmt.getRebindManager().forcePersistNow(false, null);
- }
-
- private Application expectRebindSequenceNumber(HaMgmtNode master, HaMgmtNode hotStandby, Application app, int expectedSensorSequenceValue, boolean immediate) {
- Application appRO = hotStandby.mgmt.lookup(app.getId(), Application.class);
-
- if (immediate) {
- forcePersistNow(master);
- forceRebindNow(hotStandby);
- EntityTestUtils.assertAttributeEquals(appRO, TestEntity.SEQUENCE, expectedSensorSequenceValue);
- } else {
- EntityTestUtils.assertAttributeEqualsEventually(appRO, TestEntity.SEQUENCE, expectedSensorSequenceValue);
- }
-
- log.info("got sequence number "+expectedSensorSequenceValue+" from "+appRO);
-
- // make sure the instance (proxy) is unchanged
- Application appRO2 = hotStandby.mgmt.lookup(app.getId(), Application.class);
- Assert.assertTrue(appRO2==appRO);
-
- return appRO;
- }
-
- private void forceRebindNow(HaMgmtNode hotStandby) {
- hotStandby.mgmt.getRebindManager().rebind(null, null, ManagementNodeState.HOT_STANDBY);
- }
-
- @Test
- public void testHotStandbySeesInitialCustomNameConfigAndSensorValueButDoesntAllowChange() throws Exception {
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- TestApplication app = createFirstAppAndPersist(n1);
- HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
-
- assertEquals(n2.mgmt.getApplications().size(), 1);
- Application appRO = n2.mgmt.lookup(app.getId(), Application.class);
- Assert.assertNotNull(appRO);
- Assert.assertTrue(appRO instanceof TestApplication);
- assertEquals(appRO.getDisplayName(), "First App");
- assertEquals(appRO.getConfig(TestEntity.CONF_NAME), "first-app");
- assertEquals(appRO.getAttribute(TestEntity.SEQUENCE), (Integer)3);
-
- try {
- ((TestApplication)appRO).setAttribute(TestEntity.SEQUENCE, 4);
- Assert.fail("Should not have allowed sensor to be set");
- } catch (Exception e) {
- Assert.assertTrue(e.toString().toLowerCase().contains("read-only"), "Error message did not contain expected text: "+e);
- }
- assertEquals(appRO.getAttribute(TestEntity.SEQUENCE), (Integer)3);
- }
-
- @Test
- public void testHotStandbySeesChangesToNameConfigAndSensorValue() throws Exception {
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- TestApplication app = createFirstAppAndPersist(n1);
- HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
-
- assertEquals(n2.mgmt.getApplications().size(), 1);
- Application appRO = n2.mgmt.lookup(app.getId(), Application.class);
- Assert.assertNotNull(appRO);
- assertEquals(appRO.getChildren().size(), 0);
-
- // test changes
-
- app.setDisplayName("First App Renamed");
- app.config().set(TestEntity.CONF_NAME, "first-app-renamed");
- app.setAttribute(TestEntity.SEQUENCE, 4);
-
- appRO = expectRebindSequenceNumber(n1, n2, app, 4, true);
- assertEquals(n2.mgmt.getEntityManager().getEntities().size(), 1);
- assertEquals(appRO.getDisplayName(), "First App Renamed");
- assertEquals(appRO.getConfig(TestEntity.CONF_NAME), "first-app-renamed");
-
- // and change again for good measure!
-
- app.setDisplayName("First App");
- app.config().set(TestEntity.CONF_NAME, "first-app-restored");
- app.setAttribute(TestEntity.SEQUENCE, 5);
-
- appRO = expectRebindSequenceNumber(n1, n2, app, 5, true);
- assertEquals(n2.mgmt.getEntityManager().getEntities().size(), 1);
- assertEquals(appRO.getDisplayName(), "First App");
- assertEquals(appRO.getConfig(TestEntity.CONF_NAME), "first-app-restored");
- }
-
-
- public void testHotStandbySeesStructuralChangesIncludingRemoval() throws Exception {
- doTestHotStandbySeesStructuralChangesIncludingRemoval(true);
- }
-
- @Test(groups="Integration") // due to time (it waits for background persistence)
- public void testHotStandbyUnforcedSeesStructuralChangesIncludingRemoval() throws Exception {
- doTestHotStandbySeesStructuralChangesIncludingRemoval(false);
- }
-
- public void doTestHotStandbySeesStructuralChangesIncludingRemoval(boolean immediate) throws Exception {
- HaMgmtNode n1 = createMaster(immediate ? Duration.PRACTICALLY_FOREVER : Duration.millis(200));
- TestApplication app = createFirstAppAndPersist(n1);
- HaMgmtNode n2 = createHotStandby(immediate ? Duration.PRACTICALLY_FOREVER : Duration.millis(200));
-
- assertEquals(n2.mgmt.getApplications().size(), 1);
- Application appRO = n2.mgmt.lookup(app.getId(), Application.class);
- Assert.assertNotNull(appRO);
- assertEquals(appRO.getChildren().size(), 0);
-
- // test additions - new child, new app
-
- TestEntity child = app.addChild(EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, "first-child"));
- Entities.manage(child);
- TestApplication app2 = TestApplication.Factory.newManagedInstanceForTests(n1.mgmt);
- app2.config().set(TestEntity.CONF_NAME, "second-app");
-
- app.setAttribute(TestEntity.SEQUENCE, 4);
- appRO = expectRebindSequenceNumber(n1, n2, app, 4, immediate);
-
- assertEquals(appRO.getChildren().size(), 1);
- Entity childRO = Iterables.getOnlyElement(appRO.getChildren());
- assertEquals(childRO.getId(), child.getId());
- assertEquals(childRO.getConfig(TestEntity.CONF_NAME), "first-child");
-
- assertEquals(n2.mgmt.getApplications().size(), 2);
- Application app2RO = n2.mgmt.lookup(app2.getId(), Application.class);
- Assert.assertNotNull(app2RO);
- assertEquals(app2RO.getConfig(TestEntity.CONF_NAME), "second-app");
-
- assertEquals(n2.mgmt.getEntityManager().getEntities().size(), 3);
-
- // now test removals
-
- Entities.unmanage(child);
- Entities.unmanage(app2);
-
- app.setAttribute(TestEntity.SEQUENCE, 5);
- appRO = expectRebindSequenceNumber(n1, n2, app, 5, immediate);
-
- EntityTestUtils.assertAttributeEqualsEventually(appRO, TestEntity.SEQUENCE, 5);
- assertEquals(n2.mgmt.getEntityManager().getEntities().size(), 1);
- assertEquals(appRO.getChildren().size(), 0);
- assertEquals(n2.mgmt.getApplications().size(), 1);
- Assert.assertNull(n2.mgmt.lookup(app2.getId(), Application.class));
- Assert.assertNull(n2.mgmt.lookup(child.getId(), Application.class));
- }
-
- @Test(groups="Integration", invocationCount=50)
- public void testHotStandbySeesStructuralChangesIncludingRemovalManyTimes() throws Exception {
- doTestHotStandbySeesStructuralChangesIncludingRemoval(true);
- }
-
- Deque<Long> usedMemory = new ArrayDeque<Long>();
- protected long noteUsedMemory(String message) {
- Time.sleep(Duration.millis(200));
- for (HaMgmtNode n: nodes) {
- ((AbstractManagementContext)n.mgmt).getGarbageCollector().gcIteration();
- }
- System.gc(); System.gc();
- Time.sleep(Duration.millis(50));
- System.gc(); System.gc();
- long mem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
- usedMemory.addLast(mem);
- log.info("Memory used - "+message+": "+ByteSizeStrings.java().apply(mem));
- return mem;
- }
- public void assertUsedMemoryLessThan(String event, long max) {
- noteUsedMemory(event);
- long nowUsed = usedMemory.peekLast();
- if (nowUsed > max) {
- // aggressively try to force GC
- Time.sleep(Duration.ONE_SECOND);
- usedMemory.removeLast();
- noteUsedMemory(event+" (extra GC)");
- nowUsed = usedMemory.peekLast();
- if (nowUsed > max) {
- Assert.fail("Too much memory used - "+ByteSizeStrings.java().apply(nowUsed)+" > max "+ByteSizeStrings.java().apply(max));
- }
- }
- }
- public void assertUsedMemoryMaxDelta(String event, long deltaMegabytes) {
- assertUsedMemoryLessThan(event, usedMemory.peekLast() + deltaMegabytes*1024*1024);
- }
-
- @Test(groups="Integration")
- public void testHotStandbyDoesNotLeakLotsOfRebinds() throws Exception {
- log.info("Starting test "+JavaClassNames.niceClassAndMethod());
- final int DELTA = 2;
-
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- TestApplication app = createFirstAppAndPersist(n1);
- long initialUsed = noteUsedMemory("Created app");
-
- HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
- assertUsedMemoryMaxDelta("Standby created", DELTA);
-
- forcePersistNow(n1);
- forceRebindNow(n2);
- assertUsedMemoryMaxDelta("Persisted and rebinded once", DELTA);
-
- for (int i=0; i<10; i++) {
- forcePersistNow(n1);
- forceRebindNow(n2);
- }
- assertUsedMemoryMaxDelta("Persisted and rebinded 10x", DELTA);
-
- for (int i=0; i<1000; i++) {
- if ((i+1)%100==0) {
- noteUsedMemory("iteration "+(i+1));
- usedMemory.removeLast();
- }
- forcePersistNow(n1);
- forceRebindNow(n2);
- }
- assertUsedMemoryMaxDelta("Persisted and rebinded 1000x", DELTA);
-
- Entities.unmanage(app);
- forcePersistNow(n1);
- forceRebindNow(n2);
-
- assertUsedMemoryLessThan("And now all unmanaged", initialUsed + DELTA*1000*1000);
- }
-
- static class BigObject {
- public BigObject(int sizeBytes) { array = new byte[sizeBytes]; }
- byte[] array;
- }
-
- @Test(groups="Integration")
- public void testHotStandbyDoesNotLeakBigObjects() throws Exception {
- log.info("Starting test "+JavaClassNames.niceClassAndMethod());
- final int SIZE = 5;
- final int SIZE_UP_BOUND = SIZE+2;
- final int SIZE_DOWN_BOUND = SIZE-1;
- final int GRACE = 2;
- // the XML persistence uses a lot of space, we approx at between 2x and 3c
- final int SIZE_IN_XML = 3*SIZE;
- final int SIZE_IN_XML_DOWN = 2*SIZE;
-
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- TestApplication app = createFirstAppAndPersist(n1);
- noteUsedMemory("Finished seeding");
- Long initialUsed = usedMemory.peekLast();
- app.config().set(TestEntity.CONF_OBJECT, new BigObject(SIZE*1000*1000));
- assertUsedMemoryMaxDelta("Set a big config object", SIZE_UP_BOUND);
- forcePersistNow(n1);
- assertUsedMemoryMaxDelta("Persisted a big config object", SIZE_IN_XML);
-
- HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
- forceRebindNow(n2);
- assertUsedMemoryMaxDelta("Rebinded", SIZE_UP_BOUND);
-
- for (int i=0; i<10; i++)
- forceRebindNow(n2);
- assertUsedMemoryMaxDelta("Several more rebinds", GRACE);
- for (int i=0; i<10; i++) {
- forcePersistNow(n1);
- forceRebindNow(n2);
- }
- assertUsedMemoryMaxDelta("And more rebinds and more persists", GRACE);
-
- app.config().set(TestEntity.CONF_OBJECT, "big is now small");
- assertUsedMemoryMaxDelta("Big made small at primary", -SIZE_DOWN_BOUND);
- forcePersistNow(n1);
- assertUsedMemoryMaxDelta("And persisted", -SIZE_IN_XML_DOWN);
-
- forceRebindNow(n2);
- assertUsedMemoryMaxDelta("And at secondary", -SIZE_DOWN_BOUND);
-
- Entities.unmanage(app);
- forcePersistNow(n1);
- forceRebindNow(n2);
-
- assertUsedMemoryLessThan("And now all unmanaged", initialUsed+GRACE*1000*1000);
- }
-
- @Test(groups="Integration") // because it's slow
- // Sept 2014 - there is a small leak, of 200 bytes per child created and destroyed;
- // but this goes away when the app is destroyed; it may be a benign record
- public void testHotStandbyDoesNotLeakLotsOfRebindsCreatingAndDestroyingAChildEntity() throws Exception {
- log.info("Starting test "+JavaClassNames.niceClassAndMethod());
- final int DELTA = 2;
-
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- TestApplication app = createFirstAppAndPersist(n1);
- long initialUsed = noteUsedMemory("Created app");
-
- HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
- assertUsedMemoryMaxDelta("Standby created", DELTA);
-
- TestEntity lastChild = app.addChild(EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, "first-child"));
- Entities.manage(lastChild);
- forcePersistNow(n1);
- forceRebindNow(n2);
- assertUsedMemoryMaxDelta("Child created and rebinded once", DELTA);
-
- for (int i=0; i<1000; i++) {
- if (i==9 || (i+1)%100==0) {
- noteUsedMemory("iteration "+(i+1));
- usedMemory.removeLast();
- }
- TestEntity newChild = app.addChild(EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, "first-child"));
- Entities.manage(newChild);
- Entities.unmanage(lastChild);
- lastChild = newChild;
-
- forcePersistNow(n1);
- forceRebindNow(n2);
- }
- assertUsedMemoryMaxDelta("Persisted and rebinded 1000x", DELTA);
-
- Entities.unmanage(app);
- forcePersistNow(n1);
- forceRebindNow(n2);
-
- assertUsedMemoryLessThan("And now all unmanaged", initialUsed + DELTA*1000*1000);
- }
-
- protected void assertHotStandby(HaMgmtNode n1) {
- assertEquals(n1.ha.getNodeState(), ManagementNodeState.HOT_STANDBY);
- Assert.assertTrue(n1.rebinder().isReadOnlyRunning());
- Assert.assertFalse(n1.rebinder().isPersistenceRunning());
- }
-
- protected void assertMaster(HaMgmtNode n1) {
- assertEquals(n1.ha.getNodeState(), ManagementNodeState.MASTER);
- Assert.assertFalse(n1.rebinder().isReadOnlyRunning());
- Assert.assertTrue(n1.rebinder().isPersistenceRunning());
- }
-
- @Test
- public void testChangeMode() throws Exception {
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- TestApplication app = createFirstAppAndPersist(n1);
- HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
-
- TestEntity child = app.addChild(EntitySpec.create(TestEntity.class).configure(TestEntity.CONF_NAME, "first-child"));
- Entities.manage(child);
- TestApplication app2 = TestApplication.Factory.newManagedInstanceForTests(n1.mgmt);
- app2.config().set(TestEntity.CONF_NAME, "second-app");
-
- forcePersistNow(n1);
- n2.ha.setPriority(1);
- n1.ha.changeMode(HighAvailabilityMode.HOT_STANDBY);
-
- // both now hot standby
- assertHotStandby(n1);
- assertHotStandby(n2);
-
- assertEquals(n1.mgmt.getApplications().size(), 2);
- Application app2RO = n1.mgmt.lookup(app2.getId(), Application.class);
- Assert.assertNotNull(app2RO);
- assertEquals(app2RO.getConfig(TestEntity.CONF_NAME), "second-app");
- try {
- ((TestApplication)app2RO).setAttribute(TestEntity.SEQUENCE, 4);
- Assert.fail("Should not have allowed sensor to be set");
- } catch (Exception e) {
- Assert.assertTrue(e.toString().toLowerCase().contains("read-only"), "Error message did not contain expected text: "+e);
- }
-
- n1.ha.changeMode(HighAvailabilityMode.AUTO);
- n2.ha.changeMode(HighAvailabilityMode.HOT_STANDBY, true, false);
- // both still hot standby (n1 will defer to n2 as it has higher priority)
- assertHotStandby(n1);
- assertHotStandby(n2);
-
- // with priority 1, n2 will now be elected
- n2.ha.changeMode(HighAvailabilityMode.AUTO);
- assertHotStandby(n1);
- assertMaster(n2);
-
- assertEquals(n2.mgmt.getApplications().size(), 2);
- Application app2B = n2.mgmt.lookup(app2.getId(), Application.class);
- Assert.assertNotNull(app2B);
- assertEquals(app2B.getConfig(TestEntity.CONF_NAME), "second-app");
- ((TestApplication)app2B).setAttribute(TestEntity.SEQUENCE, 4);
-
- forcePersistNow(n2);
- forceRebindNow(n1);
- Application app2BRO = n1.mgmt.lookup(app2.getId(), Application.class);
- Assert.assertNotNull(app2BRO);
- EntityTestUtils.assertAttributeEquals(app2BRO, TestEntity.SEQUENCE, 4);
- }
-
- @Test(groups="Integration", invocationCount=20)
- public void testChangeModeManyTimes() throws Exception {
- testChangeMode();
- }
-
- @Test
- public void testChangeModeToDisabledAndBack() throws Exception {
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- n1.mgmt.getLocationManager().createLocation(LocationSpec.create(LocalhostMachine.class));
- @SuppressWarnings("unused")
- TestApplication app = createFirstAppAndPersist(n1);
-
- HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
-
- // disabled n1 allows n2 to become master when next we tell it to check
- n1.ha.changeMode(HighAvailabilityMode.DISABLED);
- n2.ha.changeMode(HighAvailabilityMode.AUTO);
- assertMaster(n2);
- assertEquals(n1.ha.getNodeState(), ManagementNodeState.FAILED);
- Assert.assertTrue(n1.mgmt.getApplications().isEmpty(), "n1 should have had no apps; instead had: "+n1.mgmt.getApplications());
- Assert.assertTrue(n1.mgmt.getEntityManager().getEntities().isEmpty(), "n1 should have had no entities; instead had: "+n1.mgmt.getEntityManager().getEntities());
- Assert.assertTrue(n1.mgmt.getLocationManager().getLocations().isEmpty(), "n1 should have had no locations; instead had: "+n1.mgmt.getLocationManager().getLocations());
-
- // we can now change n1 back to hot_standby
- n1.ha.changeMode(HighAvailabilityMode.HOT_STANDBY);
- assertHotStandby(n1);
- // and it sees apps
- Assert.assertFalse(n1.mgmt.getApplications().isEmpty(), "n1 should have had apps now");
- Assert.assertFalse(n1.mgmt.getLocationManager().getLocations().isEmpty(), "n1 should have had locations now");
- // and if n2 is disabled, n1 promotes
- n2.ha.changeMode(HighAvailabilityMode.DISABLED);
- n1.ha.changeMode(HighAvailabilityMode.AUTO);
- assertMaster(n1);
- assertEquals(n2.ha.getNodeState(), ManagementNodeState.FAILED);
- }
-
- @Test
- public void testHotStandbyDoesNotStartFeeds() throws Exception {
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- TestApplication app = createFirstAppAndPersist(n1);
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntityWithFunctionFeedImpl.class));
- forcePersistNow(n1);
- Assert.assertTrue(entity.feeds().getFeeds().size() > 0, "Feeds: "+entity.feeds().getFeeds());
- for (Feed feed : entity.feeds().getFeeds()) {
- assertTrue(feed.isRunning(), "Feed expected running, but it is non-running");
- }
-
- HaMgmtNode n2 = createHotStandby(Duration.PRACTICALLY_FOREVER);
- TestEntity entityRO = (TestEntity) n2.mgmt.lookup(entity.getId(), Entity.class);
- Assert.assertTrue(entityRO.feeds().getFeeds().size() > 0, "Feeds: "+entity.feeds().getFeeds());
- for (Feed feedRO : entityRO.feeds().getFeeds()) {
- assertFalse(feedRO.isRunning(), "Feed expected non-active, but it is running");
- }
- }
-
- @Test(groups="Integration")
- public void testHotStandbyDoesNotStartFeedsRebindingManyTimes() throws Exception {
- testHotStandbyDoesNotStartFeeds();
- final HaMgmtNode hsb = createHotStandby(Duration.millis(10));
- Repeater.create("until 10 rebinds").every(Duration.millis(100)).until(
- new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return ((RebindManagerImpl)hsb.mgmt.getRebindManager()).getReadOnlyRebindCount() >= 10;
- }
- }).runRequiringTrue();
- // make sure not too many tasks (allowing 5 for rebind etc; currently just 2)
- RebindTestFixture.waitForTaskCountToBecome(hsb.mgmt, 5);
- }
-
- @Test(groups="Integration")
- public void testHotStandbyDoesNotStartFeedsRebindingManyTimesWithAnotherFeedGenerator() throws Exception {
- HaMgmtNode n1 = createMaster(Duration.PRACTICALLY_FOREVER);
- TestApplication app = createFirstAppAndPersist(n1);
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class).impl(MyEntityWithNewFeedsEachTimeImpl.class));
- forcePersistNow(n1);
- Assert.assertTrue(entity.feeds().getFeeds().size() == 4, "Feeds: "+entity.feeds().getFeeds());
-
- final HaMgmtNode hsb = createHotStandby(Duration.millis(10));
- Repeater.create("until 10 rebinds").every(Duration.millis(100)).until(
- new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- return ((RebindManagerImpl)hsb.mgmt.getRebindManager()).getReadOnlyRebindCount() >= 10;
- }
- }).runRequiringTrue();
- // make sure not too many tasks (allowing 5 for rebind etc; currently just 2)
- RebindTestFixture.waitForTaskCountToBecome(hsb.mgmt, 5);
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/ImmutableManagementPlaneSyncRecord.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/ImmutableManagementPlaneSyncRecord.java b/core/src/test/java/brooklyn/management/ha/ImmutableManagementPlaneSyncRecord.java
deleted file mode 100644
index 10c47f9..0000000
--- a/core/src/test/java/brooklyn/management/ha/ImmutableManagementPlaneSyncRecord.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableMap;
-
-public class ImmutableManagementPlaneSyncRecord implements ManagementPlaneSyncRecord {
- private final String masterNodeId;
- private final Map<String, ManagementNodeSyncRecord> managementNodes;
-
- ImmutableManagementPlaneSyncRecord(String masterNodeId, Map<String, ManagementNodeSyncRecord> nodes) {
- this.masterNodeId = masterNodeId;
- this.managementNodes = ImmutableMap.copyOf(nodes);
- }
-
- @Override
- public String getMasterNodeId() {
- return masterNodeId;
- }
-
- @Override
- public Map<String, ManagementNodeSyncRecord> getManagementNodes() {
- return managementNodes;
- }
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this).add("master", masterNodeId).add("nodes", managementNodes.keySet()).toString();
- }
-
- @Override
- public String toVerboseString() {
- return Objects.toStringHelper(this).add("master", masterNodeId).add("nodes", managementNodes).toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/ManagementPlaneSyncRecordPersisterInMemory.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/ManagementPlaneSyncRecordPersisterInMemory.java b/core/src/test/java/brooklyn/management/ha/ManagementPlaneSyncRecordPersisterInMemory.java
deleted file mode 100644
index bc8b418..0000000
--- a/core/src/test/java/brooklyn/management/ha/ManagementPlaneSyncRecordPersisterInMemory.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.IOException;
-import java.util.concurrent.TimeoutException;
-
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.rebind.persister.InMemoryObjectStore;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.VisibleForTesting;
-
-/** @deprecated since 0.7.0 use {@link ManagementPlaneSyncRecordPersisterToObjectStore}
- * with {@link InMemoryObjectStore}
- * <code>
- * new ManagementPlaneSyncRecordPersisterToObjectStore(new InMemoryObjectStore(), classLoader)
- * </code> */
-@Deprecated
-public class ManagementPlaneSyncRecordPersisterInMemory implements ManagementPlaneSyncRecordPersister {
-
- private static final Logger LOG = LoggerFactory.getLogger(ManagementPlaneSyncRecordPersisterInMemory.class);
-
- private final MutableManagementPlaneSyncRecord memento = new MutableManagementPlaneSyncRecord();
-
- private volatile boolean running = true;
-
- @Override
- public synchronized void stop() {
- running = false;
- }
-
- @Override
- public ManagementPlaneSyncRecord loadSyncRecord() throws IOException {
- if (!running) {
- throw new IllegalStateException("Persister not running; cannot load memento");
- }
-
- return memento.snapshot();
- }
-
- @VisibleForTesting
- @Override
- public synchronized void waitForWritesCompleted(Duration timeout) throws InterruptedException, TimeoutException {
- // The synchronized is sufficient - guarantee that no concurrent calls
- return;
- }
-
- @Override
- public synchronized void delta(Delta delta) {
- if (!running) {
- if (LOG.isDebugEnabled()) LOG.debug("Persister not running; ignoring checkpointed delta of manager-memento");
- return;
- }
-
- for (ManagementNodeSyncRecord m : delta.getNodes()) {
- memento.addNode(m);
- }
- for (String id : delta.getRemovedNodeIds()) {
- memento.deleteNode(id);
- }
- switch (delta.getMasterChange()) {
- case NO_CHANGE:
- break; // no-op
- case SET_MASTER:
- memento.setMasterNodeId(checkNotNull(delta.getNewMasterOrNull()));
- break;
- case CLEAR_MASTER:
- memento.setMasterNodeId(null);
- break; // no-op
- default:
- throw new IllegalStateException("Unknown state for master-change: "+delta.getMasterChange());
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/MasterChooserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/MasterChooserTest.java b/core/src/test/java/brooklyn/management/ha/MasterChooserTest.java
deleted file mode 100644
index 14804b1..0000000
--- a/core/src/test/java/brooklyn/management/ha/MasterChooserTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNull;
-
-import java.util.List;
-
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.BrooklynVersion;
-import brooklyn.entity.basic.EntityFunctions;
-import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
-import brooklyn.management.ha.BasicMasterChooser.AlphabeticMasterChooser;
-import brooklyn.management.ha.BasicMasterChooser.ScoredRecord;
-import brooklyn.util.time.Duration;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
-public class MasterChooserTest {
-
- private MutableManagementPlaneSyncRecord memento;
- private AlphabeticMasterChooser chooser;
- private long now;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- memento = new MutableManagementPlaneSyncRecord();
- chooser = new AlphabeticMasterChooser();
- now = System.currentTimeMillis();
- }
-
- @Test
- public void testChoosesFirstAlphanumeric() throws Exception {
- memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now));
- memento.addNode(newManagerMemento("node2", ManagementNodeState.STANDBY, now));
- memento.addNode(newManagerMemento("node3", ManagementNodeState.STANDBY, now));
- Duration heartbeatTimeout = Duration.THIRTY_SECONDS;
- String ownNodeId = "node2";
- assertEquals(chooser.choose(memento, heartbeatTimeout, ownNodeId).getNodeId(), "node1");
- }
-
- @Test
- public void testReturnsNullIfNoValid() throws Exception {
- memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now - 31*1000));
- Duration heartbeatTimeout = Duration.THIRTY_SECONDS;
- assertNull(chooser.choose(memento, heartbeatTimeout, "node2"));
- }
-
- @Test
- public void testFiltersOutByHeartbeat() throws Exception {
- memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now - 31*1000));
- memento.addNode(newManagerMemento("node2", ManagementNodeState.STANDBY, now - 20*1000));
- memento.addNode(newManagerMemento("node3", ManagementNodeState.STANDBY, now));
- Duration heartbeatTimeout = Duration.THIRTY_SECONDS;
- assertEquals(getIds(chooser.sort(chooser.filterHealthy(memento, heartbeatTimeout, now))), ImmutableList.of("node2", "node3"));
- }
-
- protected static List<String> getIds(List<ScoredRecord<?>> filterHealthy) {
- return ImmutableList.copyOf(Iterables.transform(filterHealthy, EntityFunctions.id()));
- }
-
- @Test
- public void testFiltersOutByStatusNotPreferringMaster() throws Exception {
- assertEquals(doTestFiltersOutByStatus(false, false), ImmutableList.of("node4", "node5"));
- }
- @Test
- public void testFiltersOutByStatusPreferringMaster() throws Exception {
- assertEquals(doTestFiltersOutByStatus(true, false), ImmutableList.of("node5", "node4"));
- }
-
- @Test
- public void testFiltersOutByStatusNotPreferringHot() throws Exception {
- assertEquals(doTestFiltersOutByStatus(false, true), ImmutableList.of("node4", "node5", "node6"));
- }
- @Test
- public void testFiltersOutByStatusPreferringHot() throws Exception {
- assertEquals(doTestFiltersOutByStatus(true, true), ImmutableList.of("node5", "node6", "node4"));
- }
-
- protected List<String> doTestFiltersOutByStatus(boolean preferHot, boolean includeHot) throws Exception {
- chooser = new AlphabeticMasterChooser(preferHot);
- memento.addNode(newManagerMemento("node1", ManagementNodeState.FAILED, now));
- memento.addNode(newManagerMemento("node2", ManagementNodeState.TERMINATED, now));
- memento.addNode(newManagerMemento("node3", null, now));
- memento.addNode(newManagerMemento("node4", ManagementNodeState.STANDBY, now));
- memento.addNode(newManagerMemento("node5", ManagementNodeState.MASTER, now));
- if (includeHot)
- memento.addNode(newManagerMemento("node6", ManagementNodeState.HOT_STANDBY, now));
- return getIds(chooser.sort(chooser.filterHealthy(memento, Duration.THIRTY_SECONDS, now)));
- }
-
- @Test
- public void testExplicityPriority() throws Exception {
- chooser = new AlphabeticMasterChooser();
- memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now, BrooklynVersion.get(), 2L));
- memento.addNode(newManagerMemento("node2", ManagementNodeState.STANDBY, now, BrooklynVersion.get(), -1L));
- memento.addNode(newManagerMemento("node3", ManagementNodeState.STANDBY, now, BrooklynVersion.get(), null));
- List<String> order = getIds(chooser.sort(chooser.filterHealthy(memento, Duration.THIRTY_SECONDS, now)));
- assertEquals(order, ImmutableList.of("node1", "node3", "node2"));
- }
-
- @Test
- public void testVersionsMaybeNull() throws Exception {
- chooser = new AlphabeticMasterChooser();
- memento.addNode(newManagerMemento("node1", ManagementNodeState.STANDBY, now, "v10", null));
- memento.addNode(newManagerMemento("node2", ManagementNodeState.STANDBY, now, "v3-snapshot", null));
- memento.addNode(newManagerMemento("node3", ManagementNodeState.STANDBY, now, "v3-snapshot", -1L));
- memento.addNode(newManagerMemento("node4", ManagementNodeState.STANDBY, now, "v3-snapshot", null));
- memento.addNode(newManagerMemento("node5", ManagementNodeState.STANDBY, now, "v3-stable", null));
- memento.addNode(newManagerMemento("node6", ManagementNodeState.STANDBY, now, "v1", null));
- memento.addNode(newManagerMemento("node7", ManagementNodeState.STANDBY, now, null, null));
- List<String> order = getIds(chooser.sort(chooser.filterHealthy(memento, Duration.THIRTY_SECONDS, now)));
- assertEquals(order, ImmutableList.of("node1", "node5", "node6", "node2", "node4", "node7", "node3"));
- }
-
- private ManagementNodeSyncRecord newManagerMemento(String nodeId, ManagementNodeState status, long timestamp) {
- return newManagerMemento(nodeId, status, timestamp, BrooklynVersion.get(), null);
- }
- private ManagementNodeSyncRecord newManagerMemento(String nodeId, ManagementNodeState status, long timestamp,
- String version, Long priority) {
- return BasicManagementNodeSyncRecord.builder().brooklynVersion(version).nodeId(nodeId).status(status).localTimestamp(timestamp).remoteTimestamp(timestamp).
- priority(priority).build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/MutableManagementPlaneSyncRecord.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/MutableManagementPlaneSyncRecord.java b/core/src/test/java/brooklyn/management/ha/MutableManagementPlaneSyncRecord.java
deleted file mode 100644
index a68cac3..0000000
--- a/core/src/test/java/brooklyn/management/ha/MutableManagementPlaneSyncRecord.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-
-import com.google.common.collect.Maps;
-
-public class MutableManagementPlaneSyncRecord implements ManagementPlaneSyncRecord {
- private String masterNodeId;
- private Map<String, ManagementNodeSyncRecord> managementNodes = Maps.newConcurrentMap();
-
- @Override
- public String getMasterNodeId() {
- return masterNodeId;
- }
-
- @Override
- public Map<String, ManagementNodeSyncRecord> getManagementNodes() {
- return managementNodes;
- }
-
- @Override
- public String toVerboseString() {
- return toString();
- }
-
- public ImmutableManagementPlaneSyncRecord snapshot() {
- return new ImmutableManagementPlaneSyncRecord(masterNodeId, managementNodes);
- }
-
- public void setMasterNodeId(String masterNodeId) {
- this.masterNodeId = masterNodeId;
- }
-
- public void addNode(ManagementNodeSyncRecord memento) {
- managementNodes.put(memento.getNodeId(), memento);
- }
-
- public void deleteNode(String nodeId) {
- managementNodes.remove(nodeId);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/TestEntityFailingRebind.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/TestEntityFailingRebind.java b/core/src/test/java/brooklyn/management/ha/TestEntityFailingRebind.java
deleted file mode 100644
index a8cfced..0000000
--- a/core/src/test/java/brooklyn/management/ha/TestEntityFailingRebind.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import org.apache.brooklyn.test.entity.TestApplicationImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TestEntityFailingRebind extends TestApplicationImpl {
-
- private static final Logger LOG = LoggerFactory.getLogger(TestEntityFailingRebind.class);
-
- public static class RebindException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- public RebindException(String message) {
- super(message);
- }
- }
-
- private static boolean throwOnRebind = true;
-
- public static void setThrowOnRebind(boolean state) {
- throwOnRebind = state;
- }
-
- public static boolean getThrowOnRebind() {
- return throwOnRebind;
- }
-
- @Override
- public void rebind() {
- if (throwOnRebind) {
- LOG.warn("Throwing intentional exception to simulate failure of rebinding " + this);
- throw new RebindException("Intentional exception thrown when rebinding " + this);
- }
- }
-
-}
[18/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/LocalSubscriptionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalSubscriptionManager.java b/core/src/main/java/brooklyn/management/internal/LocalSubscriptionManager.java
deleted file mode 100644
index c2c7905..0000000
--- a/core/src/main/java/brooklyn/management/internal/LocalSubscriptionManager.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static brooklyn.util.JavaGroovyEquivalents.elvis;
-import static brooklyn.util.JavaGroovyEquivalents.groovyTruth;
-import static brooklyn.util.JavaGroovyEquivalents.join;
-import static brooklyn.util.JavaGroovyEquivalents.mapOf;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.event.Sensor;
-import org.apache.brooklyn.api.event.SensorEvent;
-import org.apache.brooklyn.api.event.SensorEventListener;
-import org.apache.brooklyn.api.management.ExecutionManager;
-import org.apache.brooklyn.api.management.SubscriptionHandle;
-import org.apache.brooklyn.api.management.SubscriptionManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.util.task.BasicExecutionManager;
-import brooklyn.util.task.SingleThreadedScheduler;
-import brooklyn.util.text.Identifiers;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimaps;
-
-/**
- * A {@link SubscriptionManager} that stores subscription details locally.
- */
-public class LocalSubscriptionManager extends AbstractSubscriptionManager {
-
- private static final Logger LOG = LoggerFactory.getLogger(LocalSubscriptionManager.class);
-
- protected final ExecutionManager em;
-
- private final String tostring = "SubscriptionContext("+Identifiers.getBase64IdFromValue(System.identityHashCode(this), 5)+")";
-
- private final AtomicLong totalEventsPublishedCount = new AtomicLong();
- private final AtomicLong totalEventsDeliveredCount = new AtomicLong();
-
- @SuppressWarnings("rawtypes")
- protected final ConcurrentMap<String, Subscription> allSubscriptions = new ConcurrentHashMap<String, Subscription>();
- @SuppressWarnings("rawtypes")
- protected final ConcurrentMap<Object, Set<Subscription>> subscriptionsBySubscriber = new ConcurrentHashMap<Object, Set<Subscription>>();
- @SuppressWarnings("rawtypes")
- protected final ConcurrentMap<Object, Set<Subscription>> subscriptionsByToken = new ConcurrentHashMap<Object, Set<Subscription>>();
-
- public LocalSubscriptionManager(ExecutionManager m) {
- this.em = m;
- }
-
- public long getNumSubscriptions() {
- return allSubscriptions.size();
- }
-
- public long getTotalEventsPublished() {
- return totalEventsPublishedCount.get();
- }
-
- public long getTotalEventsDelivered() {
- return totalEventsDeliveredCount.get();
- }
-
- @SuppressWarnings("unchecked")
- protected synchronized <T> SubscriptionHandle subscribe(Map<String, Object> flags, Subscription<T> s) {
- Entity producer = s.producer;
- Sensor<T> sensor= s.sensor;
- s.subscriber = getSubscriber(flags, s);
- if (flags.containsKey("subscriberExecutionManagerTag")) {
- s.subscriberExecutionManagerTag = flags.remove("subscriberExecutionManagerTag");
- s.subscriberExecutionManagerTagSupplied = true;
- } else {
- s.subscriberExecutionManagerTag =
- s.subscriber instanceof Entity ? "subscription-delivery-entity-"+((Entity)s.subscriber).getId()+"["+s.subscriber+"]" :
- s.subscriber instanceof String ? "subscription-delivery-string["+s.subscriber+"]" :
- "subscription-delivery-object["+s.subscriber+"]";
- s.subscriberExecutionManagerTagSupplied = false;
- }
- s.eventFilter = (Predicate<SensorEvent<T>>) flags.remove("eventFilter");
- s.flags = flags;
-
- if (LOG.isDebugEnabled()) LOG.debug("Creating subscription {} for {} on {} {} in {}", new Object[] {s.id, s.subscriber, producer, sensor, this});
- allSubscriptions.put(s.id, s);
- addToMapOfSets(subscriptionsByToken, makeEntitySensorToken(s.producer, s.sensor), s);
- if (s.subscriber!=null) {
- addToMapOfSets(subscriptionsBySubscriber, s.subscriber, s);
- }
- if (!s.subscriberExecutionManagerTagSupplied && s.subscriberExecutionManagerTag!=null) {
- ((BasicExecutionManager) em).setTaskSchedulerForTag(s.subscriberExecutionManagerTag, SingleThreadedScheduler.class);
- }
- return s;
- }
-
- @SuppressWarnings("unchecked")
- public Set<SubscriptionHandle> getSubscriptionsForSubscriber(Object subscriber) {
- return (Set<SubscriptionHandle>) ((Set<?>) elvis(subscriptionsBySubscriber.get(subscriber), Collections.emptySet()));
- }
-
- public synchronized Set<SubscriptionHandle> getSubscriptionsForEntitySensor(Entity source, Sensor<?> sensor) {
- Set<SubscriptionHandle> subscriptions = new LinkedHashSet<SubscriptionHandle>();
- subscriptions.addAll(elvis(subscriptionsByToken.get(makeEntitySensorToken(source, sensor)), Collections.emptySet()));
- subscriptions.addAll(elvis(subscriptionsByToken.get(makeEntitySensorToken(null, sensor)), Collections.emptySet()));
- subscriptions.addAll(elvis(subscriptionsByToken.get(makeEntitySensorToken(source, null)), Collections.emptySet()));
- subscriptions.addAll(elvis(subscriptionsByToken.get(makeEntitySensorToken(null, null)), Collections.emptySet()));
- return subscriptions;
- }
-
- /**
- * Unsubscribe the given subscription id.
- *
- * @see #subscribe(Map, Entity, Sensor, SensorEventListener)
- */
- @SuppressWarnings("rawtypes")
- public synchronized boolean unsubscribe(SubscriptionHandle sh) {
- if (!(sh instanceof Subscription)) throw new IllegalArgumentException("Only subscription handles of type Subscription supported: sh="+sh+"; type="+(sh != null ? sh.getClass().getCanonicalName() : null));
- Subscription s = (Subscription) sh;
- boolean result = allSubscriptions.remove(s.id) != null;
- boolean b2 = removeFromMapOfCollections(subscriptionsByToken, makeEntitySensorToken(s.producer, s.sensor), s);
- assert result==b2;
- if (s.subscriber!=null) {
- boolean b3 = removeFromMapOfCollections(subscriptionsBySubscriber, s.subscriber, s);
- assert b3 == b2;
- }
-
- // FIXME ALEX - this seems wrong
- ((BasicExecutionManager) em).setTaskSchedulerForTag(s.subscriberExecutionManagerTag, SingleThreadedScheduler.class);
- return result;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public <T> void publish(final SensorEvent<T> event) {
- // REVIEW 1459 - execution
-
- // delivery in parallel/background, using execution manager
-
- // subscriptions, should define SingleThreadedScheduler for any subscriber ID tag
- // in order to ensure callbacks are invoked in the order they are submitted
- // (recommend exactly one per subscription to prevent deadlock)
- // this is done with:
- // em.setTaskSchedulerForTag(subscriberId, SingleThreadedScheduler.class);
-
- //note, generating the notifications must be done in the calling thread to preserve order
- //e.g. emit(A); emit(B); should cause onEvent(A); onEvent(B) in that order
- if (LOG.isTraceEnabled()) LOG.trace("{} got event {}", this, event);
- totalEventsPublishedCount.incrementAndGet();
-
- Set<Subscription> subs = (Set<Subscription>) ((Set<?>) getSubscriptionsForEntitySensor(event.getSource(), event.getSensor()));
- if (groovyTruth(subs)) {
- if (LOG.isTraceEnabled()) LOG.trace("sending {}, {} to {}", new Object[] {event.getSensor().getName(), event, join(subs, ",")});
- for (Subscription s : subs) {
- if (s.eventFilter!=null && !s.eventFilter.apply(event))
- continue;
- final Subscription sAtClosureCreation = s;
-
-// Set<Object> tags = MutableSet.of();
-// if (s.subscriberExecutionManagerTag!=null) tags.add(s.subscriberExecutionManagerTag);
-// if (event.getSource()!=null) tags.add(BrooklynTaskTags.tagForContextEntity(event.getSource()));
-// Map<String, Object> tagsMap = mapOf("tags", (Object)tags);
- // use code above, instead of line below, if we want subscription deliveries associated with the entity;
- // that will cause them to be cancelled when the entity is unmanaged
- // (not sure that is useful, and likely NOT worth the expense, but it might be...) -Alex Oct 2014
- Map<String, Object> tagsMap = mapOf("tag", s.subscriberExecutionManagerTag);
-
- em.submit(tagsMap, new Runnable() {
- @Override
- public String toString() {
- return "LSM.publish("+event+")";
- }
- public void run() {
- try {
- sAtClosureCreation.listener.onEvent(event);
- } catch (Throwable t) {
- if (event!=null && event.getSource()!=null && Entities.isNoLongerManaged(event.getSource())) {
- LOG.debug("Error processing subscriptions to "+this+", after entity unmanaged: "+t, t);
- } else {
- LOG.warn("Error processing subscriptions to "+this+": "+t, t);
- }
- }
- }});
- totalEventsDeliveredCount.incrementAndGet();
- }
- }
- }
-
- @Override
- public String toString() {
- return tostring;
- }
-
- /**
- * Copied from LanguageUtils.groovy, to remove dependency.
- *
- * Adds the given value to a collection in the map under the key.
- *
- * A collection (as {@link LinkedHashMap}) will be created if necessary,
- * synchronized on map for map access/change and set for addition there
- *
- * @return the updated set (instance, not copy)
- *
- * @deprecated since 0.5; use {@link HashMultimap}, and {@link Multimaps#synchronizedSetMultimap(com.google.common.collect.SetMultimap)}
- */
- @Deprecated
- private static <K,V> Set<V> addToMapOfSets(Map<K,Set<V>> map, K key, V valueInCollection) {
- Set<V> coll;
- synchronized (map) {
- coll = map.get(key);
- if (coll==null) {
- coll = new LinkedHashSet<V>();
- map.put(key, coll);
- }
- if (coll.isEmpty()) {
- synchronized (coll) {
- coll.add(valueInCollection);
- }
- //if collection was empty then add to the collection while holding the map lock, to prevent removal
- return coll;
- }
- }
- synchronized (coll) {
- if (!coll.isEmpty()) {
- coll.add(valueInCollection);
- return coll;
- }
- }
- //if was empty, recurse, because someone else might be removing the collection
- return addToMapOfSets(map, key, valueInCollection);
- }
-
- /**
- * Copied from LanguageUtils.groovy, to remove dependency.
- *
- * Removes the given value from a collection in the map under the key.
- *
- * @return the updated set (instance, not copy)
- *
- * @deprecated since 0.5; use {@link ArrayListMultimap} or {@link HashMultimap}, and {@link Multimaps#synchronizedListMultimap(com.google.common.collect.ListMultimap)} etc
- */
- @Deprecated
- private static <K,V> boolean removeFromMapOfCollections(Map<K,? extends Collection<V>> map, K key, V valueInCollection) {
- Collection<V> coll;
- synchronized (map) {
- coll = map.get(key);
- if (coll==null) return false;
- }
- boolean result;
- synchronized (coll) {
- result = coll.remove(valueInCollection);
- }
- if (coll.isEmpty()) {
- synchronized (map) {
- synchronized (coll) {
- if (coll.isEmpty()) {
- //only remove from the map if no one is adding to the collection or to the map, and the collection is still in the map
- if (map.get(key)==coll) {
- map.remove(key);
- }
- }
- }
- }
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java b/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java
deleted file mode 100644
index 6da41c8..0000000
--- a/core/src/main/java/brooklyn/management/internal/LocalUsageManager.java
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.basic.Lifecycle;
-import brooklyn.internal.storage.BrooklynStorage;
-
-import org.apache.brooklyn.location.basic.AbstractLocation;
-import org.apache.brooklyn.location.basic.LocationConfigKeys;
-import org.apache.brooklyn.location.basic.LocationInternal;
-
-import brooklyn.management.ManagementContextInjectable;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.usage.ApplicationUsage;
-import brooklyn.management.usage.LocationUsage;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.javalang.Reflections;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-
-public class LocalUsageManager implements UsageManager {
-
- // TODO Threading model needs revisited.
- // Synchronizes on updates to storage; but if two Brooklyn nodes were both writing to the same
- // ApplicationUsage or LocationUsage record there'd be a race. That currently won't happen
- // (at least for ApplicationUsage?) because the app is mastered in just one node at a time,
- // and because location events are just manage/unmanage which should be happening in just
- // one place at a time for a given location.
-
- private static final Logger log = LoggerFactory.getLogger(LocalUsageManager.class);
-
- private static class ApplicationMetadataImpl implements brooklyn.management.internal.UsageListener.ApplicationMetadata {
- private final Application app;
- private String applicationId;
- private String applicationName;
- private String entityType;
- private String catalogItemId;
- private Map<String, String> metadata;
-
- ApplicationMetadataImpl(Application app) {
- this.app = checkNotNull(app, "app");
- applicationId = app.getId();
- applicationName = app.getDisplayName();
- entityType = app.getEntityType().getName();
- catalogItemId = app.getCatalogItemId();
- metadata = ((EntityInternal)app).toMetadataRecord();
- }
- @Override public Application getApplication() {
- return app;
- }
- @Override public String getApplicationId() {
- return applicationId;
- }
- @Override public String getApplicationName() {
- return applicationName;
- }
- @Override public String getEntityType() {
- return entityType;
- }
- @Override public String getCatalogItemId() {
- return catalogItemId;
- }
- @Override public Map<String, String> getMetadata() {
- return metadata;
- }
- }
-
- private static class LocationMetadataImpl implements brooklyn.management.internal.UsageListener.LocationMetadata {
- private final Location loc;
- private String locationId;
- private Map<String, String> metadata;
-
- LocationMetadataImpl(Location loc) {
- this.loc = checkNotNull(loc, "loc");
- locationId = loc.getId();
- metadata = ((LocationInternal)loc).toMetadataRecord();
- }
- @Override public Location getLocation() {
- return loc;
- }
- @Override public String getLocationId() {
- return locationId;
- }
- @Override public Map<String, String> getMetadata() {
- return metadata;
- }
- }
-
- // Register a coercion from String->UsageListener, so that USAGE_LISTENERS defined in brooklyn.properties
- // will be instantiated, given their class names.
- static {
- TypeCoercions.registerAdapter(String.class, brooklyn.management.internal.UsageListener.class, new Function<String, brooklyn.management.internal.UsageListener>() {
- @Override public brooklyn.management.internal.UsageListener apply(String input) {
- // TODO Want to use classLoader = mgmt.getCatalog().getRootClassLoader();
- ClassLoader classLoader = LocalUsageManager.class.getClassLoader();
- Optional<Object> result = Reflections.invokeConstructorWithArgs(classLoader, input);
- if (result.isPresent()) {
- if (result.get() instanceof brooklyn.management.internal.UsageManager.UsageListener) {
- return new brooklyn.management.internal.UsageManager.UsageListener.UsageListenerAdapter((brooklyn.management.internal.UsageManager.UsageListener) result.get());
- } else {
- return (brooklyn.management.internal.UsageListener) result.get();
- }
- } else {
- throw new IllegalStateException("Failed to create UsageListener from class name '"+input+"' using no-arg constructor");
- }
- }
- });
- }
-
- @VisibleForTesting
- public static final String APPLICATION_USAGE_KEY = "usage-application";
-
- @VisibleForTesting
- public static final String LOCATION_USAGE_KEY = "usage-location";
-
- private final LocalManagementContext managementContext;
-
- private final Object mutex = new Object();
-
- private final List<brooklyn.management.internal.UsageListener> listeners = Lists.newCopyOnWriteArrayList();
-
- private final AtomicInteger listenerQueueSize = new AtomicInteger();
-
- private ListeningExecutorService listenerExecutor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
- .setNameFormat("brooklyn-usagemanager-listener-%d")
- .build()));
-
- public LocalUsageManager(LocalManagementContext managementContext) {
- this.managementContext = checkNotNull(managementContext, "managementContext");
-
- // TODO Once brooklyn.management.internal.UsageManager.UsageListener is deleted, restore this
- // to normal generics!
- Collection<?> listeners = managementContext.getBrooklynProperties().getConfig(UsageManager.USAGE_LISTENERS);
- if (listeners != null) {
- for (Object listener : listeners) {
- if (listener instanceof ManagementContextInjectable) {
- ((ManagementContextInjectable)listener).injectManagementContext(managementContext);
- }
- if (listener instanceof brooklyn.management.internal.UsageManager.UsageListener) {
- addUsageListener((brooklyn.management.internal.UsageManager.UsageListener)listener);
- } else if (listener instanceof brooklyn.management.internal.UsageListener) {
- addUsageListener((brooklyn.management.internal.UsageListener)listener);
- } else if (listener == null) {
- throw new NullPointerException("null listener in config "+UsageManager.USAGE_LISTENERS);
- } else {
- throw new ClassCastException("listener "+listener+" of type "+listener.getClass()+" is not of type "+brooklyn.management.internal.UsageListener.class.getName());
- }
- }
- }
- }
-
- public void terminate() {
- // Wait for the listeners to finish + close the listeners
- Duration timeout = managementContext.getBrooklynProperties().getConfig(UsageManager.USAGE_LISTENER_TERMINATION_TIMEOUT);
- if (listenerQueueSize.get() > 0) {
- log.info("Usage manager waiting for "+listenerQueueSize+" listener events for up to "+timeout);
- }
- List<ListenableFuture<?>> futures = Lists.newArrayList();
- for (final brooklyn.management.internal.UsageListener listener : listeners) {
- ListenableFuture<?> future = listenerExecutor.submit(new Runnable() {
- public void run() {
- if (listener instanceof Closeable) {
- try {
- ((Closeable)listener).close();
- } catch (IOException e) {
- log.warn("Problem closing usage listener "+listener+" (continuing)", e);
- }
- }
- }});
- futures.add(future);
- }
- try {
- Futures.successfulAsList(futures).get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- log.warn("Problem terminiating usage listeners (continuing)", e);
- } finally {
- listenerExecutor.shutdownNow();
- }
- }
-
- private void execOnListeners(final Function<brooklyn.management.internal.UsageListener, Void> job) {
- for (final brooklyn.management.internal.UsageListener listener : listeners) {
- listenerQueueSize.incrementAndGet();
- listenerExecutor.execute(new Runnable() {
- public void run() {
- try {
- job.apply(listener);
- } catch (RuntimeException e) {
- log.error("Problem notifying listener "+listener+" of "+job, e);
- Exceptions.propagateIfFatal(e);
- } finally {
- listenerQueueSize.decrementAndGet();
- }
- }});
- }
- }
-
- @Override
- public void recordApplicationEvent(final Application app, final Lifecycle state) {
- log.debug("Storing application lifecycle usage event: application {} in state {}", new Object[] {app, state});
- ConcurrentMap<String, ApplicationUsage> eventMap = managementContext.getStorage().getMap(APPLICATION_USAGE_KEY);
- synchronized (mutex) {
- ApplicationUsage usage = eventMap.get(app.getId());
- if (usage == null) {
- usage = new ApplicationUsage(app.getId(), app.getDisplayName(), app.getEntityType().getName(), ((EntityInternal)app).toMetadataRecord());
- }
- final ApplicationUsage.ApplicationEvent event = new ApplicationUsage.ApplicationEvent(state, getUser());
- usage.addEvent(event);
- eventMap.put(app.getId(), usage);
-
- execOnListeners(new Function<brooklyn.management.internal.UsageListener, Void>() {
- public Void apply(brooklyn.management.internal.UsageListener listener) {
- listener.onApplicationEvent(new ApplicationMetadataImpl(Entities.proxy(app)), event);
- return null;
- }
- public String toString() {
- return "applicationEvent("+app+", "+state+")";
- }});
- }
- }
-
- /**
- * Adds this location event to the usage record for the given location (creating the usage
- * record if one does not already exist).
- */
- @Override
- public void recordLocationEvent(final Location loc, final Lifecycle state) {
- // TODO This approach (i.e. recording events on manage/unmanage would not work for
- // locations that are reused. For example, in a FixedListMachineProvisioningLocation
- // the ssh machine location is returned to the pool and handed back out again.
- // But maybe the solution there is to hand out different instances so that one user
- // can't change the config of the SshMachineLocation to subsequently affect the next
- // user.
- //
- // TODO Should perhaps extract the location storage methods into their own class,
- // but no strong enough feelings yet...
-
- checkNotNull(loc, "location");
- if (loc.getConfig(AbstractLocation.TEMPORARY_LOCATION)) {
- log.info("Ignoring location lifecycle usage event for {} (state {}), because location is a temporary location", loc, state);
- return;
- }
- checkNotNull(state, "state of location %s", loc);
- if (loc.getId() == null) {
- log.error("Ignoring location lifecycle usage event for {} (state {}), because location has no id", loc, state);
- return;
- }
- if (managementContext.getStorage() == null) {
- log.warn("Cannot store location lifecycle usage event for {} (state {}), because storage not available", loc, state);
- return;
- }
-
- Object callerContext = loc.getConfig(LocationConfigKeys.CALLER_CONTEXT);
-
- if (callerContext != null && callerContext instanceof Entity) {
- log.debug("Storing location lifecycle usage event: location {} in state {}; caller context {}", new Object[] {loc, state, callerContext});
-
- Entity caller = (Entity) callerContext;
- String entityTypeName = caller.getEntityType().getName();
- String appId = caller.getApplicationId();
-
- final LocationUsage.LocationEvent event = new LocationUsage.LocationEvent(state, caller.getId(), entityTypeName, appId, getUser());
-
- ConcurrentMap<String, LocationUsage> usageMap = managementContext.getStorage().<String, LocationUsage>getMap(LOCATION_USAGE_KEY);
- synchronized (mutex) {
- LocationUsage usage = usageMap.get(loc.getId());
- if (usage == null) {
- usage = new LocationUsage(loc.getId(), ((LocationInternal)loc).toMetadataRecord());
- }
- usage.addEvent(event);
- usageMap.put(loc.getId(), usage);
-
- execOnListeners(new Function<brooklyn.management.internal.UsageListener, Void>() {
- public Void apply(brooklyn.management.internal.UsageListener listener) {
- listener.onLocationEvent(new LocationMetadataImpl(loc), event);
- return null;
- }
- public String toString() {
- return "locationEvent("+loc+", "+state+")";
- }});
- }
- } else {
- // normal for high-level locations
- log.trace("Not recording location lifecycle usage event for {} in state {}, because no caller context", new Object[] {loc, state});
- }
- }
-
- /**
- * Returns the usage info for the location with the given id, or null if unknown.
- */
- @Override
- public LocationUsage getLocationUsage(String locationId) {
- BrooklynStorage storage = managementContext.getStorage();
-
- Map<String, LocationUsage> usageMap = storage.getMap(LOCATION_USAGE_KEY);
- return usageMap.get(locationId);
- }
-
- /**
- * Returns the usage info that matches the given predicate.
- * For example, could be used to find locations used within a given time period.
- */
- @Override
- public Set<LocationUsage> getLocationUsage(Predicate<? super LocationUsage> filter) {
- // TODO could do more efficient indexing, to more easily find locations in use during a given period.
- // But this is good enough for first-pass.
-
- Map<String, LocationUsage> usageMap = managementContext.getStorage().getMap(LOCATION_USAGE_KEY);
- Set<LocationUsage> result = Sets.newLinkedHashSet();
-
- for (LocationUsage usage : usageMap.values()) {
- if (filter.apply(usage)) {
- result.add(usage);
- }
- }
- return result;
- }
-
- /**
- * Returns the usage info for the location with the given id, or null if unknown.
- */
- @Override
- public ApplicationUsage getApplicationUsage(String appId) {
- BrooklynStorage storage = managementContext.getStorage();
-
- Map<String, ApplicationUsage> usageMap = storage.getMap(APPLICATION_USAGE_KEY);
- return usageMap.get(appId);
- }
-
- /**
- * Returns the usage info that matches the given predicate.
- * For example, could be used to find applications used within a given time period.
- */
- @Override
- public Set<ApplicationUsage> getApplicationUsage(Predicate<? super ApplicationUsage> filter) {
- // TODO could do more efficient indexing, to more easily find locations in use during a given period.
- // But this is good enough for first-pass.
-
- Map<String, ApplicationUsage> usageMap = managementContext.getStorage().getMap(APPLICATION_USAGE_KEY);
- Set<ApplicationUsage> result = Sets.newLinkedHashSet();
-
- for (ApplicationUsage usage : usageMap.values()) {
- if (filter.apply(usage)) {
- result.add(usage);
- }
- }
- return result;
- }
-
- @Override
- @Deprecated
- public void addUsageListener(brooklyn.management.internal.UsageManager.UsageListener listener) {
- addUsageListener(new brooklyn.management.internal.UsageManager.UsageListener.UsageListenerAdapter(listener));
- }
-
- @Override
- @Deprecated
- public void removeUsageListener(brooklyn.management.internal.UsageManager.UsageListener listener) {
- removeUsageListener(new brooklyn.management.internal.UsageManager.UsageListener.UsageListenerAdapter(listener));
- }
-
- @Override
- public void addUsageListener(brooklyn.management.internal.UsageListener listener) {
- listeners.add(listener);
- }
-
- @Override
- public void removeUsageListener(brooklyn.management.internal.UsageListener listener) {
- listeners.remove(listener);
- }
-
- private String getUser() {
- EntitlementContext entitlementContext = Entitlements.getEntitlementContext();
- if (entitlementContext != null) {
- return entitlementContext.user();
- }
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java b/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java
deleted file mode 100644
index 17ecd5a..0000000
--- a/core/src/main/java/brooklyn/management/internal/LocationManagerInternal.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.LocationManager;
-
-public interface LocationManagerInternal extends LocationManager, BrooklynObjectManagerInternal<Location> {
-
- public Iterable<String> getLocationIds();
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
deleted file mode 100644
index b21f73f..0000000
--- a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.net.URI;
-import java.net.URL;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-
-import org.apache.brooklyn.api.entity.Effector;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.Task;
-
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.entity.proxying.InternalLocationFactory;
-import brooklyn.entity.proxying.InternalPolicyFactory;
-import brooklyn.internal.storage.BrooklynStorage;
-import brooklyn.management.ha.OsgiManager;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.TaskTags;
-
-import com.google.common.annotations.Beta;
-
-public interface ManagementContextInternal extends ManagementContext {
-
- public static final String SUB_TASK_TAG = TaskTags.SUB_TASK_TAG;
-
- public static final String EFFECTOR_TAG = BrooklynTaskTags.EFFECTOR_TAG;
- public static final String NON_TRANSIENT_TASK_TAG = BrooklynTaskTags.NON_TRANSIENT_TASK_TAG;
- public static final String TRANSIENT_TASK_TAG = BrooklynTaskTags.TRANSIENT_TASK_TAG;
-
- public static final String EMPTY_CATALOG_URL = "classpath://brooklyn/empty.catalog.bom";
-
- ClassLoader getBaseClassLoader();
-
- Iterable<URL> getBaseClassPathForScanning();
-
- void setBaseClassPathForScanning(Iterable<URL> urls);
-
- void setManagementNodeUri(URI uri);
-
- void addEntitySetListener(CollectionChangeListener<Entity> listener);
-
- void removeEntitySetListener(CollectionChangeListener<Entity> listener);
-
- void terminate();
-
- long getTotalEffectorInvocations();
-
- <T> T invokeEffectorMethodSync(final Entity entity, final Effector<T> eff, final Object args) throws ExecutionException;
-
- <T> Task<T> invokeEffector(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters);
-
- BrooklynStorage getStorage();
-
- BrooklynProperties getBrooklynProperties();
-
- AccessManager getAccessManager();
-
- UsageManager getUsageManager();
-
- /**
- * @return The OSGi manager, if available; may be absent if OSGi is not supported,
- * e.g. in test contexts (but will be supported in all major contexts).
- */
- Maybe<OsgiManager> getOsgiManager();
-
- InternalEntityFactory getEntityFactory();
-
- InternalLocationFactory getLocationFactory();
-
- InternalPolicyFactory getPolicyFactory();
-
- /**
- * Registers an entity that has been created, but that has not yet begun to be managed.
- * <p>
- * This differs from the idea of "preManaged" where the entities are in the process of being
- * managed, but where management is not yet complete.
- */
- // TODO would benefit from better naming! The name has percolated up from LocalEntityManager.
- // should we just rename here as register or preManage?
- void prePreManage(Entity entity);
-
- /**
- * Registers a location that has been created, but that has not yet begun to be managed.
- */
- void prePreManage(Location location);
-
- /** Object which allows adding, removing, and clearing errors.
- * TODO In future this will change to a custom interface with a unique identifier for each error. */
- @Beta
- List<Throwable> errors();
-
- @Beta
- CatalogInitialization getCatalogInitialization();
-
- @Beta
- void setCatalogInitialization(CatalogInitialization catalogInitialization);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java b/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
deleted file mode 100644
index c16ff8e..0000000
--- a/core/src/main/java/brooklyn/management/internal/ManagementTransitionInfo.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-
-/** Stores a management transition mode, and the management context. */
-// TODO does this class really pull its weight?
-public class ManagementTransitionInfo {
-
- final ManagementContext mgmtContext;
- final ManagementTransitionMode mode;
-
- public ManagementTransitionInfo(ManagementContext mgmtContext, ManagementTransitionMode mode) {
- this.mgmtContext = mgmtContext;
- this.mode = mode;
- }
-
-
- public ManagementContext getManagementContext() {
- return mgmtContext;
- }
-
- public ManagementTransitionMode getMode() {
- return mode;
- }
-
- @Override
- public String toString() {
- return super.toString()+"["+mgmtContext+";"+mode+"]";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java b/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
deleted file mode 100644
index 1d25902..0000000
--- a/core/src/main/java/brooklyn/management/internal/ManagementTransitionMode.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Records details of a management transition, specifically the {@link BrooklynObjectManagementMode} before and after,
- * and allows easy checking of various aspects of that.
- * <p>
- * This helps make code readable and keep correct logic if we expand/change the management modes.
- */
-public class ManagementTransitionMode {
-
- private static final Logger log = LoggerFactory.getLogger(ManagementTransitionMode.class);
-
- private final BrooklynObjectManagementMode modeBefore, modeAfter;
-
- private ManagementTransitionMode(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
- this.modeBefore = modeBefore;
- this.modeAfter = modeAfter;
- }
-
- public static ManagementTransitionMode transitioning(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
- return new ManagementTransitionMode(Preconditions.checkNotNull(modeBefore, "modeBefore"), Preconditions.checkNotNull(modeAfter, "modeAfter"));
- }
-
- @Deprecated /** @deprecated marking places where we aren't sure */
- public static ManagementTransitionMode guessing(BrooklynObjectManagementMode modeBefore, BrooklynObjectManagementMode modeAfter) {
- return transitioning(modeBefore, modeAfter);
- }
-
- /** @return the mode this object was previously managed as */
- public BrooklynObjectManagementMode getModeBefore() {
- return modeBefore;
- }
-
- /** @return the mode this object is now being managed as */
- public BrooklynObjectManagementMode getModeAfter() {
- return modeAfter;
- }
-
- /** This management node was previously not loaded here,
- * either it did not exist (and is just being created) or it was in persisted state but
- * not loaded at this node. */
- public boolean wasNotLoaded() {
- return getModeBefore()==BrooklynObjectManagementMode.NONEXISTENT || getModeBefore()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED;
- }
-
- /** This management node is now not going to be loaded here, either it is being destroyed
- * (not known anywhere, not even persisted) or simply forgotten here */
- public boolean isNoLongerLoaded() {
- return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT || getModeAfter()==BrooklynObjectManagementMode.UNMANAGED_PERSISTED;
- }
-
- /** This management node was the master for the given object */
- public boolean wasPrimary() {
- return getModeBefore()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
- }
-
- /** This management node is now the master for the given object */
- public boolean isPrimary() {
- return getModeAfter()==BrooklynObjectManagementMode.MANAGED_PRIMARY;
- }
-
- /** Object was previously loaded as read-only at this management node;
- * active management was occurring elsewhere (or not at all)
- */
- public boolean wasReadOnly() {
- return getModeBefore()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
- }
-
- /** Object is now being loaded as read-only at this management node;
- * expect active management to be occurring elsewhere
- */
- public boolean isReadOnly() {
- return getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY;
- }
-
- /** Object is being created:
- * previously did not exist (not even in persisted state);
- * implies that we are the active manager creating it,
- * i.e. {@link #getModeAfter()} should indicate {@link BrooklynObjectManagementMode#MANAGED_PRIMARY}.
- * (if we're read-only and the manager has just created it,
- * {@link #getModeBefore()} should indicate {@link BrooklynObjectManagementMode#UNMANAGED_PERSISTED})
- */
- public boolean isCreating() {
- if (getModeBefore()!=BrooklynObjectManagementMode.NONEXISTENT)
- return false;
-
- if (getModeAfter()==BrooklynObjectManagementMode.LOADED_READ_ONLY) {
- log.warn("isCreating set on RO object; highly irregular!");
- }
- return true;
- }
-
- /** Object is being destroyed:
- * either destroyed elsewhere and we're catching up (in read-only mode),
- * or we've been the active manager and are destroying it */
- public boolean isDestroying() {
- return getModeAfter()==BrooklynObjectManagementMode.NONEXISTENT;
- }
-
- @Override
- public String toString() {
- return ManagementTransitionMode.class.getSimpleName()+"["+getModeBefore()+"->"+getModeAfter()+"]";
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/NonDeploymentAccessManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentAccessManager.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentAccessManager.java
deleted file mode 100644
index 4cc6bba..0000000
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentAccessManager.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import org.apache.brooklyn.api.management.AccessController;
-
-
-public class NonDeploymentAccessManager implements AccessManager {
-
- private final ManagementContextInternal initialManagementContext;
-
- public NonDeploymentAccessManager(ManagementContextInternal initialManagementContext) {
- this.initialManagementContext = initialManagementContext;
- }
-
- private boolean isInitialManagementContextReal() {
- return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
- }
-
- @Override
- public AccessController getAccessController() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getAccessManager().getAccessController();
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public boolean isLocationProvisioningAllowed() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getAccessManager().isLocationProvisioningAllowed();
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public boolean isLocationManagementAllowed() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getAccessManager().isLocationManagementAllowed();
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public boolean isEntityManagementAllowed() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getAccessManager().isEntityManagementAllowed();
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public void setLocationProvisioningAllowed(boolean allowed) {
- if (isInitialManagementContextReal()) {
- initialManagementContext.getAccessManager().setLocationProvisioningAllowed(allowed);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public void setLocationManagementAllowed(boolean allowed) {
- if (isInitialManagementContextReal()) {
- initialManagementContext.getAccessManager().setLocationManagementAllowed(allowed);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public void setEntityManagementAllowed(boolean allowed) {
- if (isInitialManagementContextReal()) {
- initialManagementContext.getAccessManager().setEntityManagementAllowed(allowed);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java
deleted file mode 100644
index 8b85975..0000000
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentEntityManager.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.entity.proxying.EntityTypeRegistry;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.policy.Enricher;
-import org.apache.brooklyn.api.policy.EnricherSpec;
-import org.apache.brooklyn.api.policy.Policy;
-import org.apache.brooklyn.api.policy.PolicySpec;
-
-import com.google.common.base.Predicate;
-
-public class NonDeploymentEntityManager implements EntityManagerInternal {
-
- private final ManagementContext initialManagementContext;
-
- public NonDeploymentEntityManager(ManagementContext initialManagementContext) {
- this.initialManagementContext = initialManagementContext;
- }
-
- @Override
- public EntityTypeRegistry getEntityTypeRegistry() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().getEntityTypeRegistry();
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
- }
- }
-
- @Override
- public <T extends Entity> T createEntity(EntitySpec<T> spec) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().createEntity(spec);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
- }
- }
-
- @Override
- public <T extends Entity> T createEntity(Map<?,?> config, Class<T> type) {
- return createEntity(EntitySpec.create(type).configure(config));
- }
-
- @Override
- public <T extends Policy> T createPolicy(PolicySpec<T> spec) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().createPolicy(spec);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
- }
- }
-
- @Override
- public <T extends Enricher> T createEnricher(EnricherSpec<T> spec) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().createEnricher(spec);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
- }
- }
-
- @Override
- public Collection<Entity> getEntities() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().getEntities();
- } else {
- return Collections.emptyList();
- }
- }
-
- @Override
- public Collection<Entity> getEntitiesInApplication(Application application) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().getEntitiesInApplication(application);
- } else {
- return Collections.emptyList();
- }
- }
-
- @Override
- public Collection<Entity> findEntities(Predicate<? super Entity> filter) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().findEntities(filter);
- } else {
- return Collections.emptyList();
- }
- }
-
- @Override
- public Collection<Entity> findEntitiesInApplication(Application application, Predicate<? super Entity> filter) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().findEntitiesInApplication(application, filter);
- } else {
- return Collections.emptyList();
- }
- }
-
- @Override
- public Entity getEntity(String id) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getEntityManager().getEntity(id);
- } else {
- return null;
- }
- }
-
- @Override
- public Iterable<String> getEntityIds() {
- if (isInitialManagementContextReal()) {
- return ((EntityManagerInternal)initialManagementContext.getEntityManager()).getEntityIds();
- } else {
- return Collections.emptyList();
- }
- }
-
- @Override
- public ManagementTransitionMode getLastManagementTransitionMode(String itemId) {
- if (isInitialManagementContextReal()) {
- return ((EntityManagerInternal)initialManagementContext.getEntityManager()).getLastManagementTransitionMode(itemId);
- } else {
- return null;
- }
- }
-
- @Override
- public void setManagementTransitionMode(Entity item, ManagementTransitionMode mode) {
- if (isInitialManagementContextReal()) {
- ((EntityManagerInternal)initialManagementContext.getEntityManager()).setManagementTransitionMode(item, mode);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public boolean isManaged(Entity entity) {
- return false;
- }
-
- @Override
- public void manage(Entity e) {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot manage "+e);
- }
-
- @Override
- public void unmanage(Entity e, ManagementTransitionMode info) {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
-
- @Override
- public void manageRebindedRoot(Entity item) {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
-
- @Override
- public void unmanage(Entity e) {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot unmanage "+e);
- }
-
- private boolean isInitialManagementContextReal() {
- return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
- }
-
- @Override
- public Iterable<Entity> getAllEntitiesInApplication(Application application) {
- if (isInitialManagementContextReal()) {
- return ((EntityManagerInternal)initialManagementContext.getEntityManager()).getAllEntitiesInApplication(application);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" (with no initial management context supplied) is not valid for this operation.");
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java b/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java
deleted file mode 100644
index 5d68db6..0000000
--- a/core/src/main/java/brooklyn/management/internal/NonDeploymentLocationManager.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.LocationSpec;
-import org.apache.brooklyn.api.management.ManagementContext;
-
-public class NonDeploymentLocationManager implements LocationManagerInternal {
-
- private final ManagementContext initialManagementContext;
-
- public NonDeploymentLocationManager(ManagementContext initialManagementContext) {
- this.initialManagementContext = initialManagementContext;
- }
-
- @Override
- public <T extends Location> T createLocation(LocationSpec<T> spec) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getLocationManager().createLocation(spec);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot create "+spec);
- }
- }
-
- @Override
- public <T extends Location> T createLocation(Map<?, ?> config, Class<T> type) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getLocationManager().createLocation(config, type);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot create "+type);
- }
- }
-
- @Override
- public Collection<Location> getLocations() {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getLocationManager().getLocations();
- } else {
- return Collections.emptyList();
- }
- }
-
- @Override
- public Location getLocation(String id) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getLocationManager().getLocation(id);
- } else {
- return null;
- }
- }
-
- @Override
- public Iterable<String> getLocationIds() {
- if (isInitialManagementContextReal()) {
- return ((LocationManagerInternal)initialManagementContext.getLocationManager()).getLocationIds();
- } else {
- return Collections.emptyList();
- }
- }
-
- @Override
- public boolean isManaged(Location loc) {
- return false;
- }
-
- @Override
- public void manageRebindedRoot(Location loc) {
- if (isInitialManagementContextReal()) {
- ((LocationManagerInternal)initialManagementContext.getLocationManager()).manageRebindedRoot(loc);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot manage "+loc);
- }
- }
-
- @Override
- @Deprecated
- public Location manage(Location loc) {
- if (isInitialManagementContextReal()) {
- return initialManagementContext.getLocationManager().manage(loc);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot manage "+loc);
- }
- }
-
-
- @Override
- public ManagementTransitionMode getLastManagementTransitionMode(String itemId) {
- if (isInitialManagementContextReal()) {
- return ((LocationManagerInternal)initialManagementContext.getLocationManager()).getLastManagementTransitionMode(itemId);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public void setManagementTransitionMode(Location item, ManagementTransitionMode mode) {
- if (isInitialManagementContextReal()) {
- ((LocationManagerInternal)initialManagementContext.getLocationManager()).setManagementTransitionMode(item, mode);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public void unmanage(Location item, ManagementTransitionMode info) {
- if (isInitialManagementContextReal()) {
- ((LocationManagerInternal)initialManagementContext.getLocationManager()).unmanage(item, info);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation");
- }
- }
-
- @Override
- public void unmanage(Location loc) {
- if (isInitialManagementContextReal()) {
- initialManagementContext.getLocationManager().unmanage(loc);
- } else {
- throw new IllegalStateException("Non-deployment context "+this+" is not valid for this operation: cannot unmanage "+loc);
- }
- }
-
- private boolean isInitialManagementContextReal() {
- return (initialManagementContext != null && !(initialManagementContext instanceof NonDeploymentManagementContext));
- }
-}
[04/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/TestEntityFailingRebind.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/TestEntityFailingRebind.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/TestEntityFailingRebind.java
new file mode 100644
index 0000000..974f5d7
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/TestEntityFailingRebind.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import org.apache.brooklyn.test.entity.TestApplicationImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestEntityFailingRebind extends TestApplicationImpl {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TestEntityFailingRebind.class);
+
+ public static class RebindException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public RebindException(String message) {
+ super(message);
+ }
+ }
+
+ private static boolean throwOnRebind = true;
+
+ public static void setThrowOnRebind(boolean state) {
+ throwOnRebind = state;
+ }
+
+ public static boolean getThrowOnRebind() {
+ return throwOnRebind;
+ }
+
+ @Override
+ public void rebind() {
+ if (throwOnRebind) {
+ LOG.warn("Throwing intentional exception to simulate failure of rebinding " + this);
+ throw new RebindException("Intentional exception thrown when rebinding " + this);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/WarmStandbyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/WarmStandbyTest.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/WarmStandbyTest.java
new file mode 100644
index 0000000..8324c16
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/WarmStandbyTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.InMemoryObjectStore;
+import brooklyn.entity.rebind.persister.ListeningObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.time.Duration;
+
+@Test
+public class WarmStandbyTest {
+
+ private static final Logger log = LoggerFactory.getLogger(WarmStandbyTest.class);
+
+ private List<HaMgmtNode> nodes = new MutableList<WarmStandbyTest.HaMgmtNode>();
+ Map<String,String> sharedBackingStore = MutableMap.of();
+ Map<String,Date> sharedBackingStoreDates = MutableMap.of();
+ private ClassLoader classLoader = getClass().getClassLoader();
+
+ public class HaMgmtNode {
+ // TODO share with HotStandbyTest and SplitBrainTest and a few others (minor differences but worth it ultimately)
+
+ private ManagementContextInternal mgmt;
+ private String ownNodeId;
+ private String nodeName;
+ private ListeningObjectStore objectStore;
+ private ManagementPlaneSyncRecordPersister persister;
+ private HighAvailabilityManagerImpl ha;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ nodeName = "node "+nodes.size();
+ mgmt = newLocalManagementContext();
+ ownNodeId = mgmt.getManagementNodeId();
+ objectStore = new ListeningObjectStore(newPersistenceObjectStore());
+ objectStore.injectManagementContext(mgmt);
+ objectStore.prepareForSharedUse(PersistMode.CLEAN, HighAvailabilityMode.DISABLED);
+ persister = new ManagementPlaneSyncRecordPersisterToObjectStore(mgmt, objectStore, classLoader);
+ ((ManagementPlaneSyncRecordPersisterToObjectStore)persister).preferRemoteTimestampInMemento();
+ BrooklynMementoPersisterToObjectStore persisterObj = new BrooklynMementoPersisterToObjectStore(objectStore, mgmt.getBrooklynProperties(), classLoader);
+ mgmt.getRebindManager().setPersister(persisterObj, PersistenceExceptionHandlerImpl.builder().build());
+ ha = ((HighAvailabilityManagerImpl)mgmt.getHighAvailabilityManager())
+ .setPollPeriod(Duration.PRACTICALLY_FOREVER)
+ .setHeartbeatTimeout(Duration.THIRTY_SECONDS)
+ .setPersister(persister);
+ log.info("Created "+nodeName+" "+ownNodeId);
+ }
+
+ public void tearDown() throws Exception {
+ if (ha != null) ha.stop();
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ if (objectStore != null) objectStore.deleteCompletely();
+ }
+
+ @Override
+ public String toString() {
+ return nodeName+" "+ownNodeId;
+ }
+ }
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ nodes.clear();
+ sharedBackingStore.clear();
+ }
+
+ public HaMgmtNode newNode() throws Exception {
+ HaMgmtNode node = new HaMgmtNode();
+ node.setUp();
+ nodes.add(node);
+ return node;
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ for (HaMgmtNode n: nodes)
+ n.tearDown();
+ }
+
+ protected ManagementContextInternal newLocalManagementContext() {
+ return new LocalManagementContextForTests();
+ }
+
+ protected PersistenceObjectStore newPersistenceObjectStore() {
+ return new InMemoryObjectStore(sharedBackingStore, sharedBackingStoreDates);
+ }
+
+ // TODO refactor above -- routines above this line are shared among HotStandbyTest and SplitBrainTest
+
+ @Test
+ public void testWarmStandby() throws Exception {
+ HaMgmtNode n1 = newNode();
+ n1.ha.start(HighAvailabilityMode.AUTO);
+ assertEquals(n1.ha.getNodeState(), ManagementNodeState.MASTER);
+
+ TestApplication app = TestApplication.Factory.newManagedInstanceForTests(n1.mgmt);
+ app.start(MutableList.<Location>of());
+
+ n1.mgmt.getRebindManager().forcePersistNow(false, null);
+
+ HaMgmtNode n2 = newNode();
+ n2.ha.start(HighAvailabilityMode.STANDBY);
+ assertEquals(n2.ha.getNodeState(), ManagementNodeState.STANDBY);
+
+ assertEquals(n2.mgmt.getApplications().size(), 0);
+ }
+
+ // TODO support forcible demotion, and check that a master forcibly demoted
+ // to warm standby clears its apps, policies, and locations
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/internal/AccessManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/internal/AccessManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/management/internal/AccessManagerTest.java
new file mode 100644
index 0000000..891c3a4
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/internal/AccessManagerTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.Entities;
+
+import org.apache.brooklyn.location.basic.SimulatedLocation;
+
+import brooklyn.util.exceptions.Exceptions;
+
+import com.google.common.collect.ImmutableSet;
+
+public class AccessManagerTest {
+
+ private LocalManagementContext managementContext;
+ private TestApplication app;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ managementContext = new LocalManagementContextForTests();
+ app = ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (managementContext != null) Entities.destroyAll(managementContext);
+ app = null;
+ }
+
+ @Test
+ public void testEntityManagementAllowed() throws Exception {
+ // default is allowed
+ TestEntity e1 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ // when forbidden, should give error trying to create+manage new entity
+ managementContext.getAccessManager().setEntityManagementAllowed(false);
+ try {
+ app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ fail();
+ } catch (Exception e) {
+ // expect it to be forbidden
+ if (Exceptions.getFirstThrowableOfType(e, IllegalStateException.class) == null) {
+ throw e;
+ }
+ }
+
+ // when forbidden, should refuse to create new app
+ try {
+ ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
+ fail();
+ } catch (Exception e) {
+ // expect it to be forbidden
+ if (Exceptions.getFirstThrowableOfType(e, IllegalStateException.class) == null) {
+ throw e;
+ }
+ }
+
+ // but when forbidden, still allowed to create locations
+ managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+
+ // when re-enabled, can create entities again
+ managementContext.getAccessManager().setEntityManagementAllowed(true);
+ TestEntity e3 = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ assertEquals(ImmutableSet.copyOf(managementContext.getEntityManager().getEntities()), ImmutableSet.of(app, e1, e3));
+ }
+
+ @Test
+ public void testLocationManagementAllowed() throws Exception {
+ // default is allowed
+ Location loc1 = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+
+ // when forbidden, should give error
+ managementContext.getAccessManager().setLocationManagementAllowed(false);
+ try {
+ managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+ fail();
+ } catch (Exception e) {
+ // expect it to be forbidden
+ if (Exceptions.getFirstThrowableOfType(e, IllegalStateException.class) == null) {
+ throw e;
+ }
+ }
+
+ // but when forbidden, still allowed to create entity
+ ApplicationBuilder.newManagedApp(TestApplication.class, managementContext);
+
+ // when re-enabled, can create entities again
+ managementContext.getAccessManager().setLocationManagementAllowed(true);
+ Location loc3 = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+
+ assertEquals(ImmutableSet.copyOf(managementContext.getLocationManager().getLocations()), ImmutableSet.of(loc1, loc3));
+ }
+
+ @Test
+ public void testLocationProvisioningAllowed() throws Exception {
+ SimulatedLocation loc = managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+
+ // default is allowed
+ assertTrue(managementContext.getAccessController().canProvisionLocation(loc).isAllowed());
+
+ // when forbidden, should say so
+ managementContext.getAccessManager().setLocationProvisioningAllowed(false);
+ assertFalse(managementContext.getAccessController().canProvisionLocation(loc).isAllowed());
+
+ // but when forbidden, still allowed to create locations
+ managementContext.getLocationManager().createLocation(LocationSpec.create(SimulatedLocation.class));
+
+ // when re-enabled, can create entities again
+ managementContext.getAccessManager().setLocationProvisioningAllowed(true);
+ assertTrue(managementContext.getAccessController().canProvisionLocation(loc).isAllowed());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java
new file mode 100644
index 0000000..7f35bba
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/internal/EntityExecutionManagerTest.java
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Semaphore;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.BrooklynGarbageCollector;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.BrooklynTaskTags.WrappedEntity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.event.basic.BasicAttributeSensor;
+import brooklyn.test.Asserts;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.task.BasicExecutionManager;
+import brooklyn.util.task.ExecutionListener;
+import brooklyn.util.task.TaskBuilder;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Callables;
+
+/** Includes many tests for {@link BrooklynGarbageCollector} */
+public class EntityExecutionManagerTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EntityExecutionManagerTest.class);
+
+ private static final Duration TIMEOUT_MS = Duration.TEN_SECONDS;
+
+ private ManagementContextInternal mgmt;
+ private TestApplication app;
+ private TestEntity e;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ app = null;
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ }
+
+ @Test
+ public void testOnDoneCallback() throws InterruptedException {
+ mgmt = LocalManagementContextForTests.newInstance();
+ ExecutionManager em = mgmt.getExecutionManager();
+ BasicExecutionManager bem = (BasicExecutionManager)em;
+ final Map<Task<?>,Duration> completedTasks = MutableMap.of();
+ final Semaphore sema4 = new Semaphore(-1);
+ bem.addListener(new ExecutionListener() {
+ @Override
+ public void onTaskDone(Task<?> task) {
+ Assert.assertTrue(task.isDone());
+ Assert.assertEquals(task.getUnchecked(), "foo");
+ completedTasks.put(task, Duration.sinceUtc(task.getEndTimeUtc()));
+ sema4.release();
+ }
+ });
+ Task<String> t1 = em.submit( Tasks.<String>builder().name("t1").dynamic(false).body(Callables.returning("foo")).build() );
+ t1.getUnchecked();
+ Task<String> t2 = em.submit( Tasks.<String>builder().name("t2").dynamic(false).body(Callables.returning("foo")).build() );
+ sema4.acquire();
+ Assert.assertEquals(completedTasks.size(), 2, "completed tasks are: "+completedTasks);
+ completedTasks.get(t1).isShorterThan(Duration.TEN_SECONDS);
+ completedTasks.get(t2).isShorterThan(Duration.TEN_SECONDS);
+ }
+
+ protected void forceGc() {
+ ((LocalManagementContext)app.getManagementContext()).getGarbageCollector().gcIteration();
+ }
+
+ protected static Task<?> runEmptyTaskWithNameAndTags(Entity target, String name, Object ...tags) {
+ TaskBuilder<Object> tb = newEmptyTask(name);
+ for (Object tag: tags) tb.tag(tag);
+ Task<?> task = ((EntityInternal)target).getExecutionContext().submit(tb.build());
+ task.getUnchecked();
+ return task;
+ }
+
+ protected static TaskBuilder<Object> newEmptyTask(String name) {
+ return Tasks.builder().name(name).dynamic(false).body(Callables.returning(null));
+ }
+
+ protected void assertTaskCountForEntitySoon(final Entity entity, final int expectedCount) {
+ // Dead task (and initialization task) should have been GC'd on completion.
+ // However, the GC'ing happens in a listener, executed in a different thread - the task.get()
+ // doesn't block for it. Therefore can't always guarantee it will be GC'ed by now.
+ Repeater.create().backoff(Duration.millis(10), 2, Duration.millis(500)).limitTimeTo(Duration.TEN_SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ forceGc();
+ Collection<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(((EntityInternal)entity).getManagementContext().getExecutionManager(), entity);
+ Assert.assertEquals(tasks.size(), expectedCount, "Tasks were "+tasks);
+ return true;
+ }
+ }).runRequiringTrue();
+ }
+
+ @Test
+ public void testGetTasksAndGcBoringTags() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ final Task<?> task = runEmptyTaskWithNameAndTags(e, "should-be-kept", ManagementContextInternal.NON_TRANSIENT_TASK_TAG);
+ runEmptyTaskWithNameAndTags(e, "should-be-gcd", ManagementContextInternal.TRANSIENT_TASK_TAG);
+
+ assertTaskCountForEntitySoon(e, 1);
+ Collection<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(app.getManagementContext().getExecutionManager(), e);
+ assertEquals(tasks, ImmutableList.of(task), "Mismatched tasks, got: "+tasks);
+ }
+
+ @Test
+ public void testGcTaskAtNormalTagLimit() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ ((BrooklynProperties)app.getManagementContext().getConfig()).put(
+ BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
+
+ for (int count=0; count<5; count++)
+ runEmptyTaskWithNameAndTags(e, "task"+count, ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
+
+ assertTaskCountForEntitySoon(e, 2);
+ }
+
+ @Test
+ public void testGcTaskAtEntityLimit() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ ((BrooklynProperties)app.getManagementContext().getConfig()).put(
+ BrooklynGarbageCollector.MAX_TASKS_PER_ENTITY, 2);
+
+ for (int count=0; count<5; count++)
+ runEmptyTaskWithNameAndTags(e, "task-e-"+count, ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
+ for (int count=0; count<5; count++)
+ runEmptyTaskWithNameAndTags(app, "task-app-"+count, ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
+
+ assertTaskCountForEntitySoon(app, 2);
+ assertTaskCountForEntitySoon(e, 2);
+ }
+
+ @Test
+ public void testGcTaskWithTagAndEntityLimit() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ ((BrooklynProperties)app.getManagementContext().getConfig()).put(
+ BrooklynGarbageCollector.MAX_TASKS_PER_ENTITY, 6);
+ ((BrooklynProperties)app.getManagementContext().getConfig()).put(
+ BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
+
+ int count=0;
+
+ runEmptyTaskWithNameAndTags(app, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
+ runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
+ Time.sleep(Duration.ONE_MILLISECOND);
+ // should keep the 2 below, because all the other borings get grace, but delete the ones above
+ runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
+ runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag");
+
+ runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag", "another-tag-e");
+ runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "boring-tag", "another-tag-e");
+ // should keep both the above
+
+ runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag");
+ runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag");
+ Time.sleep(Duration.ONE_MILLISECOND);
+ runEmptyTaskWithNameAndTags(app, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag");
+ // should keep the below since they have unique tags, but remove one of the e tasks above
+ runEmptyTaskWithNameAndTags(e, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag", "and-another-tag");
+ runEmptyTaskWithNameAndTags(app, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag-app", "another-tag");
+ runEmptyTaskWithNameAndTags(app, "task-"+(count++), ManagementContextInternal.NON_TRANSIENT_TASK_TAG, "another-tag-app", "another-tag");
+
+ assertTaskCountForEntitySoon(e, 6);
+ assertTaskCountForEntitySoon(app, 3);
+
+ // now with a lowered limit, we should remove one more e
+ ((BrooklynProperties)app.getManagementContext().getConfig()).put(
+ BrooklynGarbageCollector.MAX_TASKS_PER_ENTITY, 5);
+ assertTaskCountForEntitySoon(e, 5);
+ }
+
+ @Test
+ public void testGcDynamicTaskAtNormalTagLimit() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ ((BrooklynProperties)app.getManagementContext().getConfig()).put(
+ BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
+
+ for (int count=0; count<5; count++) {
+ TaskBuilder<Object> tb = Tasks.builder().name("task-"+count).dynamic(true).body(new Runnable() { @Override public void run() {}})
+ .tag(ManagementContextInternal.NON_TRANSIENT_TASK_TAG).tag("foo");
+ ((EntityInternal)e).getExecutionContext().submit(tb.build()).getUnchecked();
+ }
+
+ // might need an eventually here, if the internal job completion and GC is done in the background
+ // (if there are no test failures for a few months, since Sept 2014, then we can remove this comment)
+ assertTaskCountForEntitySoon(e, 2);
+ }
+
+ @Test
+ public void testUnmanagedEntityCanBeGcedEvenIfPreviouslyTagged() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ e = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ String eId = e.getId();
+
+ e.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of()).get();
+ Set<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(app.getManagementContext().getExecutionManager(), e);
+ Task<?> task = Iterables.get(tasks, 0);
+ assertTrue(task.getTags().contains(BrooklynTaskTags.tagForContextEntity(e)));
+
+ Set<Object> tags = app.getManagementContext().getExecutionManager().getTaskTags();
+ assertTrue(tags.contains(BrooklynTaskTags.tagForContextEntity(e)), "tags="+tags);
+
+ Entities.destroy(e);
+ forceGc();
+
+ Set<Object> tags2 = app.getManagementContext().getExecutionManager().getTaskTags();
+ for (Object tag : tags2) {
+ if (tag instanceof Entity && ((Entity)tag).getId().equals(eId)) {
+ fail("tags contains unmanaged entity "+tag);
+ }
+ if ((tag instanceof WrappedEntity) && ((WrappedEntity)tag).entity.getId().equals(eId)
+ && ((WrappedEntity)tag).wrappingType.equals(BrooklynTaskTags.CONTEXT_ENTITY)) {
+ fail("tags contains unmanaged entity (wrapped) "+tag);
+ }
+ }
+ return;
+ }
+
+ @Test(groups="Integration")
+ public void testSubscriptionAndEffectorTasksGced() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+ BasicExecutionManager em = (BasicExecutionManager) app.getManagementContext().getExecutionManager();
+ // allow background enrichers to complete
+ Time.sleep(Duration.ONE_SECOND);
+ forceGc();
+ List<Task<?>> t1 = em.getAllTasks();
+
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ entity.setAttribute(TestEntity.NAME, "bob");
+ entity.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of()).get();
+ Entities.destroy(entity);
+ Time.sleep(Duration.ONE_SECOND);
+ forceGc();
+ List<Task<?>> t2 = em.getAllTasks();
+
+ Assert.assertEquals(t1.size(), t2.size(), "lists are different:\n"+t1+"\n"+t2+"\n");
+ }
+
+ /**
+ * Invoke effector many times, where each would claim 10MB because it stores the return value.
+ * If it didn't gc the tasks promptly, it would consume 10GB ram (so would OOME before that).
+ */
+ @Test(groups="Integration")
+ public void testEffectorTasksGcedSoNoOome() throws Exception {
+
+ BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
+ brooklynProperties.put(BrooklynGarbageCollector.GC_PERIOD, Duration.ONE_MILLISECOND);
+ brooklynProperties.put(BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
+
+ app = ApplicationBuilder.newManagedApp(TestApplication.class, LocalManagementContextForTests.newInstance(brooklynProperties));
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ for (int i = 0; i < 1000; i++) {
+ if (i%100==0) LOG.info(JavaClassNames.niceClassAndMethod()+": iteration "+i);
+ try {
+ LOG.debug("testEffectorTasksGced: iteration="+i);
+ entity.invoke(TestEntity.IDENTITY_EFFECTOR, ImmutableMap.of("arg", new BigObject(10*1000*1000))).get();
+
+ Time.sleep(Duration.ONE_MILLISECOND); // Give GC thread a chance to run
+ forceGc();
+ } catch (OutOfMemoryError e) {
+ LOG.warn(JavaClassNames.niceClassAndMethod()+": OOME at iteration="+i);
+ throw e;
+ }
+ }
+ }
+
+ @Test(groups="Integration")
+ public void testUnmanagedEntityGcedOnUnmanageEvenIfEffectorInvoked() throws Exception {
+ app = TestApplication.Factory.newManagedInstanceForTests();
+
+ BasicAttributeSensor<Object> byteArrayAttrib = new BasicAttributeSensor<Object>(Object.class, "test.byteArray", "");
+
+ for (int i = 0; i < 1000; i++) {
+ if (i<100 && i%10==0 || i%100==0) LOG.info(JavaClassNames.niceClassAndMethod()+": iteration "+i);
+ try {
+ LOG.debug(JavaClassNames.niceClassAndMethod()+": iteration="+i);
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ entity.setAttribute(byteArrayAttrib, new BigObject(10*1000*1000));
+ entity.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of()).get();
+
+ // we get exceptions because tasks are still trying to publish after deployment;
+ // this should prevent them
+// ((LocalEntityManager)app.getManagementContext().getEntityManager()).stopTasks(entity, Duration.ONE_SECOND);
+// Entities.destroy(entity);
+
+ // alternatively if we 'unmanage' instead of destroy, there are usually not errors
+ // (the errors come from the node transitioning to a 'stopping' state on destroy,
+ // and publishing lots of info then)
+ Entities.unmanage(entity);
+
+ forceGc();
+ // previously we did an extra GC but it was crazy slow, shouldn't be needed
+// System.gc(); System.gc();
+ } catch (OutOfMemoryError e) {
+ LOG.warn(JavaClassNames.niceClassAndMethod()+": OOME at iteration="+i);
+ ExecutionManager em = app.getManagementContext().getExecutionManager();
+ Collection<Task<?>> tasks = ((BasicExecutionManager)em).getAllTasks();
+ LOG.info("TASKS count "+tasks.size()+": "+tasks);
+ throw e;
+ }
+ }
+ }
+
+ @Test(groups={"Integration"})
+ public void testEffectorTasksGcedForMaxPerTag() throws Exception {
+ int maxNumTasks = 2;
+ BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
+ brooklynProperties.put(BrooklynGarbageCollector.GC_PERIOD, Duration.ONE_SECOND);
+ brooklynProperties.put(BrooklynGarbageCollector.MAX_TASKS_PER_TAG, 2);
+
+ app = ApplicationBuilder.newManagedApp(TestApplication.class, LocalManagementContextForTests.newInstance(brooklynProperties));
+ final TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ List<Task<?>> tasks = Lists.newArrayList();
+
+ for (int i = 0; i < (maxNumTasks+1); i++) {
+ Task<?> task = entity.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of());
+ task.get();
+ tasks.add(task);
+
+ // TASKS_OLDEST_FIRST_COMPARATOR is based on comparing EndTimeUtc; but two tasks executed in
+ // rapid succession could finish in same millisecond
+ // (especially when using System.currentTimeMillis, which can return the same time for several millisconds).
+ Thread.sleep(10);
+ }
+
+ // Should initially have all tasks
+ Set<Task<?>> storedTasks = app.getManagementContext().getExecutionManager().getTasksWithAllTags(
+ ImmutableList.of(BrooklynTaskTags.tagForContextEntity(entity), ManagementContextInternal.EFFECTOR_TAG));
+ assertEquals(storedTasks, ImmutableSet.copyOf(tasks), "storedTasks="+storedTasks+"; expected="+tasks);
+
+ // Then oldest should be GC'ed to leave only maxNumTasks
+ final List<Task<?>> recentTasks = tasks.subList(tasks.size()-maxNumTasks, tasks.size());
+ Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new Runnable() {
+ @Override public void run() {
+ Set<Task<?>> storedTasks2 = app.getManagementContext().getExecutionManager().getTasksWithAllTags(
+ ImmutableList.of(BrooklynTaskTags.tagForContextEntity(entity), ManagementContextInternal.EFFECTOR_TAG));
+ List<String> storedTasks2Str = FluentIterable
+ .from(storedTasks2)
+ .transform(new Function<Task<?>, String>() {
+ @Override public String apply(Task<?> input) {
+ return taskToVerboseString(input);
+ }})
+ .toList();
+ assertEquals(storedTasks2, ImmutableSet.copyOf(recentTasks), "storedTasks="+storedTasks2Str+"; expected="+recentTasks);
+ }});
+ }
+
+ private String taskToVerboseString(Task t) {
+ return Objects.toStringHelper(t)
+ .add("id", t.getId())
+ .add("displayName", t.getDisplayName())
+ .add("submitTime", t.getSubmitTimeUtc())
+ .add("startTime", t.getStartTimeUtc())
+ .add("endTime", t.getEndTimeUtc())
+ .add("status", t.getStatusSummary())
+ .add("tags", t.getTags())
+ .toString();
+ }
+
+ @Test(groups="Integration")
+ public void testEffectorTasksGcedForAge() throws Exception {
+ Duration maxTaskAge = Duration.millis(100);
+ Duration maxOverhead = Duration.millis(250);
+ Duration earlyReturnGrace = Duration.millis(10);
+ BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
+ brooklynProperties.put(BrooklynGarbageCollector.GC_PERIOD, Duration.ONE_MILLISECOND);
+ brooklynProperties.put(BrooklynGarbageCollector.MAX_TASK_AGE, maxTaskAge);
+
+ app = ApplicationBuilder.newManagedApp(TestApplication.class, LocalManagementContextForTests.newInstance(brooklynProperties));
+ final TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ Stopwatch stopwatch = Stopwatch.createStarted();
+ Task<?> oldTask = entity.invoke(TestEntity.MY_EFFECTOR, ImmutableMap.<String,Object>of());
+ oldTask.get();
+
+ Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), new Runnable() {
+ @Override public void run() {
+ Set<Task<?>> storedTasks = app.getManagementContext().getExecutionManager().getTasksWithAllTags(ImmutableList.of(
+ BrooklynTaskTags.tagForTargetEntity(entity),
+ ManagementContextInternal.EFFECTOR_TAG));
+ assertEquals(storedTasks, ImmutableSet.of(), "storedTasks="+storedTasks);
+ }});
+
+ Duration timeToGc = Duration.of(stopwatch);
+ assertTrue(timeToGc.isLongerThan(maxTaskAge.subtract(earlyReturnGrace)), "timeToGc="+timeToGc+"; maxTaskAge="+maxTaskAge);
+ assertTrue(timeToGc.isShorterThan(maxTaskAge.add(maxOverhead)), "timeToGc="+timeToGc+"; maxTaskAge="+maxTaskAge);
+ }
+
+ private static class BigObject implements Serializable {
+ private static final long serialVersionUID = -4021304829674972215L;
+ private final int sizeBytes;
+ private final byte[] data;
+
+ BigObject(int sizeBytes) {
+ this.sizeBytes = sizeBytes;
+ this.data = new byte[sizeBytes];
+ }
+
+ @Override
+ public String toString() {
+ return "BigObject["+sizeBytes+"/"+data.length+"]";
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalManagementContextInstancesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalManagementContextInstancesTest.java b/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalManagementContextInstancesTest.java
new file mode 100644
index 0000000..973b795
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalManagementContextInstancesTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests the {@link LocalManagementContext#terminateAll()} and {@link LocalManagementContext#getInstances()} behaviour.
+ * Note this test must NEVER be run in parallel with other tests, as it will terminate the ManagementContext of those
+ * other tests.
+ *
+ * @author pveentjer
+ */
+public class LocalManagementContextInstancesTest {
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown(){
+ LocalManagementContext.terminateAll();
+ }
+
+ /** WIP group because other threads may be running in background,
+ * creating management contexts at the same time as us (slim chance, but observed once);
+ * they shouldn't be, but cleaning that up is another matter! */
+ @Test(groups="WIP")
+ public void testGetInstances(){
+ LocalManagementContext.terminateAll();
+ LocalManagementContext context1 = new LocalManagementContext();
+ LocalManagementContext context2 = new LocalManagementContext();
+ LocalManagementContext context3 = new LocalManagementContext();
+
+ assertEquals(LocalManagementContext.getInstances(), ImmutableSet.of(context1, context2, context3));
+ }
+
+ /** WIP group because other threads may be running in background;
+ * they shouldn't be, but cleaning that up is another matter! */
+ @Test
+ public void terminateAll(){
+ LocalManagementContext.terminateAll();
+
+ LocalManagementContext context1 = new LocalManagementContext();
+ LocalManagementContext context2 = new LocalManagementContext();
+
+ LocalManagementContext.terminateAll();
+
+ assertTrue(LocalManagementContext.getInstances().isEmpty());
+ assertFalse(context1.isRunning());
+ assertFalse(context2.isRunning());
+ }
+
+ @Test
+ public void terminateExplicitContext(){
+ LocalManagementContext context1 = new LocalManagementContext();
+ LocalManagementContext context2 = new LocalManagementContext();
+ LocalManagementContext context3 = new LocalManagementContext();
+
+ context2.terminate();
+
+ Assert.assertFalse(LocalManagementContext.getInstances().contains(context2));
+ Assert.assertTrue(LocalManagementContext.getInstances().contains(context1));
+ Assert.assertTrue(LocalManagementContext.getInstances().contains(context3));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalManagementContextTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalManagementContextTest.java b/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalManagementContextTest.java
new file mode 100644
index 0000000..d88765c
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalManagementContextTest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.ManagementContext.PropertiesReloadListener;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynProperties.Factory.Builder;
+import brooklyn.util.os.Os;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+
+public class LocalManagementContextTest {
+
+ private LocalManagementContext context;
+ private File globalPropertiesFile;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ context = null;
+ globalPropertiesFile = Os.newTempFile(getClass(), "global.properties");
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (context!=null) context.terminate();
+ if (globalPropertiesFile != null) globalPropertiesFile.delete();
+ }
+
+ @Test
+ public void testReloadPropertiesFromBuilder() throws IOException {
+ String globalPropertiesContents = "brooklyn.location.localhost.displayName=myname";
+ Files.write(globalPropertiesContents, globalPropertiesFile, Charsets.UTF_8);
+ Builder propsBuilder = new BrooklynProperties.Factory.Builder()
+ .globalPropertiesFile(globalPropertiesFile.getAbsolutePath());
+ // no builder support in LocalManagementContextForTests (we are testing that the builder's files are reloaded so we need it here)
+ context = new LocalManagementContext(propsBuilder);
+ Location location = context.getLocationRegistry().resolve("localhost");
+ assertEquals(location.getDisplayName(), "myname");
+ String newGlobalPropertiesContents = "brooklyn.location.localhost.displayName=myname2";
+ Files.write(newGlobalPropertiesContents, globalPropertiesFile, Charsets.UTF_8);
+ context.reloadBrooklynProperties();
+ Location location2 = context.getLocationRegistry().resolve("localhost");
+ assertEquals(location.getDisplayName(), "myname");
+ assertEquals(location2.getDisplayName(), "myname2");
+ }
+
+ @Test
+ public void testReloadPropertiesFromProperties() throws IOException {
+ String globalPropertiesContents = "brooklyn.location.localhost.displayName=myname";
+ Files.write(globalPropertiesContents, globalPropertiesFile, Charsets.UTF_8);
+ BrooklynProperties brooklynProperties = new BrooklynProperties.Factory.Builder()
+ .globalPropertiesFile(globalPropertiesFile.getAbsolutePath())
+ .build();
+ context = LocalManagementContextForTests.builder(true).useProperties(brooklynProperties).build();
+ Location location = context.getLocationRegistry().resolve("localhost");
+ assertEquals(location.getDisplayName(), "myname");
+ String newGlobalPropertiesContents = "brooklyn.location.localhost.displayName=myname2";
+ Files.write(newGlobalPropertiesContents, globalPropertiesFile, Charsets.UTF_8);
+ context.reloadBrooklynProperties();
+ Location location2 = context.getLocationRegistry().resolve("localhost");
+ assertEquals(location.getDisplayName(), "myname");
+ assertEquals(location2.getDisplayName(), "myname");
+ }
+
+ @Test
+ public void testPropertiesModified() throws IOException {
+ BrooklynProperties properties = BrooklynProperties.Factory.newEmpty();
+ properties.put("myname", "myval");
+ context = LocalManagementContextForTests.builder(true).useProperties(properties).build();
+ assertEquals(context.getBrooklynProperties().get("myname"), "myval");
+ properties.put("myname", "newval");
+ assertEquals(properties.get("myname"), "newval");
+ // TODO: Should changes in the 'properties' collection be reflected in context.getBrooklynProperties()?
+ assertNotEquals(context.getBrooklynProperties().get("myname"), "newval");
+ }
+
+ @Test
+ public void testAddAndRemoveReloadListener() {
+ final AtomicInteger reloadedCallbackCount = new AtomicInteger(0);
+ BrooklynProperties properties = BrooklynProperties.Factory.newEmpty();
+ properties.put("myname", "myval");
+ context = LocalManagementContextForTests.builder(true).useProperties(properties).build();
+ PropertiesReloadListener listener = new PropertiesReloadListener() {
+ public void reloaded() {
+ reloadedCallbackCount.incrementAndGet();
+ }
+ };
+ assertEquals(reloadedCallbackCount.get(), 0);
+ context.addPropertiesReloadListener(listener);
+ context.reloadBrooklynProperties();
+ assertEquals(reloadedCallbackCount.get(), 1);
+ context.removePropertiesReloadListener(listener);
+ context.reloadBrooklynProperties();
+ assertEquals(reloadedCallbackCount.get(), 1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManagerTest.java
new file mode 100644
index 0000000..635e562
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/internal/LocalSubscriptionManagerTest.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+import org.apache.brooklyn.api.management.SubscriptionManager;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.BrooklynAppUnitTestSupport;
+import brooklyn.entity.basic.BasicGroup;
+import brooklyn.entity.basic.Entities;
+
+/**
+ * testing the {@link SubscriptionManager} and associated classes.
+ */
+public class LocalSubscriptionManagerTest extends BrooklynAppUnitTestSupport {
+
+ private static final int TIMEOUT_MS = 5000;
+
+ private TestEntity entity;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ }
+
+ private void manage(Entity ...entities) {
+ for (Entity e: entities)
+ Entities.manage(e);
+ }
+
+ @Test
+ public void testSubscribeToEntityAttributeChange() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ app.subscribe(entity, TestEntity.SEQUENCE, new SensorEventListener<Object>() {
+ @Override public void onEvent(SensorEvent<Object> event) {
+ latch.countDown();
+ }});
+ entity.setSequenceValue(1234);
+ if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ fail("Timeout waiting for Event on TestEntity listener");
+ }
+ }
+
+ @Test
+ public void testSubscribeToEntityWithAttributeWildcard() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ app.subscribe(entity, null, new SensorEventListener<Object>() {
+ @Override public void onEvent(SensorEvent<Object> event) {
+ latch.countDown();
+ }});
+ entity.setSequenceValue(1234);
+ if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ fail("Timeout waiting for Event on TestEntity listener");
+ }
+ }
+
+ @Test
+ public void testSubscribeToAttributeChangeWithEntityWildcard() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ app.subscribe(null, TestEntity.SEQUENCE, new SensorEventListener<Object>() {
+ @Override public void onEvent(SensorEvent<Object> event) {
+ latch.countDown();
+ }});
+ entity.setSequenceValue(1234);
+ if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ fail("Timeout waiting for Event on TestEntity listener");
+ }
+ }
+
+ @Test
+ public void testSubscribeToChildAttributeChange() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ app.subscribeToChildren(app, TestEntity.SEQUENCE, new SensorEventListener<Object>() {
+ @Override public void onEvent(SensorEvent<Object> event) {
+ latch.countDown();
+ }});
+ entity.setSequenceValue(1234);
+ if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ fail("Timeout waiting for Event on child TestEntity listener");
+ }
+ }
+
+ @Test
+ public void testSubscribeToMemberAttributeChange() throws Exception {
+ BasicGroup group = app.createAndManageChild(EntitySpec.create(BasicGroup.class));
+ TestEntity member = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+ manage(group, member);
+
+ group.addMember(member);
+
+ final List<SensorEvent<Integer>> events = new CopyOnWriteArrayList<SensorEvent<Integer>>();
+ final CountDownLatch latch = new CountDownLatch(1);
+ app.subscribeToMembers(group, TestEntity.SEQUENCE, new SensorEventListener<Integer>() {
+ @Override public void onEvent(SensorEvent<Integer> event) {
+ events.add(event);
+ latch.countDown();
+ }});
+ member.setAttribute(TestEntity.SEQUENCE, 123);
+
+ if (!latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ fail("Timeout waiting for Event on parent TestEntity listener");
+ }
+ assertEquals(events.size(), 1);
+ assertEquals(events.get(0).getValue(), (Integer)123);
+ assertEquals(events.get(0).getSensor(), TestEntity.SEQUENCE);
+ assertEquals(events.get(0).getSource().getId(), member.getId());
+ }
+
+ // Regression test for ConcurrentModificationException in issue #327
+ @Test(groups="Integration")
+ public void testConcurrentSubscribingAndPublishing() throws Exception {
+ final AtomicReference<Exception> threadException = new AtomicReference<Exception>();
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class));
+
+ // Repeatedly subscribe and unsubscribe, so listener-set constantly changing while publishing to it.
+ // First create a stable listener so it is always the same listener-set object.
+ Thread thread = new Thread() {
+ public void run() {
+ try {
+ SensorEventListener<Object> noopListener = new SensorEventListener<Object>() {
+ @Override public void onEvent(SensorEvent<Object> event) {
+ }
+ };
+ app.subscribe(null, TestEntity.SEQUENCE, noopListener);
+ while (!Thread.currentThread().isInterrupted()) {
+ SubscriptionHandle handle = app.subscribe(null, TestEntity.SEQUENCE, noopListener);
+ app.unsubscribe(null, handle);
+ }
+ } catch (Exception e) {
+ threadException.set(e);
+ }
+ }
+ };
+
+ try {
+ thread.start();
+ for (int i = 0; i < 10000; i++) {
+ entity.setAttribute(TestEntity.SEQUENCE, i);
+ }
+ } finally {
+ thread.interrupt();
+ }
+
+ if (threadException.get() != null) throw threadException.get();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiPathTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiPathTest.java b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiPathTest.java
new file mode 100644
index 0000000..8dcbec2
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiPathTest.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.osgi;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.osgi.framework.BundleException;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.config.BrooklynServerPaths;
+import brooklyn.entity.basic.Entities;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Identifiers;
+
+
+/**
+ * Tests that OSGi entities load correctly and have the right catalog information set.
+ * Note further tests done elsewhere using CAMP YAML (referring to methods in this class).
+ */
+public class OsgiPathTest {
+
+ protected LocalManagementContext mgmt = null;
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws BundleException, IOException, InterruptedException {
+ if (mgmt!=null) Entities.destroyAll(mgmt);
+ }
+
+ @Test(groups="Integration") // integration only because OSGi takes ~200ms
+ public void testOsgiPathDefault() {
+ mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).build();
+ String path = BrooklynServerPaths.getOsgiCacheDir(mgmt).getAbsolutePath();
+ Assert.assertTrue(path.startsWith(BrooklynServerPaths.getMgmtBaseDir(mgmt)), path);
+ Assert.assertTrue(path.contains(mgmt.getManagementNodeId()), path);
+
+ assertExistsThenIsCleaned(path);
+ }
+
+ @Test(groups="Integration") // integration only because OSGi takes ~200ms
+ public void testOsgiPathCustom() {
+ BrooklynProperties bp = BrooklynProperties.Factory.newEmpty();
+ String randomSeg = "osgi-test-"+Identifiers.makeRandomId(4);
+ bp.put(BrooklynServerConfig.OSGI_CACHE_DIR, "${brooklyn.os.tmpdir}"+"/"+randomSeg+"/"+"${brooklyn.mgmt.node.id}");
+ mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).useProperties(bp).build();
+ String path = BrooklynServerPaths.getOsgiCacheDir(mgmt).getAbsolutePath();
+ Os.deleteOnExitRecursivelyAndEmptyParentsUpTo(new File(path), new File(Os.tmp()+"/"+randomSeg));
+
+ Assert.assertTrue(path.startsWith(Os.tmp()), path);
+ Assert.assertTrue(path.contains(mgmt.getManagementNodeId()), path);
+
+ assertExistsThenIsCleaned(path);
+ }
+
+ @Test(groups="Integration") // integration only because OSGi takes ~200ms
+ public void testOsgiPathCustomWithoutNodeIdNotCleaned() {
+ BrooklynProperties bp = BrooklynProperties.Factory.newEmpty();
+ String randomSeg = "osgi-test-"+Identifiers.makeRandomId(4);
+ bp.put(BrooklynServerConfig.OSGI_CACHE_DIR, "${brooklyn.os.tmpdir}"+"/"+randomSeg+"/"+"sample");
+ mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).useProperties(bp).build();
+ String path = BrooklynServerPaths.getOsgiCacheDir(mgmt).getAbsolutePath();
+ Os.deleteOnExitRecursivelyAndEmptyParentsUpTo(new File(path), new File(Os.tmp()+"/"+randomSeg));
+
+ Assert.assertTrue(path.startsWith(Os.tmp()), path);
+ Assert.assertFalse(path.contains(mgmt.getManagementNodeId()), path);
+
+ assertExistsThenCorrectCleanedBehaviour(path, false);
+ }
+
+ private void assertExistsThenIsCleaned(String path) {
+ assertExistsThenCorrectCleanedBehaviour(path, true);
+ }
+ private void assertExistsThenCorrectCleanedBehaviour(String path, boolean shouldBeCleanAfterwards) {
+ Assert.assertTrue(new File(path).exists(), "OSGi cache "+path+" should exist when in use");
+ Entities.destroyAll(mgmt);
+ mgmt = null;
+ if (shouldBeCleanAfterwards)
+ Assert.assertFalse(new File(path).exists(), "OSGi cache "+path+" should be cleaned after");
+ else
+ Assert.assertTrue(new File(path).exists(), "OSGi cache "+path+" should NOT be cleaned after");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java
new file mode 100644
index 0000000..7f1cc48
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiStandaloneTest.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.osgi;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarInputStream;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+
+import brooklyn.util.exceptions.Exceptions;
+
+import org.apache.commons.io.FileUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.launch.Framework;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.maven.MavenArtifact;
+import brooklyn.util.maven.MavenRetriever;
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+import brooklyn.util.osgi.Osgis;
+import brooklyn.util.osgi.Osgis.ManifestHelper;
+import brooklyn.util.stream.Streams;
+
+/**
+ * Tests some assumptions about OSGi behaviour, in standalone mode (not part of brooklyn).
+ * See {@link OsgiTestResources} for description of test resources.
+ */
+public class OsgiStandaloneTest {
+
+ private static final Logger log = LoggerFactory.getLogger(OsgiStandaloneTest.class);
+
+ public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = OsgiTestResources.BROOKLYN_OSGI_TEST_A_0_1_0_PATH;
+ public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:"+BROOKLYN_OSGI_TEST_A_0_1_0_PATH;
+
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_NAME = "org.apache.brooklyn.test.resources.osgi.brooklyn-test-osgi-entities";
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_VERSION = "0.1.0";
+
+ protected Framework framework = null;
+ private File storageTempDir;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ storageTempDir = Os.newTempDir("osgi-standalone");
+ framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws BundleException, IOException, InterruptedException {
+ tearDownOsgiFramework(framework, storageTempDir);
+ }
+
+ public static void tearDownOsgiFramework(Framework framework, File storageTempDir) throws BundleException, InterruptedException, IOException {
+ if (framework!=null) {
+ framework.stop();
+ Assert.assertEquals(framework.waitForStop(1000).getType(), FrameworkEvent.STOPPED);
+ framework = null;
+ }
+ if (storageTempDir!=null) {
+ FileUtils.deleteDirectory(storageTempDir);
+ storageTempDir = null;
+ }
+ }
+
+ protected Bundle install(String url) throws BundleException {
+ try {
+ return Osgis.install(framework, url);
+ } catch (Exception e) {
+ throw new IllegalStateException("test resources not available; may be an IDE issue, so try a mvn rebuild of this project", e);
+ }
+ }
+
+ protected Bundle installFromClasspath(String resourceName) throws BundleException {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), resourceName);
+ try {
+ return Osgis.install(framework, String.format("classpath:%s", resourceName));
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Test
+ public void testInstallBundle() throws Exception {
+ Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
+ checkMath(bundle, 3, 6);
+ }
+
+ @Test
+ public void testBootBundle() throws Exception {
+ Bundle bundle = installFromClasspath(BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+ Class<?> bundleCls = bundle.loadClass("brooklyn.osgi.tests.SimpleEntity");
+ Assert.assertEquals(Entity.class, bundle.loadClass(Entity.class.getName()));
+ Assert.assertEquals(Entity.class, bundleCls.getClassLoader().loadClass(Entity.class.getName()));
+ }
+
+ @Test
+ public void testDuplicateBundle() throws Exception {
+ MavenArtifact artifact = new MavenArtifact("org.apache.brooklyn", "brooklyn-api", "jar", "0.8.0-SNAPSHOT"); // BROOKLYN_VERSION
+ String localUrl = MavenRetriever.localUrl(artifact);
+ if ("file".equals(Urls.getProtocol(localUrl))) {
+ helperDuplicateBundle(localUrl);
+ } else {
+ log.warn("Skipping test OsgiStandaloneTest.testDuplicateBundle due to " + artifact + " not available in local repo.");
+ }
+ }
+
+ @Test(groups="Integration")
+ public void testRemoteDuplicateBundle() throws Exception {
+ helperDuplicateBundle(MavenRetriever.hostedUrl(new MavenArtifact("org.apache.brooklyn", "brooklyn-api", "jar", "0.8.0-SNAPSHOT"))); // BROOKLYN_VERSION
+ }
+
+ public void helperDuplicateBundle(String url) throws Exception {
+ //The bundle is already installed from the boot path.
+ //Make sure that we still get the initially loaded
+ //bundle after trying to install the same version.
+ Bundle bundle = install(url);
+ Assert.assertTrue(Osgis.isExtensionBundle(bundle));
+ }
+
+ @Test
+ public void testAMultiplier() throws Exception {
+ Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
+ checkMath(bundle, 3, 6);
+ setAMultiplier(bundle, 5);
+ checkMath(bundle, 3, 15);
+ }
+
+ /** run two multiplier tests to ensure that irrespective of order the tests run in,
+ * on a fresh install the multiplier is reset */
+ @Test
+ public void testANOtherMultiple() throws Exception {
+ Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
+ checkMath(bundle, 3, 6);
+ setAMultiplier(bundle, 14);
+ checkMath(bundle, 3, 42);
+ }
+
+ @Test
+ public void testGetBundle() throws Exception {
+ Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
+ setAMultiplier(bundle, 3);
+
+ // can look it up based on the same location string (no other "location identifier" reference string seems to work here, however)
+ Bundle bundle2 = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
+ checkMath(bundle2, 3, 9);
+ }
+
+ @Test
+ public void testUninstallAndReinstallBundle() throws Exception {
+ Bundle bundle = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
+ checkMath(bundle, 3, 6);
+ setAMultiplier(bundle, 3);
+ checkMath(bundle, 3, 9);
+ bundle.uninstall();
+
+ Bundle bundle2 = installFromClasspath(BROOKLYN_OSGI_TEST_A_0_1_0_PATH);
+ checkMath(bundle2, 3, 6);
+ }
+
+ protected void checkMath(Bundle bundle, int input, int output) throws Exception {
+ Assert.assertNotNull(bundle);
+ Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");
+ Object aInst = aClass.newInstance();
+ Object result = aClass.getMethod("times", int.class).invoke(aInst, input);
+ Assert.assertEquals(result, output);
+ }
+
+ protected void setAMultiplier(Bundle bundle, int newMultiplier) throws Exception {
+ Assert.assertNotNull(bundle);
+ Class<?> aClass = bundle.loadClass("brooklyn.test.osgi.TestA");
+ aClass.getField("multiplier").set(null, newMultiplier);
+ }
+
+ @Test
+ public void testReadAManifest() throws Exception {
+ Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
+ log.info("Bundles and exported packages:");
+ MutableSet<String> allPackages = MutableSet.of();
+ while (manifests.hasMoreElements()) {
+ ManifestHelper mf = Osgis.ManifestHelper.forManifestContents(Streams.readFullyString( manifests.nextElement().openStream() ));
+ List<String> mfPackages = mf.getExportedPackages();
+ log.info(" "+mf.getSymbolicNameVersion()+": "+mfPackages);
+ allPackages.addAll(mfPackages);
+ }
+ log.info("Total export package count: "+allPackages.size());
+ Assert.assertTrue(allPackages.size()>20, "did not find enough packages"); // probably much larger
+ Assert.assertTrue(allPackages.contains(Osgis.class.getPackage().getName()));
+ }
+
+ @Test
+ public void testReadKnownManifest() throws Exception {
+ TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+ InputStream in = this.getClass().getResourceAsStream(BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+ JarInputStream jarIn = new JarInputStream(in);
+ ManifestHelper helper = Osgis.ManifestHelper.forManifest(jarIn.getManifest());
+ jarIn.close();
+ Assert.assertEquals(helper.getVersion().toString(), "0.1.0");
+ Assert.assertTrue(helper.getExportedPackages().contains("brooklyn.osgi.tests"));
+ }
+
+ @Test
+ public void testLoadOsgiBundleDependencies() throws Exception {
+ Bundle bundle = installFromClasspath(BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+ Assert.assertNotNull(bundle);
+ Class<?> aClass = bundle.loadClass("brooklyn.osgi.tests.SimpleApplicationImpl");
+ Object aInst = aClass.newInstance();
+ Assert.assertNotNull(aInst);
+ }
+
+ @Test
+ public void testLoadAbsoluteWindowsResourceWithInstalledOSGi() {
+ //Felix installs an additional URL to the system classloader
+ //which throws an IllegalArgumentException when passed a
+ //windows path. See ExtensionManager.java static initializer.
+ String context = "mycontext";
+ String dummyPath = "C:\\dummypath";
+ ResourceUtils utils = ResourceUtils.create(this, context);
+ try {
+ utils.getResourceFromUrl(dummyPath);
+ Assert.fail("Non-reachable, should throw an exception for non-existing resource.");
+ } catch (RuntimeException e) {
+ Assert.assertTrue(e.getMessage().startsWith("Error getting resource '"+dummyPath+"' for "+context));
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiTestResources.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiTestResources.java b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiTestResources.java
new file mode 100644
index 0000000..b44da4d
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/osgi/OsgiTestResources.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.osgi;
+
+/**
+ * Many OSGi tests require OSGi bundles (of course). Test bundles have been collected here
+ * for convenience and clarity. Available bundles (on the classpath, with source code
+ * either embedded or in /src/dependencies) are described by the constants in this class.
+ * <p>
+ * Some of these bundles are also used in REST API tests, as that stretches catalog further
+ * (using CAMP) and that is one area where OSGi is heavily used.
+ */
+public class OsgiTestResources {
+
+
+ /**
+ * brooklyn-osgi-test-a_0.1.0 -
+ * defines TestA which has a "times" method and a static multiplier field;
+ * we set the multiplier to determine when we are sharing versions and when not
+ */
+ public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = "/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar";
+
+ /**
+ * brooklyn-test-osgi-entities (v 0.1.0) -
+ * defines an entity and an application, to confirm it can be read and used by brooklyn
+ */
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = "/brooklyn/osgi/brooklyn-test-osgi-entities.jar";
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_APPLICATION = "brooklyn.osgi.tests.SimpleApplication";
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY = "brooklyn.osgi.tests.SimpleEntity";
+ public static final String BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY = "brooklyn.osgi.tests.SimplePolicy";
+
+ /**
+ * brooklyn-test-osgi-more-entities_0.1.0 -
+ * another bundle with a minimal sayHi effector, used to test versioning and dependencies
+ * (this one has no dependencies, but see also {@value #BROOKLYN_TEST_MORE_ENTITIES_V2_PATH})
+ */
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART = "brooklyn-test-osgi-more-entities";
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL =
+ "org.apache.brooklyn.test.resources.osgi."+BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART;
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_PATH = "/brooklyn/osgi/" + BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART + "_0.1.0.jar";
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY = "brooklyn.osgi.tests.more.MoreEntity";
+
+ /**
+ * brooklyn-test-osgi-more-entities_0.2.0 -
+ * similar to {@link #BROOKLYN_TEST_MORE_ENTITIES_V1_PATH} but saying "HI NAME" rather than "Hi NAME",
+ * and declaring an explicit dependency on SimplePolicy from {@link #BROOKLYN_TEST_OSGI_ENTITIES_PATH}
+ */
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_PATH = "/brooklyn/osgi/" + BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART + "_0.2.0.jar";
+
+ /**
+ * bundle with identical metadata (same symbolic name and version -- hence being an evil twin)
+ * as {@link #BROOKLYN_TEST_MORE_ENTITIES_V2_PATH},
+ * but slightly different behaviour -- saying "HO NAME" -- in order to make sure we can differentiate two two
+ * at runtime.
+ */
+ public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH = "/brooklyn/osgi/" + BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FINAL_PART + "_evil-twin_0.2.0.jar";
+
+}
[02/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java
----------------------------------------------------------------------
diff --git a/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java b/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java
index c089531..29eb71d 100644
--- a/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java
+++ b/software/base/src/test/java/org/apache/brooklyn/location/basic/WinRmMachineLocationLiveTest.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.location.basic;
import static org.testng.Assert.assertEquals;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.location.jclouds.JcloudsLocation;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
@@ -35,8 +36,8 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.BrooklynAppLiveTestSupport;
import brooklyn.entity.basic.Entities;
+
import org.apache.brooklyn.location.jclouds.JcloudsWinRmMachineLocation;
-import brooklyn.management.internal.ManagementContextInternal;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.java b/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.java
index 67c8a51..1dc25df 100644
--- a/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.java
+++ b/software/database/src/test/java/brooklyn/entity/database/mariadb/MariaDbIntegrationTest.java
@@ -23,6 +23,7 @@ import java.net.InetAddress;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,8 +37,9 @@ import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.database.DatastoreMixins.DatastoreCommon;
import brooklyn.entity.database.VogellaExampleAccess;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
+
import brooklyn.util.collections.MutableMap;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlIntegrationTest.java b/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlIntegrationTest.java
index 3d6ed4c..7cb5863 100644
--- a/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlIntegrationTest.java
+++ b/software/database/src/test/java/brooklyn/entity/database/postgresql/PostgreSqlIntegrationTest.java
@@ -20,6 +20,7 @@ package brooklyn.entity.database.postgresql;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,8 +33,8 @@ import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.database.DatastoreMixins.DatastoreCommon;
import brooklyn.entity.database.VogellaExampleAccess;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/database/src/test/java/brooklyn/entity/database/rubyrep/RubyRepIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/database/src/test/java/brooklyn/entity/database/rubyrep/RubyRepIntegrationTest.java b/software/database/src/test/java/brooklyn/entity/database/rubyrep/RubyRepIntegrationTest.java
index e56b990..7028d1b 100644
--- a/software/database/src/test/java/brooklyn/entity/database/rubyrep/RubyRepIntegrationTest.java
+++ b/software/database/src/test/java/brooklyn/entity/database/rubyrep/RubyRepIntegrationTest.java
@@ -26,6 +26,7 @@ import java.util.List;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,8 +47,6 @@ import brooklyn.entity.database.postgresql.PostgreSqlNode;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.management.internal.LocalManagementContext;
-
public class RubyRepIntegrationTest {
public static final Logger log = LoggerFactory.getLogger(RubyRepIntegrationTest.class);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java
----------------------------------------------------------------------
diff --git a/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java b/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java
index a2317ec..758ace7 100644
--- a/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java
+++ b/software/messaging/src/test/java/brooklyn/entity/messaging/storm/StormAbstractCloudLiveTest.java
@@ -30,6 +30,7 @@ import java.util.Map;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.EntityTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,7 +52,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.messaging.storm.topologies.ExclamationBolt;
import brooklyn.entity.trait.Startable;
import brooklyn.entity.zookeeper.ZooKeeperEnsemble;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.file.ArchiveBuilder;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseOfflineTest.java
----------------------------------------------------------------------
diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseOfflineTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseOfflineTest.java
index e0053b6..8535876 100644
--- a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseOfflineTest.java
+++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/couchbase/CouchbaseOfflineTest.java
@@ -25,9 +25,10 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
+
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.basic.BasicOsDetails;
import org.apache.brooklyn.location.basic.BasicOsDetails.OsArchs;
-import brooklyn.management.internal.LocalManagementContext;
public class CouchbaseOfflineTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceTest.java
index 01ad82f..be7ef17 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/dns/AbstractGeoDnsServiceTest.java
@@ -32,6 +32,7 @@ import org.apache.brooklyn.api.location.LocationRegistry;
import org.apache.brooklyn.api.location.LocationResolver;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.entity.dns.AbstractGeoDnsService;
import org.apache.brooklyn.entity.dns.AbstractGeoDnsServiceImpl;
import org.apache.brooklyn.entity.dns.AbstractGeoDnsServiceTest;
@@ -63,7 +64,6 @@ import org.apache.brooklyn.location.basic.SimulatedLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
import org.apache.brooklyn.location.geo.HostGeoInfo;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.CollectionFunctionals;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java
index cfe99c3..2e894ea 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/UrlMappingTest.java
@@ -28,6 +28,7 @@ import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.entity.proxy.nginx.UrlMapping;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
@@ -48,7 +49,6 @@ import brooklyn.entity.rebind.RebindTestUtils;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
index a96a268..f18b414 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.entity.proxy.nginx.NginxController;
import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
import org.apache.brooklyn.test.EntityTestUtils;
@@ -55,7 +56,6 @@ import brooklyn.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocationReuseIntegrationTest.RecordingSshjTool;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.internal.ssh.SshTool;
import brooklyn.util.net.Networking;
import brooklyn.util.repeat.Repeater;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java
index fc3b0b4..588a890 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/ControlledDynamicWebAppClusterRebindIntegrationTest.java
@@ -31,6 +31,7 @@ import java.util.concurrent.Executors;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.entity.proxy.nginx.NginxController;
import org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
import org.apache.brooklyn.test.TestResourceUnavailableException;
@@ -46,8 +47,9 @@ import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.rebind.RebindTestUtils;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
+
import brooklyn.util.internal.TimeExtras;
import com.google.common.base.Predicates;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java
index 8a3ab2e3..aabac25 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/webapp/jboss/DynamicWebAppClusterRebindIntegrationTest.java
@@ -31,6 +31,7 @@ import java.util.concurrent.Executors;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.entity.webapp.DynamicWebAppCluster;
import org.apache.brooklyn.test.TestResourceUnavailableException;
import org.apache.brooklyn.test.WebAppMonitor;
@@ -44,8 +45,8 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.rebind.RebindTestUtils;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java
----------------------------------------------------------------------
diff --git a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java b/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java
index 05d26c0..0b4dfd8 100644
--- a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java
+++ b/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGrid.java
@@ -24,9 +24,9 @@ import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.internal.storage.DataGrid;
-import brooklyn.management.internal.ManagementContextInternal;
import com.google.common.collect.ImmutableMap;
import com.hazelcast.config.Config;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java
----------------------------------------------------------------------
diff --git a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java b/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java
index 004bd16..c723f67 100644
--- a/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java
+++ b/storage/hazelcast/src/main/java/org/apache/brooklyn/internal/storage/impl/hazelcast/HazelcastDataGridFactory.java
@@ -18,9 +18,10 @@
*/
package org.apache.brooklyn.internal.storage.impl.hazelcast;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+
import brooklyn.internal.storage.DataGrid;
import brooklyn.internal.storage.DataGridFactory;
-import brooklyn.management.internal.ManagementContextInternal;
import com.hazelcast.core.HazelcastInstance;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java
----------------------------------------------------------------------
diff --git a/storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java b/storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java
index 426abd5..464117e 100644
--- a/storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java
+++ b/storage/hazelcast/src/test/java/org/apache/brooklyn/storage/impl/hazelcast/HazelcastStorageTest.java
@@ -33,9 +33,11 @@ import brooklyn.internal.storage.BrooklynStorage;
import brooklyn.internal.storage.DataGridFactory;
import brooklyn.internal.storage.Reference;
import brooklyn.internal.storage.impl.BrooklynStorageImpl;
+
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.internal.storage.impl.hazelcast.HazelcastDataGrid;
import org.apache.brooklyn.internal.storage.impl.hazelcast.HazelcastDataGridFactory;
-import brooklyn.management.internal.LocalManagementContext;
+
import brooklyn.util.collections.MutableList;
import com.hazelcast.core.Hazelcast;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java b/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java
index d70392d..471d5e3 100644
--- a/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java
+++ b/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleLocalhostIntegrationTest.java
@@ -16,7 +16,7 @@ import brooklyn.entity.basic.StartableApplication;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.entity.webapp.JavaWebAppService;
import org.apache.brooklyn.api.management.ManagementContext;
-import brooklyn.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import brooklyn.util.ResourceUtils;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleUnitTest.java
----------------------------------------------------------------------
diff --git a/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleUnitTest.java b/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleUnitTest.java
index 9cc42ae..df15e0a 100644
--- a/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleUnitTest.java
+++ b/usage/archetypes/quickstart/src/brooklyn-sample/src/test/java/com/acme/sample/brooklyn/sample/app/SampleUnitTest.java
@@ -16,7 +16,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.entity.webapp.JavaWebAppService;
import org.apache.brooklyn.entity.webapp.WebAppService;
import org.apache.brooklyn.api.management.ManagementContext;
-import brooklyn.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampPlatformLauncherAbstract.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampPlatformLauncherAbstract.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampPlatformLauncherAbstract.java
index 5167481..7adf958 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampPlatformLauncherAbstract.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampPlatformLauncherAbstract.java
@@ -19,9 +19,9 @@
package org.apache.brooklyn.camp.brooklyn;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import io.brooklyn.camp.spi.PlatformRootSummary;
-import brooklyn.management.internal.LocalManagementContext;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index fe22e89..7def6cf 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -47,13 +47,13 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.entity.basic.BasicApplicationImpl;
-import brooklyn.management.internal.EntityManagementUtils;
-import brooklyn.management.internal.EntityManagementUtils.CreationResult;
import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.flags.TypeCoercions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index d17740d..57d53da 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -46,6 +46,9 @@ import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
import org.apache.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver;
import org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.config.ConfigKey;
@@ -54,9 +57,6 @@ import brooklyn.entity.basic.BrooklynTags;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.management.ManagementContextInjectable;
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
index 94dd3d0..be18cc2 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
@@ -31,11 +31,11 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Urls;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
index 086ddaf..601a46a 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
+import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.ConfigKeys;
@@ -36,7 +37,6 @@ import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.EntityPredicates;
import brooklyn.event.basic.DependentConfiguration;
import brooklyn.event.basic.Sensors;
-import brooklyn.management.internal.EntityManagerInternal;
import brooklyn.util.guava.Maybe;
import brooklyn.util.task.TaskBuilder;
import brooklyn.util.task.Tasks;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ApplicationsYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ApplicationsYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ApplicationsYamlTest.java
index 9d9e340..ddd54bf 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ApplicationsYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ApplicationsYamlTest.java
@@ -24,13 +24,13 @@ import static org.testng.Assert.assertTrue;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
import brooklyn.entity.basic.BasicApplication;
import brooklyn.entity.basic.BasicEntity;
-import brooklyn.management.internal.EntityManagementUtils;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
index 36ce910..d2ada07 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
@@ -41,7 +42,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.StartableApplication;
import brooklyn.entity.rebind.RebindOptions;
import brooklyn.entity.rebind.RebindTestFixture;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.ResourceUtils;
import brooklyn.util.config.ConfigBag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
index a11bff6..df4b41b 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,7 +40,6 @@ import org.testng.annotations.BeforeMethod;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.ResourceUtils;
import brooklyn.util.config.ConfigBag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
index d984db2..107b0b9 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
@@ -23,10 +23,10 @@ import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.Factory;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.InstantiatorFromKey;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.testng.Assert;
import org.testng.annotations.Test;
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
import brooklyn.policy.ha.ServiceRestarter;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.javalang.JavaClassNames;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
index 5e51b0e..87d014b 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,7 +41,6 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.RebindTestUtils;
import brooklyn.event.basic.Sensors;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.task.Tasks;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
index 6c803e1..06f596a 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/EntitiesYamlTest.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
+import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
import org.slf4j.Logger;
@@ -60,7 +61,6 @@ import brooklyn.entity.basic.SameServerEntity;
import brooklyn.entity.effector.Effectors;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.event.basic.Sensors;
-import brooklyn.management.internal.EntityManagerInternal;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Functionals;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
index 343dd8f..e558288 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/JavaWebAppWithDslYamlRebindIntegrationTest.java
@@ -28,6 +28,7 @@ import java.util.Set;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
@@ -37,7 +38,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.stream.Streams;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
index a1b2ae0..ba29051 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
@@ -25,6 +25,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.trait.Configurable;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
import org.apache.brooklyn.entity.proxy.ProxySslConfig;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -36,7 +37,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.ManagementContextInjectable;
import brooklyn.util.config.ConfigBag;
import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.flags.TypeCoercions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java
index 1c91cf1..535ac24 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ReferencedYamlTest.java
@@ -21,13 +21,13 @@ package org.apache.brooklyn.camp.brooklyn;
import java.util.Collection;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
import org.apache.brooklyn.test.TestResourceUnavailableException;
import org.testng.Assert;
import org.testng.annotations.Test;
import brooklyn.entity.basic.BasicApplication;
import brooklyn.entity.basic.BasicEntity;
-import brooklyn.management.osgi.OsgiStandaloneTest;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java
index 7332af7..65bb7e0 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/AbstractCatalogXmlTest.java
@@ -20,6 +20,8 @@ package org.apache.brooklyn.camp.brooklyn.catalog;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
import org.apache.brooklyn.test.TestResourceUnavailableException;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
@@ -31,8 +33,6 @@ import java.io.StringReader;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.osgi.OsgiTestResources;
import brooklyn.util.ResourceUtils;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index 0f326ad..1bf481d 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -37,9 +37,9 @@ import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
+import org.apache.brooklyn.core.management.osgi.OsgiVersionMoreEntityTest;
import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
import org.apache.brooklyn.test.TestResourceUnavailableException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
index 111b180..c4579ff 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
@@ -32,11 +32,11 @@ import org.apache.brooklyn.api.catalog.BrooklynCatalog;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
+import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.BasicEntity;
-import brooklyn.management.osgi.OsgiStandaloneTest;
-import brooklyn.management.osgi.OsgiTestResources;
import org.apache.brooklyn.test.TestResourceUnavailableException;
import org.apache.brooklyn.test.entity.TestEntity;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
index 7160657..70076f9 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java
@@ -33,14 +33,12 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
import brooklyn.catalog.CatalogPredicates;
import brooklyn.event.basic.BasicConfigKey;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-
-import brooklyn.management.osgi.OsgiStandaloneTest;
-
import org.apache.brooklyn.test.TestResourceUnavailableException;
import brooklyn.util.text.StringFunctions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
index 10c60fb..6a44df3 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
@@ -25,10 +25,10 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
import brooklyn.catalog.CatalogPredicates;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.management.osgi.OsgiStandaloneTest;
import org.apache.brooklyn.test.TestResourceUnavailableException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java
index 2de6366..3a21fac 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java
@@ -27,10 +27,8 @@ import org.testng.annotations.Test;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
-
-import brooklyn.management.osgi.OsgiStandaloneTest;
-import brooklyn.management.osgi.OsgiTestResources;
-
+import org.apache.brooklyn.core.management.osgi.OsgiStandaloneTest;
+import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
import org.apache.brooklyn.test.TestResourceUnavailableException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/cli/src/main/java/org/apache/brooklyn/cli/CloudExplorer.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/CloudExplorer.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/CloudExplorer.java
index 32d2cec..32111e9 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/CloudExplorer.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/CloudExplorer.java
@@ -40,12 +40,12 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationDefinition;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.location.basic.LocationConfigKeys;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
import org.apache.brooklyn.location.jclouds.JcloudsLocation;
import org.apache.brooklyn.location.jclouds.JcloudsUtil;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
import brooklyn.util.stream.Streams;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
index 6162ad1..09cba24 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
@@ -79,6 +79,7 @@ import org.apache.brooklyn.cli.CloudExplorer.ComputeListImagesCommand;
import org.apache.brooklyn.cli.CloudExplorer.ComputeListInstancesCommand;
import org.apache.brooklyn.cli.CloudExplorer.ComputeTerminateInstancesCommand;
import org.apache.brooklyn.cli.ItemLister.ListAllCommand;
+import org.apache.brooklyn.core.management.ha.OsgiManager;
import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.AbstractEntity;
@@ -93,9 +94,6 @@ import brooklyn.entity.trait.Startable;
import org.apache.brooklyn.launcher.BrooklynLauncher;
import org.apache.brooklyn.launcher.BrooklynServerDetails;
import org.apache.brooklyn.launcher.config.StopWhichAppsOnShutdown;
-
-import brooklyn.management.ha.OsgiManager;
-
import org.apache.brooklyn.rest.security.PasswordHasher;
import org.apache.brooklyn.rest.util.ShutdownHandler;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
index b1efe6f..8267ca3 100644
--- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
@@ -49,6 +49,10 @@ import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynAssemblyTemplateInstantiator;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -85,12 +89,6 @@ import brooklyn.entity.trait.Startable;
import org.apache.brooklyn.launcher.config.StopWhichAppsOnShutdown;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation.LocalhostMachine;
import org.apache.brooklyn.location.basic.PortRanges;
-
-import brooklyn.management.ha.HighAvailabilityManagerImpl;
-import brooklyn.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-
import org.apache.brooklyn.rest.BrooklynWebConfig;
import org.apache.brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
import org.apache.brooklyn.rest.security.provider.BrooklynUserWithRandomPasswordSecurityProvider;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
index 2b6c831..c9bf366 100644
--- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
@@ -67,12 +67,10 @@ import brooklyn.internal.BrooklynInitialization;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.launcher.config.CustomResourceLocator;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.PortRanges;
-
-import brooklyn.management.internal.ManagementContextInternal;
-
import org.apache.brooklyn.rest.BrooklynRestApi;
import org.apache.brooklyn.rest.BrooklynWebConfig;
import org.apache.brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
index fa9e722..461065e 100644
--- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
@@ -23,12 +23,10 @@ import io.brooklyn.camp.spi.PlatformRootSummary;
import brooklyn.entity.basic.BrooklynShutdownHooks;
import org.apache.brooklyn.launcher.BrooklynLauncher;
-
-import brooklyn.management.internal.LocalManagementContext;
-
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import com.google.common.annotations.Beta;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java
index 55ed04a..b65e3dd 100644
--- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java
@@ -21,9 +21,11 @@ package org.apache.brooklyn.launcher.config;
import brooklyn.config.BrooklynServiceAttributes;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynConfigKeys;
+
+import org.apache.brooklyn.core.management.internal.BrooklynGarbageCollector;
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.management.internal.BrooklynGarbageCollector;
import org.apache.brooklyn.rest.BrooklynWebConfig;
+
import brooklyn.util.internal.BrooklynSystemProperties;
import brooklyn.util.internal.StringSystemProperty;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
index e562399..1806aa9 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
@@ -23,6 +23,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.launcher.BrooklynLauncher;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
@@ -43,7 +44,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.rebind.RebindTestUtils;
import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.test.Asserts;
import brooklyn.util.os.Os;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
index 9f11563..b0796db 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
@@ -22,6 +22,8 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.launcher.BrooklynLauncher;
import static org.testng.Assert.assertEquals;
@@ -55,8 +57,6 @@ import brooklyn.entity.rebind.RebindTestUtils;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.exceptions.FatalRuntimeException;
import brooklyn.util.io.FileUtil;
import brooklyn.util.net.Urls;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
index db4f5ff..8ee48f4 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
@@ -18,7 +18,9 @@
*/
package org.apache.brooklyn.launcher;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.launcher.BrooklynWebServer;
+
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@@ -47,7 +49,7 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
+
import org.apache.brooklyn.rest.BrooklynWebConfig;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
index 2c50716..d145906 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
@@ -18,9 +18,12 @@
*/
package org.apache.brooklyn.launcher;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.launcher.BrooklynWebServer;
import org.apache.brooklyn.launcher.BrooklynLauncher;
import org.apache.brooklyn.launcher.BrooklynServerDetails;
+
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;
@@ -36,8 +39,6 @@ import org.testng.annotations.Test;
import brooklyn.config.BrooklynProperties;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Networking;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
index f8ea8fb..4fcc63d 100644
--- a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.EntityTestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,7 +48,6 @@ import org.apache.brooklyn.launcher.BrooklynLauncher;
import org.apache.brooklyn.launcher.SimpleYamlLauncherForTests;
import org.apache.brooklyn.launcher.camp.BrooklynCampPlatformLauncher;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.test.Asserts;
import brooklyn.util.ResourceUtils;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java b/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
index d692790..4b5b1b1 100644
--- a/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
+++ b/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
@@ -45,9 +45,9 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.launcher.BrooklynLauncher;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.os.Os;
import brooklyn.util.time.Duration;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
index be3a690..11847dd 100644
--- a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
+++ b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/ApplicationResourceIntegrationTest.java
@@ -36,11 +36,11 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.StartableApplication;
-import org.apache.brooklyn.location.basic.BasicLocationRegistry;
-import brooklyn.management.internal.LocalManagementContext;
+import org.apache.brooklyn.location.basic.BasicLocationRegistry;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.rest.BrooklynRestApiLauncher;
import org.apache.brooklyn.rest.BrooklynRestApiLauncherTest;
import org.apache.brooklyn.rest.domain.ApplicationSpec;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
----------------------------------------------------------------------
diff --git a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
index 9c5c20e..03bb6ea 100644
--- a/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
+++ b/usage/rest-client/src/test/java/org/apache/brooklyn/rest/client/BrooklynApiRestClientTest.java
@@ -35,11 +35,11 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.StartableApplication;
-import org.apache.brooklyn.location.basic.BasicLocationRegistry;
-import brooklyn.management.internal.LocalManagementContext;
+import org.apache.brooklyn.location.basic.BasicLocationRegistry;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.rest.BrooklynRestApiLauncher;
import org.apache.brooklyn.rest.BrooklynRestApiLauncherTest;
import org.apache.brooklyn.rest.domain.ApplicationSummary;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/filter/BrooklynPropertiesSecurityFilter.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/filter/BrooklynPropertiesSecurityFilter.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/filter/BrooklynPropertiesSecurityFilter.java
index 0094562..5f47438 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/filter/BrooklynPropertiesSecurityFilter.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/filter/BrooklynPropertiesSecurityFilter.java
@@ -35,10 +35,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.BrooklynServiceAttributes;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.entitlement.WebEntitlementContext;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.WebEntitlementContext;
import org.apache.brooklyn.rest.security.provider.DelegatingSecurityProvider;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java
index 4cecb94..9313987 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java
@@ -29,11 +29,11 @@ import org.codehaus.jackson.map.ObjectMapper;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.config.BrooklynServiceAttributes;
import brooklyn.config.render.RendererHints;
-import brooklyn.management.ManagementContextInjectable;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.ManagementContextInjectable;
import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils;
import org.apache.brooklyn.rest.util.WebResourceUtils;
import org.apache.brooklyn.rest.util.json.BrooklynJacksonJsonProvider;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AccessResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AccessResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AccessResource.java
index 73a3d14..22f2765 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AccessResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AccessResource.java
@@ -20,8 +20,8 @@ package org.apache.brooklyn.rest.resources;
import javax.ws.rs.core.Response;
-import brooklyn.management.internal.AccessManager;
-import brooklyn.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.internal.AccessManager;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.rest.api.AccessApi;
import org.apache.brooklyn.rest.domain.AccessSummary;
import org.apache.brooklyn.rest.transform.AccessTransformer;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
index 9849ed2..8a54607 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java
@@ -52,12 +52,6 @@ import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.trait.Startable;
import brooklyn.event.basic.Sensors;
-import brooklyn.management.entitlement.EntitlementPredicates;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.entitlement.Entitlements.EntityAndItem;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
-import brooklyn.management.internal.EntityManagementUtils;
-import brooklyn.management.internal.EntityManagementUtils.CreationResult;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
@@ -66,6 +60,12 @@ import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.entitlement.EntitlementPredicates;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
import org.apache.brooklyn.rest.api.ApplicationApi;
import org.apache.brooklyn.rest.domain.ApplicationSpec;
import org.apache.brooklyn.rest.domain.ApplicationSummary;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 218d729..e841b27 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -44,14 +44,14 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
import brooklyn.catalog.CatalogPredicates;
import brooklyn.catalog.internal.BasicBrooklynCatalog;
import brooklyn.catalog.internal.CatalogDto;
import brooklyn.catalog.internal.CatalogItemComparator;
import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
import org.apache.brooklyn.rest.api.CatalogApi;
import org.apache.brooklyn.rest.domain.ApiError;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
index ebc1276..1d6e961 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EffectorResource.java
@@ -33,13 +33,12 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
-import brooklyn.management.internal.EffectorUtils;
-
import org.apache.brooklyn.api.entity.Effector;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.apache.brooklyn.rest.api.EffectorApi;
import org.apache.brooklyn.rest.domain.EffectorSummary;
import org.apache.brooklyn.rest.domain.SummaryComparators;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
index 98917cd..5353f50 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java
@@ -30,10 +30,10 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.management.entitlement.Entitlements;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.rest.api.EntityConfigApi;
import org.apache.brooklyn.rest.domain.EntityConfigSummary;
import org.apache.brooklyn.rest.filter.HaHotStateRequired;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
index ec730a9..a50a86e 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/EntityResource.java
@@ -41,15 +41,15 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.BrooklynTags;
import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.management.entitlement.EntitlementPredicates;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.internal.EntityManagementUtils;
-import brooklyn.management.internal.EntityManagementUtils.CreationResult;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.entitlement.EntitlementPredicates;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils;
+import org.apache.brooklyn.core.management.internal.EntityManagementUtils.CreationResult;
import org.apache.brooklyn.rest.api.EntityApi;
import org.apache.brooklyn.rest.domain.EntitySummary;
import org.apache.brooklyn.rest.domain.LocationSummary;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
index b4aa5ce..655c20c 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/PolicyConfigResource.java
@@ -25,11 +25,11 @@ import javax.ws.rs.core.Response;
import brooklyn.basic.BrooklynObjectInternal;
import brooklyn.config.ConfigKey;
-import brooklyn.management.entitlement.Entitlements;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.rest.api.PolicyConfigApi;
import org.apache.brooklyn.rest.domain.PolicyConfigSummary;
import org.apache.brooklyn.rest.filter.HaHotStateRequired;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
index e6c73db..e8b85ef 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
@@ -29,11 +29,11 @@ import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.event.basic.BasicAttributeSensor;
-import brooklyn.management.entitlement.Entitlements;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.rest.api.SensorApi;
import org.apache.brooklyn.rest.domain.SensorSummary;
import org.apache.brooklyn.rest.filter.HaHotStateRequired;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
index 8edc1d5..9c48ddf 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ServerResource.java
@@ -50,8 +50,6 @@ import brooklyn.entity.basic.StartableApplication;
import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
import brooklyn.entity.rebind.persister.FileBasedObjectStore;
import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.internal.ManagementContextInternal;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
@@ -63,6 +61,8 @@ import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
import org.apache.brooklyn.api.management.ha.MementoCopyMode;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.rest.api.ServerApi;
import org.apache.brooklyn.rest.domain.BrooklynFeatureSummary;
import org.apache.brooklyn.rest.domain.HighAvailabilitySummary;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/UsageResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/UsageResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/UsageResource.java
index 936de70..bf83a74 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/UsageResource.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/UsageResource.java
@@ -31,14 +31,16 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.entity.basic.Lifecycle;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.usage.ApplicationUsage;
-import brooklyn.management.usage.ApplicationUsage.ApplicationEvent;
-import brooklyn.management.usage.LocationUsage;
+
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage;
+import org.apache.brooklyn.core.management.usage.LocationUsage;
+import org.apache.brooklyn.core.management.usage.ApplicationUsage.ApplicationEvent;
import org.apache.brooklyn.rest.api.UsageApi;
import org.apache.brooklyn.rest.domain.UsageStatistic;
import org.apache.brooklyn.rest.domain.UsageStatistics;
import org.apache.brooklyn.rest.transform.ApplicationTransformer;
+
import brooklyn.util.exceptions.UserFacingException;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Time;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/AccessTransformer.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/AccessTransformer.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/AccessTransformer.java
index 4a0807f..31b0389 100644
--- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/AccessTransformer.java
+++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/transform/AccessTransformer.java
@@ -20,7 +20,7 @@ package org.apache.brooklyn.rest.transform;
import java.net.URI;
-import brooklyn.management.internal.AccessManager;
+import org.apache.brooklyn.core.management.internal.AccessManager;
import org.apache.brooklyn.rest.domain.AccessSummary;
import com.google.common.collect.ImmutableMap;
[09/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromPropertiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromPropertiesTest.java b/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromPropertiesTest.java
index a8d6e31..8fa0f53 100644
--- a/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromPropertiesTest.java
+++ b/core/src/test/java/brooklyn/entity/drivers/downloads/DownloadProducerFromPropertiesTest.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager.
import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager.DownloadTargets;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.annotations.AfterMethod;
@@ -39,8 +40,6 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.management.internal.LocalManagementContext;
-
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java b/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java
index ce3dffc..fa963c3 100644
--- a/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java
+++ b/core/src/test/java/brooklyn/entity/effector/EffectorBasicTest.java
@@ -25,6 +25,7 @@ import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.TestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.slf4j.Logger;
@@ -37,8 +38,9 @@ import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.trait.FailingEntity;
import brooklyn.entity.trait.Startable;
+
import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.management.internal.ManagementContextInternal;
+
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.task.Tasks;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/proxying/ApplicationBuilderOverridingTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/proxying/ApplicationBuilderOverridingTest.java b/core/src/test/java/brooklyn/entity/proxying/ApplicationBuilderOverridingTest.java
index 3d3573e..f8f6302 100644
--- a/core/src/test/java/brooklyn/entity/proxying/ApplicationBuilderOverridingTest.java
+++ b/core/src/test/java/brooklyn/entity/proxying/ApplicationBuilderOverridingTest.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -48,7 +49,6 @@ import brooklyn.entity.basic.BasicApplication;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.StartableApplication;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.exceptions.Exceptions;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/proxying/EntityProxyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/proxying/EntityProxyTest.java b/core/src/test/java/brooklyn/entity/proxying/EntityProxyTest.java
index fea7058..3ee866c 100644
--- a/core/src/test/java/brooklyn/entity/proxying/EntityProxyTest.java
+++ b/core/src/test/java/brooklyn/entity/proxying/EntityProxyTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.EntityManager;
import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@@ -40,7 +41,6 @@ import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.StartableApplication;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.collections.MutableMap;
import com.google.common.collect.ImmutableList;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/proxying/InternalEntityFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/proxying/InternalEntityFactoryTest.java b/core/src/test/java/brooklyn/entity/proxying/InternalEntityFactoryTest.java
index 004d02d..8f0d3ec 100644
--- a/core/src/test/java/brooklyn/entity/proxying/InternalEntityFactoryTest.java
+++ b/core/src/test/java/brooklyn/entity/proxying/InternalEntityFactoryTest.java
@@ -26,6 +26,7 @@ import static org.testng.Assert.assertTrue;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestApplicationImpl;
@@ -37,7 +38,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.AbstractApplication;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.ManagementContextInternal;
public class InternalEntityFactoryTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
index 45a39cc..41917d4 100644
--- a/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/ActivePartialRebindVersionTest.java
@@ -25,12 +25,12 @@ import org.testng.annotations.Test;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.osgi.OsgiVersionMoreEntityTest;
import brooklyn.catalog.internal.CatalogTestUtils;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.entity.rebind.transformer.CompoundTransformer;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
import brooklyn.util.collections.MutableList;
public class ActivePartialRebindVersionTest extends RebindTestFixtureWithApp {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
index 7856be7..2b5cebf 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogEntityTest.java
@@ -39,12 +39,12 @@ import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.StartableApplication;
import brooklyn.event.basic.Sensors;
-import brooklyn.management.internal.LocalManagementContext;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.TestResourceUnavailableException;
import brooklyn.util.javalang.UrlClassLoader;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
index ff37f74..5d95534 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.catalog.internal.BasicBrooklynCatalog;
@@ -47,8 +48,9 @@ import brooklyn.catalog.internal.CatalogDto;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.internal.BrooklynFeatureEnablement;
+
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.internal.LocalManagementContext;
+
import brooklyn.policy.basic.AbstractPolicy;
import com.google.common.base.Joiner;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
index c04ef95..2c3890c 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
@@ -30,12 +30,12 @@ import brooklyn.camp.lite.CampPlatformWithJustBrooklynMgmt;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
import brooklyn.internal.BrooklynFeatureEnablement;
-import brooklyn.management.internal.LocalManagementContext;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
index 75ba13e..992ca8e 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindEntityTest.java
@@ -52,6 +52,7 @@ import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.api.mementos.BrooklynMementoManifest;
import org.apache.brooklyn.api.mementos.EntityMemento;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl;
@@ -74,7 +75,6 @@ import brooklyn.event.basic.Sensors;
import org.apache.brooklyn.location.basic.LocationConfigTest.MyLocation;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
index 82d122a..ba168cf 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindFailuresTest.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -51,7 +52,6 @@ import brooklyn.entity.basic.EntityFunctions;
import brooklyn.entity.basic.EntityPredicates;
import brooklyn.entity.rebind.RebindEntityTest.MyEntity;
import brooklyn.entity.rebind.RebindEntityTest.MyEntityImpl;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.policy.basic.AbstractPolicy;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.flags.SetFromFlag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java
index db51a91..c368a7a 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindFeedTest.java
@@ -28,6 +28,7 @@ import org.apache.brooklyn.api.entity.Feed;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.core.management.internal.BrooklynGarbageCollector;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestEntity;
import org.apache.brooklyn.test.entity.TestEntityImpl.TestEntityWithoutEnrichers;
@@ -54,7 +55,6 @@ import brooklyn.event.feed.ssh.SshValueFunctions;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.management.internal.BrooklynGarbageCollector;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableList;
import brooklyn.util.http.BetterMockWebServer;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java
index c3c27c2..868665f 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindFeedWithHaTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -40,7 +41,6 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.http.BetterMockWebServer;
import brooklyn.util.repeat.Repeater;
import brooklyn.util.task.BasicExecutionManager;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
index 1522140..d563bea 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestFixture.java
@@ -40,6 +40,8 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.mementos.BrooklynMementoManifest;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.Entities;
@@ -49,8 +51,6 @@ import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
import brooklyn.entity.rebind.persister.FileBasedObjectStore;
import brooklyn.entity.rebind.persister.PersistMode;
import brooklyn.entity.trait.Startable;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.os.Os;
import brooklyn.util.repeat.Repeater;
import brooklyn.util.task.BasicExecutionManager;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java b/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
index 7541009..8e7ec46 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindTestUtils.java
@@ -38,6 +38,9 @@ import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.api.mementos.BrooklynMemento;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
+import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,9 +53,6 @@ import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
import brooklyn.entity.rebind.persister.FileBasedObjectStore;
import brooklyn.entity.rebind.persister.PersistMode;
import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.io.FileUtil;
import brooklyn.util.javalang.Serializers;
import brooklyn.util.javalang.Serializers.ObjectReplacer;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
index cd74827..3dcef6a 100644
--- a/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/persister/XmlMementoSerializerTest.java
@@ -30,8 +30,6 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
-import brooklyn.management.osgi.OsgiTestResources;
-
import org.apache.brooklyn.location.basic.SimulatedLocation;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
@@ -54,13 +52,14 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister.LookupContext;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.management.osgi.OsgiTestResources;
+import org.apache.brooklyn.core.management.osgi.OsgiVersionMoreEntityTest;
import brooklyn.catalog.internal.CatalogItemBuilder;
import brooklyn.catalog.internal.CatalogItemDtoAbstract;
import brooklyn.catalog.internal.CatalogTestUtils;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.group.DynamicCluster;
-import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
index 56896ca..0e00554 100644
--- a/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/transformer/CompoundTransformerTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.entity.rebind.RebindManager.RebindFailureMode;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.TestApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,7 +51,6 @@ import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
import brooklyn.entity.rebind.persister.FileBasedObjectStore;
import brooklyn.entity.rebind.persister.PersistMode;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.guava.SerializablePredicate;
import brooklyn.util.os.Os;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/event/feed/ConfigToAttributesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/event/feed/ConfigToAttributesTest.java b/core/src/test/java/brooklyn/event/feed/ConfigToAttributesTest.java
index fb8f620..ff6ffab 100644
--- a/core/src/test/java/brooklyn/event/feed/ConfigToAttributesTest.java
+++ b/core/src/test/java/brooklyn/event/feed/ConfigToAttributesTest.java
@@ -21,6 +21,8 @@ package brooklyn.event.feed;
import static org.testng.Assert.assertEquals;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.annotations.AfterMethod;
@@ -30,8 +32,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
import brooklyn.event.basic.BasicAttributeSensorAndConfigKey;
import brooklyn.event.basic.TemplatedStringAttributeSensorAndConfigKey;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
public class ConfigToAttributesTest {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManager.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManager.java b/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManager.java
deleted file mode 100644
index 9674d93..0000000
--- a/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManager.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
-import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-
-public class AcmeEntitlementManager extends PerUserEntitlementManager {
-
- public AcmeEntitlementManager() {
- // default mode (if no user specified) is root
- super(Entitlements.root());
-
- super.addUser("admin", Entitlements.root());
-
- super.addUser("support", Entitlements.readOnly());
-
- // metrics can log in but can't really do much else
- super.addUser("metrics", Entitlements.minimal());
-
- // 'navigator' defines a user with a custom entitlement manager allowing
- // access to see entities (in the tree) but not to do anything
- // or even see any sensor information on those entities
- super.addUser("navigator", new EntitlementManager() {
- @Override
- public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
- if (Entitlements.SEE_ENTITY.equals(entitlementClass)) return true;
- return false;
- }
- });
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManagerTest.java b/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManagerTest.java
deleted file mode 100644
index e43fe4a..0000000
--- a/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManagerTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import java.net.URI;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.management.entitlement.Entitlements.EntityAndItem;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
-
-public class AcmeEntitlementManagerTest extends AcmeEntitlementManagerTestFixture {
-
- protected void addGlobalConfig() {
- configBag.put(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, AcmeEntitlementManager.class.getName());
- }
-
- @Test
- public void testOtherAuthorizedUserHasAllPermissions() {
- checkUserHasAllPermissions("other");
- }
-
- @Test
- public void testNullUserHasAllPermissions() {
- checkUserHasAllPermissions(null);
- }
-
- @Test
- public void testNavigatorHasListPermissionsOnly() {
- setup(configBag);
- WebEntitlementContext entitlementContext = new WebEntitlementContext("navigator", "127.0.0.1", URI.create("/X").toString(), "X");
- Entitlements.setEntitlementContext(entitlementContext);
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.ROOT, null));
- Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_ENTITY, app));
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
- // and cannot invoke methods
- confirmEffectorEntitlement(false);
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManagerTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManagerTestFixture.java b/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManagerTestFixture.java
deleted file mode 100644
index 63ee8a0..0000000
--- a/core/src/test/java/brooklyn/management/entitlement/AcmeEntitlementManagerTestFixture.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import java.io.IOException;
-import java.net.URI;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.BasicApplication;
-import brooklyn.entity.basic.Entities;
-import brooklyn.management.entitlement.Entitlements.EntityAndItem;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
-
-public abstract class AcmeEntitlementManagerTestFixture {
-
- protected ManagementContext mgmt;
- protected Application app;
- protected ConfigBag configBag;
-
- public void setup(ConfigBag cfg) {
- mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newEmpty().addFrom(cfg));
- app = ApplicationBuilder.newManagedApp(EntitySpec.create(BasicApplication.class), mgmt);
- }
-
- @BeforeMethod(alwaysRun=true)
- public void init() throws IOException {
- Entitlements.clearEntitlementContext();
- configBag = ConfigBag.newInstance();
- addGlobalConfig();
- }
-
- protected abstract void addGlobalConfig() throws IOException;
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() {
- Entitlements.clearEntitlementContext();
- if (app != null) Entities.destroyAll(app.getManagementContext());
- if (mgmt != null) Entities.destroyAll(mgmt);
- app = null;
- mgmt = null;
- }
-
- @Test
- public void testMetricsHasMinimalPermissions() {
- checkUserHasMinimalPermissions("metrics");
- }
-
- public void checkUserHasMinimalPermissions(String username) {
- setup(configBag);
- WebEntitlementContext entitlementContext = new WebEntitlementContext(username, "127.0.0.1", URI.create("/applications").toString(), "H");
- Entitlements.setEntitlementContext(entitlementContext);
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.ROOT, null));
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_ENTITY, app));
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
- // and can invoke methods
- confirmEffectorEntitlement(false);
- }
-
- @Test
- public void testSupportHasReadOnlyPermissions() {
- checkUserHasReadOnlyPermissions("support");
- }
-
- public void checkUserHasReadOnlyPermissions(String username) {
- setup(configBag);
- WebEntitlementContext entitlementContext = new WebEntitlementContext(username, "127.0.0.1", URI.create("/X").toString(), "B");
- Entitlements.setEntitlementContext(entitlementContext);
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.ROOT, null));
- Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_ENTITY, app));
- Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
- // and cannot invoke methods
- confirmEffectorEntitlement(false);
- }
-
- @Test
- public void testAdminHasAllPermissions() {
- checkUserHasAllPermissions("admin");
- }
-
- public void checkUserHasAllPermissions(String user) {
- setup(configBag);
- WebEntitlementContext entitlementContext = new WebEntitlementContext(user, "127.0.0.1", URI.create("/X").toString(), "A");
- Entitlements.setEntitlementContext(entitlementContext);
- Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.ROOT, null));
- Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_ENTITY, app));
- Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
- // and can invoke methods
- confirmEffectorEntitlement(true);
- }
-
- protected void confirmEffectorEntitlement(boolean shouldSucceed) {
- try {
- ((BasicApplication)app).start(ImmutableList.<Location>of());
- checkNoException(shouldSucceed);
- } catch (Exception e) {
- checkNotEntitledException(shouldSucceed, e);
- }
- }
-
- private void checkNoException(boolean shouldBeEntitled) {
- checkNotEntitledException(shouldBeEntitled, null);
- }
-
- private void checkNotEntitledException(boolean shouldBeEntitled, Exception e) {
- if (e==null) {
- if (shouldBeEntitled) return;
- Assert.fail("entitlement should have been denied");
- }
-
- Exception notEntitled = Exceptions.getFirstThrowableOfType(e, NotEntitledException.class);
- if (notEntitled==null)
- throw Exceptions.propagate(e);
- if (!shouldBeEntitled) {
- /* denied, as it should have been */
- return;
- }
- Assert.fail("entitlement should have been granted, but was denied: "+e);
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/entitlement/EntitlementsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/entitlement/EntitlementsTest.java b/core/src/test/java/brooklyn/management/entitlement/EntitlementsTest.java
deleted file mode 100644
index 901c5ae..0000000
--- a/core/src/test/java/brooklyn/management/entitlement/EntitlementsTest.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.BasicApplication;
-import brooklyn.entity.basic.Entities;
-import brooklyn.management.entitlement.Entitlements.EntityAndItem;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
-
-@Test
-public class EntitlementsTest {
-
- private ManagementContext mgmt;
- private Application app;
-
- @BeforeMethod
- public void setup() {
- mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newEmpty());
- app = ApplicationBuilder.newManagedApp(EntitySpec.create(BasicApplication.class), mgmt);
- }
-
- @AfterMethod
- public void tearDown() {
- if (app != null) Entities.destroyAll(app.getManagementContext());
- if (mgmt != null) Entities.destroyAll(mgmt);
- app = null;
- mgmt = null;
- }
-
- // allowing
- public void testAllowingRoot() {
- EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.ROOT);
- assertTrue(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
- public void testAllowingSeeEntity() {
- EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_ENTITY);
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
- assertTrue(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
- public void testAllowingInvokeEffector() {
- EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.INVOKE_EFFECTOR);
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertTrue(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
- public void testAllowingSeeSensor() {
- EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_SENSOR);
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertTrue(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
- public void testAllowingDeployApplication() {
- EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.DEPLOY_APPLICATION);
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertTrue(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
- public void testAllowingSeeAllServerInfo() {
- EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_ALL_SERVER_INFO);
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertTrue(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
-
- // nonSecret
- public void testSeeNonSecretSensors() {
- EntitlementManager seeNonSecretSensors = Entitlements.FineGrainedEntitlements.seeNonSecretSensors();
- assertFalse(seeNonSecretSensors.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "password")));
- assertTrue(seeNonSecretSensors.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "any-sensor")));
- }
-
- // allOf
- public void testAllOfWithSeeEntityAndSeeSensors() {
- EntitlementManager allOf = Entitlements.FineGrainedEntitlements.allOf(
- Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_ENTITY),
- Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_SENSOR));
- assertFalse(allOf.isEntitled(null, Entitlements.ROOT, null));
- assertTrue(allOf.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(allOf.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertTrue(allOf.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(allOf.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(allOf.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
-
- // anyOf
- public void testAnyOfWithSeeEntityAndSeeSensors() {
- EntitlementManager anyOf = Entitlements.FineGrainedEntitlements.anyOf(
- Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_ENTITY),
- Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_SENSOR));
- assertFalse(anyOf.isEntitled(null, Entitlements.ROOT, null));
- assertTrue(anyOf.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(anyOf.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertTrue(anyOf.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(anyOf.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(anyOf.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
-
- // root
- public void testGlobalRootEntitlement() {
- EntitlementManager root = Entitlements.root();
- assertTrue(root.isEntitled(null, Entitlements.ROOT, null));
- assertTrue(root.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertTrue(root.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertTrue(root.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertTrue(root.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertTrue(root.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
- public void testAppSpecificRootEntitlement() {
- EntitlementManager root = Entitlements.root();
- assertTrue(root.isEntitled(null, Entitlements.SEE_ENTITY, app));
- assertTrue(root.isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- assertTrue(root.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "any-sensor")));
- assertTrue(root.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "password")));
- assertTrue(root.isEntitled(null, Entitlements.DEPLOY_APPLICATION, Entitlements.EntityAndItem.of(app, null)));
- assertTrue(root.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
-
- // minimal
- public void testGlobalMinimalEntitlement() {
- EntitlementManager minimal = Entitlements.minimal();
- assertFalse(minimal.isEntitled(null, Entitlements.ROOT, null));
- assertFalse(minimal.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(minimal.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertFalse(minimal.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(minimal.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(minimal.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
- public void testAppSpecificMinimalEntitlement() {
- EntitlementManager minimal = Entitlements.minimal();
- assertFalse(minimal.isEntitled(null, Entitlements.SEE_ENTITY, app));
- assertFalse(minimal.isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- assertFalse(minimal.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "any-sensor")));
- assertFalse(minimal.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "password")));
- assertFalse(minimal.isEntitled(null, Entitlements.DEPLOY_APPLICATION, Entitlements.EntityAndItem.of(app, null)));
- assertFalse(minimal.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
-
- // readOnly
- public void testGlobalReadOnlyEntitlement() {
- EntitlementManager readOnly = Entitlements.readOnly();
- assertFalse(readOnly.isEntitled(null, Entitlements.ROOT, null));
- assertTrue(readOnly.isEntitled(null, Entitlements.SEE_ENTITY, null));
- assertFalse(readOnly.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
- assertFalse(readOnly.isEntitled(null, Entitlements.SEE_SENSOR, null));
- assertFalse(readOnly.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
- assertFalse(readOnly.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
- }
- public void testAppSpecificReadOnlyEntitlement() {
- EntitlementManager readOnly = Entitlements.readOnly();
- assertTrue(readOnly.isEntitled(null, Entitlements.SEE_ENTITY, app));
- assertFalse(readOnly.isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- assertTrue(readOnly.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "any-sensor")));
- assertFalse(readOnly.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "password")));
- assertFalse(readOnly.isEntitled(null, Entitlements.DEPLOY_APPLICATION, Entitlements.EntityAndItem.of(app, null)));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/entitlement/EntityEntitlementTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/entitlement/EntityEntitlementTest.java b/core/src/test/java/brooklyn/management/entitlement/EntityEntitlementTest.java
deleted file mode 100644
index b6bf5c1..0000000
--- a/core/src/test/java/brooklyn/management/entitlement/EntityEntitlementTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.BasicApplication;
-import brooklyn.entity.basic.Entities;
-import brooklyn.management.entitlement.Entitlements.EntityAndItem;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
-
-public class EntityEntitlementTest {
-
- private static final Logger log = LoggerFactory.getLogger(EntityEntitlementTest.class);
-
- ManagementContext mgmt;
- Application app;
-
- public void setup(ConfigBag cfg) {
- mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newEmpty().addFrom(cfg));
- app = ApplicationBuilder.newManagedApp(EntitySpec.create(BasicApplication.class), mgmt);
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() {
- if (app != null) Entities.destroyAll(app.getManagementContext());
- if (mgmt != null) Entities.destroyAll(mgmt);
- app = null;
- mgmt = null;
- }
-
- @Test
- public void testDefaultRootAllows() {
- setup(ConfigBag.newInstance());
- // default "root" access allows ROOT permission, and invoke effector, etc
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.ROOT, null));
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
- // and can invoke methods, without any user/login registered
- confirmEffectorEntitlement(true);
- confirmSensorEntitlement(true);
- }
-
- @Test
- public void testExplicitRootAllows() {
- setup(ConfigBag.newInstance().configure(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, "root"));
-
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.ROOT, null));
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
-
- confirmEffectorEntitlement(true);
- confirmSensorEntitlement(true);
- }
-
- @Test
- public void testReadOnlyThrowsNotEntitled() {
- try {
- setup(ConfigBag.newInstance().configure(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, "readonly"));
- // eventually above call will fail in app creation, but for now the call below falls
- ((BasicApplication)app).start(ImmutableList.<Location>of());
- tearDown();
-
- Assert.fail("something should have been disallowed");
- } catch (Exception e) {
- checkNotEntitledException(e);
- } finally {
- app = null;
- if (mgmt!=null) ((LocalManagementContext)mgmt).terminate();
- mgmt = null;
- }
- }
-
- @Test(enabled=false)
- // this test (and minimal below) currently work fine until tearDown,
- // but then of course they don't have entitlement to call 'stop';
- // (as more entitlement checks are added app creation will fail).
- //
- // TODO these tests should set up a user with the permission,
- // e.g. so system has root, but 'bob' has read-only, then we can test read-only;
- // TODO rest api tests, as some of the permissions will only be enforced at REST level
- public void testReadOnlyAllowsSome() {
- setup(ConfigBag.newInstance().configure(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, "readonly"));
-
- Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.ROOT, null));
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
- Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
-
- confirmEffectorEntitlement(false);
- confirmSensorEntitlement(true);
- }
-
- @Test(enabled=false)
- public void testMinimalDisallows() {
- setup(ConfigBag.newInstance().configure(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, "minimal"));
-
- Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.ROOT, null));
- Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
- Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
- Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
-
- confirmEffectorEntitlement(false);
- confirmSensorEntitlement(false);
- }
-
- protected void confirmSensorEntitlement(boolean shouldSucceed) {
- // TODO... based on above
- // (though maybe we should test against REST API classes rather than lower level programmatic?
- // TBC...)
- log.warn("confirmSensorEntitlement still required!");
- }
-
- // TODO specific users tests
-
- protected void confirmEffectorEntitlement(boolean shouldSucceed) {
- try {
- ((BasicApplication)app).start(ImmutableList.<Location>of());
- checkNoException(shouldSucceed);
- } catch (Exception e) {
- checkNotEntitledException(shouldSucceed, e);
- }
- }
-
- private void checkNoException(boolean shouldBeEntitled) {
- checkNotEntitledException(shouldBeEntitled, null);
- }
-
- private void checkNotEntitledException(Exception e) {
- checkNotEntitledException(false, e);
- }
-
- private void checkNotEntitledException(boolean shouldBeEntitled, Exception e) {
- if (e==null) {
- if (shouldBeEntitled) return;
- Assert.fail("entitlement should have been denied");
- }
-
- Exception notEntitled = Exceptions.getFirstThrowableOfType(e, NotEntitledException.class);
- if (notEntitled==null)
- throw Exceptions.propagate(e);
- if (!shouldBeEntitled) {
- /* denied, as it should have been */
- return;
- }
- Assert.fail("entitlement should have been granted, but was denied: "+e);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/entitlement/PerUserEntitlementManagerPropertiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/entitlement/PerUserEntitlementManagerPropertiesTest.java b/core/src/test/java/brooklyn/management/entitlement/PerUserEntitlementManagerPropertiesTest.java
deleted file mode 100644
index b583c08..0000000
--- a/core/src/test/java/brooklyn/management/entitlement/PerUserEntitlementManagerPropertiesTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.entitlement;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Properties;
-
-import org.testng.annotations.Test;
-
-
-public class PerUserEntitlementManagerPropertiesTest extends AcmeEntitlementManagerTestFixture {
-
- protected void addGlobalConfig() throws IOException {
- Properties moreProps = new Properties();
- moreProps.load(new StringReader(
- "brooklyn.entitlements.global=brooklyn.management.entitlement.PerUserEntitlementManager\n"
- + "brooklyn.entitlements.perUser.admin=root\n"
- + "brooklyn.entitlements.perUser.support=readonly\n"
- + "brooklyn.entitlements.perUser.metrics=minimal"));
- configBag.putAll(moreProps);
- }
-
- @Test
- public void testOtherAuthorizedUserHasMinimalPermissions() {
- checkUserHasMinimalPermissions("other");
- }
-
- @Test
- public void testNullUserHasAllPermissions() {
- checkUserHasAllPermissions(null);
- }
-
-
-}
-
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerFileBasedTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerFileBasedTest.java b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerFileBasedTest.java
deleted file mode 100644
index 7091f08..0000000
--- a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerFileBasedTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import java.io.File;
-
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.rebind.persister.FileBasedObjectStore;
-import brooklyn.util.os.Os;
-
-@Test
-public class HighAvailabilityManagerFileBasedTest extends HighAvailabilityManagerTestFixture {
-
- private File dir;
-
- protected FileBasedObjectStore newPersistenceObjectStore() {
- if (dir!=null)
- throw new IllegalStateException("Test does not support multiple object stores");
- dir = Os.newTempDir(getClass());
- return new FileBasedObjectStore(dir);
- }
-
- @Override
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws Exception {
- super.tearDown();
- dir = Os.deleteRecursively(dir).asNullOrThrowing();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryIntegrationTest.java b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryIntegrationTest.java
deleted file mode 100644
index a379faa..0000000
--- a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryIntegrationTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.rebind.persister.InMemoryObjectStore;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.base.Ticker;
-
-@Test(groups="Integration")
-public class HighAvailabilityManagerInMemoryIntegrationTest extends HighAvailabilityManagerTestFixture {
-
- private static final Logger log = LoggerFactory.getLogger(HighAvailabilityManagerInMemoryIntegrationTest.class);
-
- @Override
- protected PersistenceObjectStore newPersistenceObjectStore() {
- return new InMemoryObjectStore();
- }
-
- @Override
- protected Duration getPollPeriod() {
- return Duration.millis(100);
- }
-
- @Override
- protected long tickerAdvance(Duration duration) {
- log.info("sleeping for "+duration);
- // actually sleep, in order to advance the local time ticker
- Time.sleep(duration);
- return super.tickerAdvance(duration);
- }
-
- @Override
- protected Ticker getRemoteTicker() {
- // use real times
- return null;
- }
-
- @Override
- @Test(groups="Integration", enabled=false, invocationCount=50)
- public void testGetManagementPlaneStatusManyTimes() throws Exception {
- }
-
- @Test(groups="Integration")
- @Override
- public void testGetManagementPlaneStatus() throws Exception {
- super.testGetManagementPlaneStatus();
- }
-
- @Test(groups="Integration")
- @Override
- public void testDoesNotPromoteIfMasterTimeoutNotExpired() throws Exception {
- super.testDoesNotPromoteIfMasterTimeoutNotExpired();
- }
-
- @Test(groups="Integration")
- @Override
- public void testGetManagementPlaneSyncStateDoesNotThrowNpeBeforePersisterSet() throws Exception {
- super.testGetManagementPlaneSyncStateDoesNotThrowNpeBeforePersisterSet();
- }
-
- @Test(groups="Integration")
- @Override
- public void testGetManagementPlaneSyncStateInfersTimedOutNodeAsFailed() throws Exception {
- super.testGetManagementPlaneSyncStateInfersTimedOutNodeAsFailed();
- }
-
- @Test(groups="Integration")
- @Override
- public void testPromotes() throws Exception {
- super.testPromotes();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java b/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java
deleted file mode 100644
index ff86733..0000000
--- a/core/src/test/java/brooklyn/management/ha/HighAvailabilityManagerInMemoryTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.location.NoMachinesAvailableException;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.apache.brooklyn.test.entity.TestApplication;
-import org.apache.brooklyn.test.entity.TestEntity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.rebind.persister.InMemoryObjectStore;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-
-import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.util.collections.MutableList;
-
-import com.google.common.collect.Iterables;
-
-@Test
-public class HighAvailabilityManagerInMemoryTest extends HighAvailabilityManagerTestFixture {
-
- private static final Logger log = LoggerFactory.getLogger(HighAvailabilityManagerInMemoryTest.class);
-
- protected PersistenceObjectStore newPersistenceObjectStore() {
- return new InMemoryObjectStore();
- }
-
- public void testGetManagementPlaneStatus() throws Exception {
- super.testGetManagementPlaneStatus();
- }
-
- // extra test that promoteToMaster doesn't interfere with what is managed
- public void testLocationsStillManagedCorrectlyAfterDoublePromotion() throws NoMachinesAvailableException {
- HighAvailabilityManagerImpl ha = (HighAvailabilityManagerImpl) managementContext.getHighAvailabilityManager();
- ha.start(HighAvailabilityMode.MASTER);
-
- TestApplication app = TestApplication.Factory.newManagedInstanceForTests(managementContext);
-
- LocalhostMachineProvisioningLocation l = app.newLocalhostProvisioningLocation();
- l.setConfig(TestEntity.CONF_NAME, "sample1");
- Assert.assertEquals(l.getConfig(TestEntity.CONF_NAME), "sample1");
-
- SshMachineLocation l2 = l.obtain();
- Assert.assertEquals(l2.getConfig(TestEntity.CONF_NAME), "sample1");
- Assert.assertNotNull(l2.getParent(), "Parent not set after dodgy promoteToMaster");
- Assert.assertEquals(l2.getParent().getConfig(TestEntity.CONF_NAME), "sample1");
-
- TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class).location(l).location(l2));
- log.info("Entities managed are: "+managementContext.getEntityManager().getEntities());
- Collection<Location> le = entity.getLocations();
- log.info("Locs at entity are: "+le);
- Collection<Location> lm = managementContext.getLocationManager().getLocations();
- log.info("Locs managed are: "+lm);
- log.info(" objs: "+identities(lm));
- Assert.assertNotNull(entity.getManagementSupport().getManagementContext());
- Assert.assertNotNull( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext());
- Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().isDeployed());
- checkEntitiesHealthy(app, entity);
-
- managementContext.getRebindManager().forcePersistNow(true, null);
- log.info("Test deliberately doing unnecessary extra promoteToMaster");
- ha.promoteToMaster();
-
- log.info("Entities managed are: "+managementContext.getEntityManager().getEntities());
- Collection<Location> lle = entity.getLocations();
- log.info("Locs at entity(old) are: "+lle);
- log.info(" objs: "+identities(lle));
- // check entities -- the initial-full promotion previously re-created items,
- // and plugged them in as children, but only managed the roots
- checkEntitiesHealthy(app, entity);
-
- // assert what's in the location manager is accurate
- Collection<Location> llmm = managementContext.getLocationManager().getLocations();
- log.info("Locs managed are: "+llmm);
- log.info(" objs: "+identities(llmm));
- Assert.assertEquals(llmm, lm);
- SshMachineLocation ll2a = Iterables.getOnlyElement(Iterables.filter(llmm, SshMachineLocation.class));
- Assert.assertEquals(ll2a.getConfig(TestEntity.CONF_NAME), "sample1");
- Assert.assertNotNull(ll2a.getParent(), "Parent not set after dodgy promoteToMaster");
- Assert.assertEquals(ll2a.getParent().getConfig(TestEntity.CONF_NAME), "sample1");
-
- // and what's in the location manager is accurate
- Entity ee = (Entity)managementContext.lookup(entity.getId());
- Collection<Location> llee = ee.getLocations();
- log.info("Locs at entity(lookup) are: "+llee);
- log.info(" objs: "+identities(llee));
- SshMachineLocation ll2b = Iterables.getOnlyElement(Iterables.filter(llee, SshMachineLocation.class));
- Assert.assertEquals(ll2b.getConfig(TestEntity.CONF_NAME), "sample1");
- Assert.assertNotNull(ll2b.getParent(), "Parent not set after dodgy promoteToMaster");
- Assert.assertEquals(ll2b.getParent().getConfig(TestEntity.CONF_NAME), "sample1");
- }
-
- private void checkEntitiesHealthy(TestApplication app, TestEntity entity) {
- Assert.assertNotNull(app.getManagementSupport().getManagementContext());
- Assert.assertTrue( app.getManagementSupport().getManagementContext().isRunning() );
-
- Assert.assertNotNull(entity.getManagementSupport().getManagementContext());
- Assert.assertNotNull( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext() );
- Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().isDeployed());
- Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext() instanceof LocalManagementContext );
- }
-
- @Test(groups="Integration", invocationCount=50)
- public void testLocationsStillManagedCorrectlyAfterDoublePromotionManyTimes() throws NoMachinesAvailableException {
- testLocationsStillManagedCorrectlyAfterDoublePromotion();
- }
-
- private List<String> identities(Collection<?> objs) {
- List<String> result = MutableList.of();
- for (Object obj: objs)
- result.add(Integer.toHexString(System.identityHashCode(obj)));
- return result;
- }
-
-}
[06/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
deleted file mode 100644
index 0877ed5..0000000
--- a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.osgi;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
-import java.util.List;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.launch.Framework;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import org.apache.brooklyn.api.basic.BrooklynObject;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.api.policy.PolicySpec;
-
-import brooklyn.catalog.internal.CatalogEntityItemDto;
-import brooklyn.catalog.internal.CatalogItemBuilder;
-import brooklyn.catalog.internal.CatalogItemDtoAbstract;
-import brooklyn.catalog.internal.CatalogTestUtils;
-import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.effector.Effectors;
-import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.entity.proxying.InternalPolicyFactory;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-
-import org.apache.brooklyn.test.TestResourceUnavailableException;
-import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.test.entity.TestApplication;
-
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.os.Os;
-import brooklyn.util.osgi.Osgis;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-
-
-/**
- * Tests that OSGi entities load correctly and have the right catalog information set.
- * Note further tests done elsewhere using CAMP YAML (referring to methods in this class).
- */
-public class OsgiVersionMoreEntityTest {
-
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
- public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
-
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V1_PATH;
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V1_PATH;
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_PATH;
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V2_PATH;
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH;
- public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH;
-
- public static final String TEST_VERSION = "0.1.0";
-
- public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1 = "Hi BROOKLYN from V1";
- public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2 = "HI BROOKLYN FROM V2";
- public static final String EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN = "HO BROOKLYN FROM V2 EVIL TWIN";
-
- protected LocalManagementContext mgmt;
- protected TestApplication app;
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).build();
- app = TestApplication.Factory.newManagedInstanceForTests(mgmt);
- }
-
- @AfterMethod(alwaysRun=true)
- public void tearDown() throws BundleException, IOException, InterruptedException {
- Entities.destroyAll(mgmt);
- }
-
- /**
- * Test fix for
- * java.lang.NoClassDefFoundError: brooklyn.event.AttributeSensor not found by io.brooklyn.brooklyn-test-osgi-entities [41]
- */
- @Test
- public void testEntityProxy() throws Exception {
- File storageTempDir = Os.newTempDir("osgi-standalone");
- Framework framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
-
- try {
- ManagementContextInternal managementContext;
- InternalEntityFactory factory;
-
- managementContext = new LocalManagementContextForTests();
- InternalPolicyFactory policyFactory = new InternalPolicyFactory(managementContext);
- factory = new InternalEntityFactory(managementContext, managementContext.getEntityManager().getEntityTypeRegistry(), policyFactory);
-
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_ENTITIES_PATH);
- Bundle bundle = Osgis.install(framework, BROOKLYN_TEST_OSGI_ENTITIES_PATH);
- @SuppressWarnings("unchecked")
- Class<? extends Entity> bundleCls = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntityImpl");
- @SuppressWarnings("unchecked")
- Class<? extends Entity> bundleInterface = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntity");
-
- @SuppressWarnings("unchecked")
- EntitySpec<Entity> spec = (EntitySpec<Entity>) (((EntitySpec<Entity>)EntitySpec.create(bundleInterface))).impl(bundleCls);
- Entity entity = bundleCls.newInstance();
- factory.createEntityProxy(spec, entity);
-
- if (managementContext != null) Entities.destroyAll(managementContext);
- } finally {
- OsgiStandaloneTest.tearDownOsgiFramework(framework, storageTempDir);
- }
- }
-
- protected CatalogItem<?, ?> addCatalogItemWithTypeAsName(String type, String version, String ...libraries) {
- return addCatalogItemWithNameAndType(type, version, type, libraries);
- }
- protected CatalogItem<?, ?> addCatalogItemWithNameAndType(String symName, String version, String type, String ...libraries) {
- return addCatalogItemWithNameAndType(mgmt, symName, version, type, libraries);
- }
-
- @SuppressWarnings("deprecation")
- static CatalogItem<?, ?> addCatalogItemWithNameAndType(ManagementContext mgmt, String symName, String version, String type, String ...libraries) {
- CatalogEntityItemDto c1 = newCatalogItemWithNameAndType(symName, version, type, libraries);
- mgmt.getCatalog().addItem(c1);
- CatalogItem<?, ?> c2 = mgmt.getCatalog().getCatalogItem(symName, version);
- Preconditions.checkNotNull(c2, "Item "+type+":"+version+" was not found after adding it");
- return c2;
- }
-
- static CatalogEntityItemDto newCatalogItemWithTypeAsName(String type, String version, String ...libraries) {
- return newCatalogItemWithNameAndType(type, version, type, libraries);
- }
- static CatalogEntityItemDto newCatalogItemWithNameAndType(String symName, String version, String type, String ...libraries) {
- @SuppressWarnings("deprecation")
- CatalogEntityItemDto c1 = CatalogItemBuilder.newEntity(symName, version)
- .javaType(type)
- .libraries(CatalogItemDtoAbstract.parseLibraries(Arrays.asList(libraries)))
- .build();
- return c1;
- }
-
- protected Entity addItemFromCatalog(CatalogItem<?, ?> c2) {
- return addItemFromCatalog(mgmt, app, c2);
- }
-
- public static Entity addItemFromCatalog(ManagementContext mgmt, TestApplication parent, CatalogItem<?, ?> c2) {
- return parent.createAndManageChild( CatalogTestUtils.createEssentialEntitySpec(mgmt, c2) );
- }
-
- public static void assertV1MethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1);
- }
- public static void assertV2MethodCall(BrooklynObject me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2);
- }
- public static void assertV2EvilTwinMethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- Assert.assertEquals(doMethodCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN);
- }
-
- public static Object doMethodCallBrooklyn(BrooklynObject me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- return me.getClass().getMethod("sayHI", String.class).invoke(me, "Brooklyn");
- }
-
- public static void assertV1EffectorCall(Entity me) {
- Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V1);
- }
- public static void assertV2EffectorCall(Entity me) {
- Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2);
- }
- public static void assertV2EvilTwinEffectorCall(Entity me) {
- Assert.assertEquals(doEffectorCallBrooklyn(me), EXPECTED_SAY_HI_BROOKLYN_RESPONSE_FROM_V2_EVIL_TWIN);
- }
-
- public static String doEffectorCallBrooklyn(Entity me) {
- return me.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), ImmutableMap.of("name", "brooklyn")).getUnchecked();
- }
-
- public static CatalogItem<?, ?> addMoreEntityV1(ManagementContext mgmt, String versionToRegister) {
- TestResourceUnavailableException.throwIfResourceUnavailable(OsgiVersionMoreEntityTest.class, BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
- return addCatalogItemWithNameAndType(mgmt,
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- versionToRegister,
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
- }
- public static CatalogItem<?, ?> addMoreEntityV2(ManagementContext mgmt, String versionToRegister) {
- TestResourceUnavailableException.throwIfResourceUnavailable(OsgiVersionMoreEntityTest.class, BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
- return addCatalogItemWithNameAndType(mgmt,
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- versionToRegister,
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- BROOKLYN_TEST_MORE_ENTITIES_V2_URL,
- BROOKLYN_TEST_OSGI_ENTITIES_URL);
- }
-
- @Test
- public void testMoreEntitiesV1() throws Exception {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
-
- CatalogItem<?, ?> c2 = addMoreEntityV1(mgmt, TEST_VERSION);
-
- // test load and instantiate
- Entity me = addItemFromCatalog(c2);
- Assert.assertEquals(me.getCatalogItemId(), CatalogUtils.getVersionedId(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION));
-
- assertV1MethodCall(me);
- assertV1EffectorCall(me);
-
- // test adding a child gets the right type; this time by entity parent hierarchy
- BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, c2);
- @SuppressWarnings({ "unchecked", "rawtypes" })
- Entity me2 = me.addChild(EntitySpec.create( (Class)loader.loadClass(c2.getJavaType()) ));
- Assert.assertEquals(me2.getCatalogItemId(), CatalogUtils.getVersionedId(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION));
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected PolicySpec<?> getPolicySpec(CatalogItem<?, ?> cp) {
- BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, cp);
- PolicySpec spec = PolicySpec.create( (Class)loader.loadClass(cp.getJavaType()) );
- spec.catalogItemId(cp.getId());
- return spec;
- }
-
- @Test
- public void testMoreEntitiesV1Policy() throws Exception {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_ENTITIES_PATH);
-
- CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- TEST_VERSION,
- BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
-
- // test load and instantiate
- Entity me = addItemFromCatalog(c2);
-
- CatalogItem<?, ?> cp = addCatalogItemWithTypeAsName(
- OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY,
- TEST_VERSION,
- BROOKLYN_TEST_OSGI_ENTITIES_URL);
- me.addPolicy(getPolicySpec(cp));
-
- Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
-
- String catalogItemId = Iterables.getOnlyElement( me.getPolicies() ).getCatalogItemId();
- Assert.assertNotNull(catalogItemId);
- // must be the actual source bundle
- Assert.assertFalse(catalogItemId.equals(me.getCatalogItemId()), "catalog item id is: "+catalogItemId);
- Assert.assertTrue(catalogItemId.equals(CatalogUtils.getVersionedId(OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY, TEST_VERSION)), "catalog item id is: "+catalogItemId);
- }
-
- @Test
- public void testMoreEntitiesV2FailsWithoutBasicTestOsgiEntitiesBundle() throws Exception {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
-
- CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- TEST_VERSION,
- BROOKLYN_TEST_MORE_ENTITIES_V2_URL);
-
- // test load and instantiate
- try {
- Entity me = addItemFromCatalog(c2);
- Assert.fail("Should have failed, with unresolved dependency; instead got "+me);
- } catch (Exception e) {
- Assert.assertTrue(e.toString().toLowerCase().contains("unresolved constraint"), "Missing expected text in error: "+e);
- Assert.assertTrue(e.toString().toLowerCase().contains("wiring.package"), "Missing expected text in error: "+e);
- Assert.assertTrue(e.toString().toLowerCase().contains("brooklyn.osgi.tests"), "Missing expected text in error: "+e);
- }
- }
-
- // V2 works with dependency declared, and can load
- // and has policy, with policy item catalog ID is reasonable
- @Test
- public void testMoreEntitiesV2() throws Exception {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
-
- CatalogItem<?, ?> c2 = addCatalogItemWithTypeAsName(
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- TEST_VERSION,
- BROOKLYN_TEST_MORE_ENTITIES_V2_URL,
- BROOKLYN_TEST_OSGI_ENTITIES_URL);
-
- // test load and instantiate
- Entity me = addItemFromCatalog(c2);
- Assert.assertEquals(me.getCatalogItemId(), CatalogUtils.getVersionedId(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION));
-
- assertV2MethodCall(me);
- assertV2EffectorCall(me);
- Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
-
- String catalogItemId = Iterables.getOnlyElement( me.getPolicies() ).getCatalogItemId();
- Assert.assertNotNull(catalogItemId);
- // allow either me's bundle (more) or the actual source bundle
- Assert.assertTrue(catalogItemId.equals(me.getCatalogItemId()) || catalogItemId.startsWith("brooklyn-test-osgi-entities"));
- }
-
- @Test
- public void testMoreEntitiesV1ThenV2GivesV2() throws Exception {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
-
- addCatalogItemWithTypeAsName(
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- TEST_VERSION,
- BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
- addCatalogItemWithTypeAsName(
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- TEST_VERSION,
- BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
-
- // test load and instantiate
- Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION) );
-
- assertV2MethodCall(me);
- assertV2EffectorCall(me);
- Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
- }
-
- @Test
- public void testMoreEntitiesV2ThenV1GivesV1() throws Exception {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
-
- addCatalogItemWithTypeAsName(
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- TEST_VERSION,
- BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
- addCatalogItemWithTypeAsName(
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- TEST_VERSION,
- BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
-
- // test load and instantiate
- Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, TEST_VERSION) );
- /*
- * WARNING - Weird maven-bundle-plugin and OSGi behaviour. Some caveats:
- * <p>
- * (1) When "import-package" declares a version, that is the *minimum* version;
- * it may be that semantic versioning is applied, so 1.3.1 = [1.3.1,4.0.0);
- * or it may be just a minimum 1.3.1 = [1.3.1,) ... i can't find good docs
- * [but see http://www.christianposta.com/blog/?p=241]
- * <p>
- * (2) Different versions of maven-bundle-plugin do wildly different things.
- * * v1.4.0 attaches the version to import-package (so you get the minimum
- * which can cause this test to fail);
- * * v2.x does not seem to declare the exported package at all in import-package
- * (violating the so-called best practice, see
- * http://blog.osgi.org/2007/04/importance-of-exporting-nd-importing.html )
- * * v2.4.0 gives a huge list in import/export package, with semver ranges;
- * but the other versions seem not to list much and they do NOT have versions
- * <p>
- * The tests are all working with 2.5.3 but if version dependencies become any
- * more intertwined maven-bundle-plugin will almost certainly NOT do the wrong
- * thing because packages do not have versions. (Ironically, 1.4.0 seems the
- * best behaved, but for the minimum/semver package version behaviour, and
- * even that wouldn't be so bad if you're doing semver, or if you figure out
- * how to override with a _versionpolicy tag!)
- */
- assertV1MethodCall(me);
- assertV1EffectorCall(me);
- Assert.assertEquals(me.getPolicies().size(), 0, "Wrong number of policies: "+me.getPolicies());
- }
-
- @Test
- public void testUnfazedByMoreEntitiesV1AndV2AndV2EvilTwin() throws Exception {
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V1_PATH);
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_PATH);
- TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_PATH);
-
- addCatalogItemWithNameAndType("v1",
- TEST_VERSION,
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
- addCatalogItemWithNameAndType("v2",
- TEST_VERSION,
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
- addCatalogItemWithNameAndType("v2-evil",
- TEST_VERSION,
- OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY,
- BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
-
- // test osgi finding
-
- List<Bundle> bundles = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
- .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL).findAll();
- Assert.assertEquals(bundles.size(), 3, "Wrong list of bundles: "+bundles);
-
- Maybe<Bundle> preferredVersion = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
- .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL).find();
- Assert.assertTrue(preferredVersion.isPresent());
- Assert.assertEquals(preferredVersion.get().getVersion().toString(), "0.2.0");
-
- Maybe<Bundle> evilVersion = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework()).
- preferringFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL).find();
- Assert.assertTrue(evilVersion.isPresent());
- Assert.assertEquals(evilVersion.get().getVersion().toString(), "0.2.0");
-
- // test preferredUrl vs requiredUrl
-
- Maybe<Bundle> versionIgnoresInvalidPreferredUrl = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
- .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL)
- .version(TEST_VERSION)
- .preferringFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL).find();
- Assert.assertTrue(versionIgnoresInvalidPreferredUrl.isPresent());
- Assert.assertEquals(versionIgnoresInvalidPreferredUrl.get().getVersion().toString(), TEST_VERSION);
-
- Maybe<Bundle> versionRespectsInvalidRequiredUrl = Osgis.bundleFinder(mgmt.getOsgiManager().get().getFramework())
- .symbolicName(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL)
- .version(TEST_VERSION)
- .requiringFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL).find();
- Assert.assertFalse(versionRespectsInvalidRequiredUrl.isPresent());
-
- // test entity resolution
-
- Entity v2 = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v2", TEST_VERSION) );
- assertV2MethodCall(v2);
- assertV2EffectorCall(v2);
- Assert.assertEquals(v2.getPolicies().size(), 1, "Wrong number of policies: "+v2.getPolicies());
-
- Entity v2_evil = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v2-evil", TEST_VERSION) );
- assertV2EvilTwinMethodCall(v2_evil);
- assertV2EvilTwinEffectorCall(v2_evil);
- Assert.assertEquals(v2_evil.getPolicies().size(), 1, "Wrong number of policies: "+v2_evil.getPolicies());
-
- Entity v1 = addItemFromCatalog( mgmt.getCatalog().getCatalogItem("v1", TEST_VERSION) );
- assertV1MethodCall(v1);
- assertV1EffectorCall(v1);
- Assert.assertEquals(v1.getPolicies().size(), 0, "Wrong number of policies: "+v1.getPolicies());
- }
-
- // TODO versioning (WIP until #92), install both V1 and V2 with version number, and test that both work
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java b/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java
index f419101..85eaf3d 100644
--- a/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java
+++ b/core/src/test/java/brooklyn/qa/longevity/EntityCleanupLongevityTestFixture.java
@@ -26,6 +26,9 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.event.SensorEvent;
import org.apache.brooklyn.api.event.SensorEventListener;
import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.management.internal.AbstractManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -43,9 +46,6 @@ import brooklyn.internal.storage.impl.BrooklynStorageImpl;
import org.apache.brooklyn.location.basic.SimulatedLocation;
-import brooklyn.management.internal.AbstractManagementContext;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.util.task.BasicExecutionManager;
import brooklyn.util.task.TaskScheduler;
import brooklyn.util.text.Strings;
@@ -66,7 +66,7 @@ public abstract class EntityCleanupLongevityTestFixture {
final static long MEMORY_MARGIN_OF_ERROR = 10*1024*1024;
/** Iterations might currently leave behind:
- * <li> brooklyn.management.usage.ApplicationUsage$ApplicationEvent (one each for started/stopped/destroyed, per app)
+ * <li> org.apache.brooklyn.core.management.usage.ApplicationUsage$ApplicationEvent (one each for started/stopped/destroyed, per app)
* <li> SingleThreadedScheduler (subscription delivery tag for the entity)
* <p>
* Set at 2kb per iter for now. We'd like to drop this to 0 of course!
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java b/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java
index f5e0052..578164f 100644
--- a/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java
+++ b/core/src/test/java/brooklyn/util/task/ssh/SshTasksTest.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +38,6 @@ import brooklyn.entity.basic.Entities;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocation;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.net.Urls;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommandsIntegrationTest;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java b/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java
index b19c389..e60310d 100644
--- a/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java
+++ b/core/src/test/java/brooklyn/util/task/system/SystemTasksTest.java
@@ -21,13 +21,13 @@ package brooklyn.util.task.system;
import java.io.File;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
import brooklyn.util.os.Os;
import brooklyn.util.task.ssh.SshTasks;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java b/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java
index a9143cc..bd8ef87 100644
--- a/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java
+++ b/core/src/test/java/brooklyn/util/text/TemplateProcessorTest.java
@@ -21,6 +21,7 @@ package brooklyn.util.text;
import static org.testng.Assert.assertEquals;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.test.entity.TestApplication;
import org.apache.brooklyn.test.entity.TestEntity;
import org.testng.Assert;
@@ -30,7 +31,6 @@ import org.testng.annotations.Test;
import brooklyn.entity.BrooklynAppUnitTestSupport;
import brooklyn.event.basic.DependentConfiguration;
-import brooklyn.management.internal.ManagementContextInternal;
import brooklyn.test.FixedLocaleTest;
import com.google.common.collect.ImmutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManager.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManager.java b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManager.java
new file mode 100644
index 0000000..0d0daa5
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManager.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import org.apache.brooklyn.api.management.entitlement.EntitlementClass;
+import org.apache.brooklyn.api.management.entitlement.EntitlementContext;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.PerUserEntitlementManager;
+
+public class AcmeEntitlementManager extends PerUserEntitlementManager {
+
+ public AcmeEntitlementManager() {
+ // default mode (if no user specified) is root
+ super(Entitlements.root());
+
+ super.addUser("admin", Entitlements.root());
+
+ super.addUser("support", Entitlements.readOnly());
+
+ // metrics can log in but can't really do much else
+ super.addUser("metrics", Entitlements.minimal());
+
+ // 'navigator' defines a user with a custom entitlement manager allowing
+ // access to see entities (in the tree) but not to do anything
+ // or even see any sensor information on those entities
+ super.addUser("navigator", new EntitlementManager() {
+ @Override
+ public <T> boolean isEntitled(EntitlementContext context, EntitlementClass<T> entitlementClass, T entitlementClassArgument) {
+ if (Entitlements.SEE_ENTITY.equals(entitlementClass)) return true;
+ return false;
+ }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTest.java
new file mode 100644
index 0000000..82fa5bd
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import java.net.URI;
+
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.WebEntitlementContext;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class AcmeEntitlementManagerTest extends AcmeEntitlementManagerTestFixture {
+
+ protected void addGlobalConfig() {
+ configBag.put(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, AcmeEntitlementManager.class.getName());
+ }
+
+ @Test
+ public void testOtherAuthorizedUserHasAllPermissions() {
+ checkUserHasAllPermissions("other");
+ }
+
+ @Test
+ public void testNullUserHasAllPermissions() {
+ checkUserHasAllPermissions(null);
+ }
+
+ @Test
+ public void testNavigatorHasListPermissionsOnly() {
+ setup(configBag);
+ WebEntitlementContext entitlementContext = new WebEntitlementContext("navigator", "127.0.0.1", URI.create("/X").toString(), "X");
+ Entitlements.setEntitlementContext(entitlementContext);
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.ROOT, null));
+ Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_ENTITY, app));
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+ // and cannot invoke methods
+ confirmEffectorEntitlement(false);
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java
new file mode 100644
index 0000000..5689da2
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/AcmeEntitlementManagerTestFixture.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.NotEntitledException;
+import org.apache.brooklyn.core.management.entitlement.WebEntitlementContext;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.BasicApplication;
+import brooklyn.entity.basic.Entities;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
+
+public abstract class AcmeEntitlementManagerTestFixture {
+
+ protected ManagementContext mgmt;
+ protected Application app;
+ protected ConfigBag configBag;
+
+ public void setup(ConfigBag cfg) {
+ mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newEmpty().addFrom(cfg));
+ app = ApplicationBuilder.newManagedApp(EntitySpec.create(BasicApplication.class), mgmt);
+ }
+
+ @BeforeMethod(alwaysRun=true)
+ public void init() throws IOException {
+ Entitlements.clearEntitlementContext();
+ configBag = ConfigBag.newInstance();
+ addGlobalConfig();
+ }
+
+ protected abstract void addGlobalConfig() throws IOException;
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() {
+ Entitlements.clearEntitlementContext();
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ app = null;
+ mgmt = null;
+ }
+
+ @Test
+ public void testMetricsHasMinimalPermissions() {
+ checkUserHasMinimalPermissions("metrics");
+ }
+
+ public void checkUserHasMinimalPermissions(String username) {
+ setup(configBag);
+ WebEntitlementContext entitlementContext = new WebEntitlementContext(username, "127.0.0.1", URI.create("/applications").toString(), "H");
+ Entitlements.setEntitlementContext(entitlementContext);
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.ROOT, null));
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_ENTITY, app));
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+ // and can invoke methods
+ confirmEffectorEntitlement(false);
+ }
+
+ @Test
+ public void testSupportHasReadOnlyPermissions() {
+ checkUserHasReadOnlyPermissions("support");
+ }
+
+ public void checkUserHasReadOnlyPermissions(String username) {
+ setup(configBag);
+ WebEntitlementContext entitlementContext = new WebEntitlementContext(username, "127.0.0.1", URI.create("/X").toString(), "B");
+ Entitlements.setEntitlementContext(entitlementContext);
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.ROOT, null));
+ Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_ENTITY, app));
+ Assert.assertFalse(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+ // and cannot invoke methods
+ confirmEffectorEntitlement(false);
+ }
+
+ @Test
+ public void testAdminHasAllPermissions() {
+ checkUserHasAllPermissions("admin");
+ }
+
+ public void checkUserHasAllPermissions(String user) {
+ setup(configBag);
+ WebEntitlementContext entitlementContext = new WebEntitlementContext(user, "127.0.0.1", URI.create("/X").toString(), "A");
+ Entitlements.setEntitlementContext(entitlementContext);
+ Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.ROOT, null));
+ Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_ENTITY, app));
+ Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ Assert.assertTrue(Entitlements.isEntitled(mgmt.getEntitlementManager(), Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+ // and can invoke methods
+ confirmEffectorEntitlement(true);
+ }
+
+ protected void confirmEffectorEntitlement(boolean shouldSucceed) {
+ try {
+ ((BasicApplication)app).start(ImmutableList.<Location>of());
+ checkNoException(shouldSucceed);
+ } catch (Exception e) {
+ checkNotEntitledException(shouldSucceed, e);
+ }
+ }
+
+ private void checkNoException(boolean shouldBeEntitled) {
+ checkNotEntitledException(shouldBeEntitled, null);
+ }
+
+ private void checkNotEntitledException(boolean shouldBeEntitled, Exception e) {
+ if (e==null) {
+ if (shouldBeEntitled) return;
+ Assert.fail("entitlement should have been denied");
+ }
+
+ Exception notEntitled = Exceptions.getFirstThrowableOfType(e, NotEntitledException.class);
+ if (notEntitled==null)
+ throw Exceptions.propagate(e);
+ if (!shouldBeEntitled) {
+ /* denied, as it should have been */
+ return;
+ }
+ Assert.fail("entitlement should have been granted, but was denied: "+e);
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntitlementsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntitlementsTest.java b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntitlementsTest.java
new file mode 100644
index 0000000..aac83f6
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntitlementsTest.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.BasicApplication;
+import brooklyn.entity.basic.Entities;
+
+@Test
+public class EntitlementsTest {
+
+ private ManagementContext mgmt;
+ private Application app;
+
+ @BeforeMethod
+ public void setup() {
+ mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newEmpty());
+ app = ApplicationBuilder.newManagedApp(EntitySpec.create(BasicApplication.class), mgmt);
+ }
+
+ @AfterMethod
+ public void tearDown() {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ app = null;
+ mgmt = null;
+ }
+
+ // allowing
+ public void testAllowingRoot() {
+ EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.ROOT);
+ assertTrue(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+ public void testAllowingSeeEntity() {
+ EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_ENTITY);
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
+ assertTrue(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+ public void testAllowingInvokeEffector() {
+ EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.INVOKE_EFFECTOR);
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertTrue(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+ public void testAllowingSeeSensor() {
+ EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_SENSOR);
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertTrue(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+ public void testAllowingDeployApplication() {
+ EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.DEPLOY_APPLICATION);
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertTrue(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+ public void testAllowingSeeAllServerInfo() {
+ EntitlementManager allowSeeEntity = Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_ALL_SERVER_INFO);
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.ROOT, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(allowSeeEntity.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertTrue(allowSeeEntity.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+
+ // nonSecret
+ public void testSeeNonSecretSensors() {
+ EntitlementManager seeNonSecretSensors = Entitlements.FineGrainedEntitlements.seeNonSecretSensors();
+ assertFalse(seeNonSecretSensors.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "password")));
+ assertTrue(seeNonSecretSensors.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "any-sensor")));
+ }
+
+ // allOf
+ public void testAllOfWithSeeEntityAndSeeSensors() {
+ EntitlementManager allOf = Entitlements.FineGrainedEntitlements.allOf(
+ Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_ENTITY),
+ Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_SENSOR));
+ assertFalse(allOf.isEntitled(null, Entitlements.ROOT, null));
+ assertTrue(allOf.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(allOf.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertTrue(allOf.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(allOf.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(allOf.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+
+ // anyOf
+ public void testAnyOfWithSeeEntityAndSeeSensors() {
+ EntitlementManager anyOf = Entitlements.FineGrainedEntitlements.anyOf(
+ Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_ENTITY),
+ Entitlements.FineGrainedEntitlements.allowing(Entitlements.SEE_SENSOR));
+ assertFalse(anyOf.isEntitled(null, Entitlements.ROOT, null));
+ assertTrue(anyOf.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(anyOf.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertTrue(anyOf.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(anyOf.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(anyOf.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+
+ // root
+ public void testGlobalRootEntitlement() {
+ EntitlementManager root = Entitlements.root();
+ assertTrue(root.isEntitled(null, Entitlements.ROOT, null));
+ assertTrue(root.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertTrue(root.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertTrue(root.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertTrue(root.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertTrue(root.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+ public void testAppSpecificRootEntitlement() {
+ EntitlementManager root = Entitlements.root();
+ assertTrue(root.isEntitled(null, Entitlements.SEE_ENTITY, app));
+ assertTrue(root.isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ assertTrue(root.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "any-sensor")));
+ assertTrue(root.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "password")));
+ assertTrue(root.isEntitled(null, Entitlements.DEPLOY_APPLICATION, Entitlements.EntityAndItem.of(app, null)));
+ assertTrue(root.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+
+ // minimal
+ public void testGlobalMinimalEntitlement() {
+ EntitlementManager minimal = Entitlements.minimal();
+ assertFalse(minimal.isEntitled(null, Entitlements.ROOT, null));
+ assertFalse(minimal.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(minimal.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertFalse(minimal.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(minimal.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(minimal.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+ public void testAppSpecificMinimalEntitlement() {
+ EntitlementManager minimal = Entitlements.minimal();
+ assertFalse(minimal.isEntitled(null, Entitlements.SEE_ENTITY, app));
+ assertFalse(minimal.isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ assertFalse(minimal.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "any-sensor")));
+ assertFalse(minimal.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "password")));
+ assertFalse(minimal.isEntitled(null, Entitlements.DEPLOY_APPLICATION, Entitlements.EntityAndItem.of(app, null)));
+ assertFalse(minimal.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+
+ // readOnly
+ public void testGlobalReadOnlyEntitlement() {
+ EntitlementManager readOnly = Entitlements.readOnly();
+ assertFalse(readOnly.isEntitled(null, Entitlements.ROOT, null));
+ assertTrue(readOnly.isEntitled(null, Entitlements.SEE_ENTITY, null));
+ assertFalse(readOnly.isEntitled(null, Entitlements.INVOKE_EFFECTOR, null));
+ assertFalse(readOnly.isEntitled(null, Entitlements.SEE_SENSOR, null));
+ assertFalse(readOnly.isEntitled(null, Entitlements.DEPLOY_APPLICATION, null));
+ assertFalse(readOnly.isEntitled(null, Entitlements.SEE_ALL_SERVER_INFO, null));
+ }
+ public void testAppSpecificReadOnlyEntitlement() {
+ EntitlementManager readOnly = Entitlements.readOnly();
+ assertTrue(readOnly.isEntitled(null, Entitlements.SEE_ENTITY, app));
+ assertFalse(readOnly.isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ assertTrue(readOnly.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "any-sensor")));
+ assertFalse(readOnly.isEntitled(null, Entitlements.SEE_SENSOR, Entitlements.EntityAndItem.of(app, "password")));
+ assertFalse(readOnly.isEntitled(null, Entitlements.DEPLOY_APPLICATION, Entitlements.EntityAndItem.of(app, null)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java
new file mode 100644
index 0000000..bb25740
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/EntityEntitlementTest.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.entitlement.NotEntitledException;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.EntityAndItem;
+import org.apache.brooklyn.core.management.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.test.entity.LocalManagementContextForTests;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.BasicApplication;
+import brooklyn.entity.basic.Entities;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
+
+public class EntityEntitlementTest {
+
+ private static final Logger log = LoggerFactory.getLogger(EntityEntitlementTest.class);
+
+ ManagementContext mgmt;
+ Application app;
+
+ public void setup(ConfigBag cfg) {
+ mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newEmpty().addFrom(cfg));
+ app = ApplicationBuilder.newManagedApp(EntitySpec.create(BasicApplication.class), mgmt);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() {
+ if (app != null) Entities.destroyAll(app.getManagementContext());
+ if (mgmt != null) Entities.destroyAll(mgmt);
+ app = null;
+ mgmt = null;
+ }
+
+ @Test
+ public void testDefaultRootAllows() {
+ setup(ConfigBag.newInstance());
+ // default "root" access allows ROOT permission, and invoke effector, etc
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.ROOT, null));
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+ // and can invoke methods, without any user/login registered
+ confirmEffectorEntitlement(true);
+ confirmSensorEntitlement(true);
+ }
+
+ @Test
+ public void testExplicitRootAllows() {
+ setup(ConfigBag.newInstance().configure(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, "root"));
+
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.ROOT, null));
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+
+ confirmEffectorEntitlement(true);
+ confirmSensorEntitlement(true);
+ }
+
+ @Test
+ public void testReadOnlyThrowsNotEntitled() {
+ try {
+ setup(ConfigBag.newInstance().configure(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, "readonly"));
+ // eventually above call will fail in app creation, but for now the call below falls
+ ((BasicApplication)app).start(ImmutableList.<Location>of());
+ tearDown();
+
+ Assert.fail("something should have been disallowed");
+ } catch (Exception e) {
+ checkNotEntitledException(e);
+ } finally {
+ app = null;
+ if (mgmt!=null) ((LocalManagementContext)mgmt).terminate();
+ mgmt = null;
+ }
+ }
+
+ @Test(enabled=false)
+ // this test (and minimal below) currently work fine until tearDown,
+ // but then of course they don't have entitlement to call 'stop';
+ // (as more entitlement checks are added app creation will fail).
+ //
+ // TODO these tests should set up a user with the permission,
+ // e.g. so system has root, but 'bob' has read-only, then we can test read-only;
+ // TODO rest api tests, as some of the permissions will only be enforced at REST level
+ public void testReadOnlyAllowsSome() {
+ setup(ConfigBag.newInstance().configure(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, "readonly"));
+
+ Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.ROOT, null));
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
+ Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ Assert.assertTrue(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+
+ confirmEffectorEntitlement(false);
+ confirmSensorEntitlement(true);
+ }
+
+ @Test(enabled=false)
+ public void testMinimalDisallows() {
+ setup(ConfigBag.newInstance().configure(Entitlements.GLOBAL_ENTITLEMENT_MANAGER, "minimal"));
+
+ Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.ROOT, null));
+ Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_ENTITY, app));
+ Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of("any-eff", null))));
+ Assert.assertFalse(mgmt.getEntitlementManager().isEntitled(null, Entitlements.SEE_SENSOR, EntityAndItem.of(app, "any-sensor")));
+
+ confirmEffectorEntitlement(false);
+ confirmSensorEntitlement(false);
+ }
+
+ protected void confirmSensorEntitlement(boolean shouldSucceed) {
+ // TODO... based on above
+ // (though maybe we should test against REST API classes rather than lower level programmatic?
+ // TBC...)
+ log.warn("confirmSensorEntitlement still required!");
+ }
+
+ // TODO specific users tests
+
+ protected void confirmEffectorEntitlement(boolean shouldSucceed) {
+ try {
+ ((BasicApplication)app).start(ImmutableList.<Location>of());
+ checkNoException(shouldSucceed);
+ } catch (Exception e) {
+ checkNotEntitledException(shouldSucceed, e);
+ }
+ }
+
+ private void checkNoException(boolean shouldBeEntitled) {
+ checkNotEntitledException(shouldBeEntitled, null);
+ }
+
+ private void checkNotEntitledException(Exception e) {
+ checkNotEntitledException(false, e);
+ }
+
+ private void checkNotEntitledException(boolean shouldBeEntitled, Exception e) {
+ if (e==null) {
+ if (shouldBeEntitled) return;
+ Assert.fail("entitlement should have been denied");
+ }
+
+ Exception notEntitled = Exceptions.getFirstThrowableOfType(e, NotEntitledException.class);
+ if (notEntitled==null)
+ throw Exceptions.propagate(e);
+ if (!shouldBeEntitled) {
+ /* denied, as it should have been */
+ return;
+ }
+ Assert.fail("entitlement should have been granted, but was denied: "+e);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManagerPropertiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManagerPropertiesTest.java b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManagerPropertiesTest.java
new file mode 100644
index 0000000..f420019
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/entitlement/PerUserEntitlementManagerPropertiesTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.entitlement;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Properties;
+
+import org.testng.annotations.Test;
+
+
+public class PerUserEntitlementManagerPropertiesTest extends AcmeEntitlementManagerTestFixture {
+
+ protected void addGlobalConfig() throws IOException {
+ Properties moreProps = new Properties();
+ moreProps.load(new StringReader(
+ "brooklyn.entitlements.global=org.apache.brooklyn.core.management.entitlement.PerUserEntitlementManager\n"
+ + "brooklyn.entitlements.perUser.admin=root\n"
+ + "brooklyn.entitlements.perUser.support=readonly\n"
+ + "brooklyn.entitlements.perUser.metrics=minimal"));
+ configBag.putAll(moreProps);
+ }
+
+ @Test
+ public void testOtherAuthorizedUserHasMinimalPermissions() {
+ checkUserHasMinimalPermissions("other");
+ }
+
+ @Test
+ public void testNullUserHasAllPermissions() {
+ checkUserHasAllPermissions(null);
+ }
+
+
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerFileBasedTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerFileBasedTest.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerFileBasedTest.java
new file mode 100644
index 0000000..99640b7
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerFileBasedTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import java.io.File;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.rebind.persister.FileBasedObjectStore;
+import brooklyn.util.os.Os;
+
+@Test
+public class HighAvailabilityManagerFileBasedTest extends HighAvailabilityManagerTestFixture {
+
+ private File dir;
+
+ protected FileBasedObjectStore newPersistenceObjectStore() {
+ if (dir!=null)
+ throw new IllegalStateException("Test does not support multiple object stores");
+ dir = Os.newTempDir(getClass());
+ return new FileBasedObjectStore(dir);
+ }
+
+ @Override
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ super.tearDown();
+ dir = Os.deleteRecursively(dir).asNullOrThrowing();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerInMemoryIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerInMemoryIntegrationTest.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerInMemoryIntegrationTest.java
new file mode 100644
index 0000000..4b5a5cf
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerInMemoryIntegrationTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.rebind.persister.InMemoryObjectStore;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+
+import com.google.common.base.Ticker;
+
+@Test(groups="Integration")
+public class HighAvailabilityManagerInMemoryIntegrationTest extends HighAvailabilityManagerTestFixture {
+
+ private static final Logger log = LoggerFactory.getLogger(HighAvailabilityManagerInMemoryIntegrationTest.class);
+
+ @Override
+ protected PersistenceObjectStore newPersistenceObjectStore() {
+ return new InMemoryObjectStore();
+ }
+
+ @Override
+ protected Duration getPollPeriod() {
+ return Duration.millis(100);
+ }
+
+ @Override
+ protected long tickerAdvance(Duration duration) {
+ log.info("sleeping for "+duration);
+ // actually sleep, in order to advance the local time ticker
+ Time.sleep(duration);
+ return super.tickerAdvance(duration);
+ }
+
+ @Override
+ protected Ticker getRemoteTicker() {
+ // use real times
+ return null;
+ }
+
+ @Override
+ @Test(groups="Integration", enabled=false, invocationCount=50)
+ public void testGetManagementPlaneStatusManyTimes() throws Exception {
+ }
+
+ @Test(groups="Integration")
+ @Override
+ public void testGetManagementPlaneStatus() throws Exception {
+ super.testGetManagementPlaneStatus();
+ }
+
+ @Test(groups="Integration")
+ @Override
+ public void testDoesNotPromoteIfMasterTimeoutNotExpired() throws Exception {
+ super.testDoesNotPromoteIfMasterTimeoutNotExpired();
+ }
+
+ @Test(groups="Integration")
+ @Override
+ public void testGetManagementPlaneSyncStateDoesNotThrowNpeBeforePersisterSet() throws Exception {
+ super.testGetManagementPlaneSyncStateDoesNotThrowNpeBeforePersisterSet();
+ }
+
+ @Test(groups="Integration")
+ @Override
+ public void testGetManagementPlaneSyncStateInfersTimedOutNodeAsFailed() throws Exception {
+ super.testGetManagementPlaneSyncStateInfersTimedOutNodeAsFailed();
+ }
+
+ @Test(groups="Integration")
+ @Override
+ public void testPromotes() throws Exception {
+ super.testPromotes();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerInMemoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerInMemoryTest.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerInMemoryTest.java
new file mode 100644
index 0000000..6ae9dfb
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerInMemoryTest.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.NoMachinesAvailableException;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+import org.apache.brooklyn.core.management.internal.LocalManagementContext;
+import org.apache.brooklyn.test.entity.TestApplication;
+import org.apache.brooklyn.test.entity.TestEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.rebind.persister.InMemoryObjectStore;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+
+import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.location.basic.SshMachineLocation;
+
+import brooklyn.util.collections.MutableList;
+
+import com.google.common.collect.Iterables;
+
+@Test
+public class HighAvailabilityManagerInMemoryTest extends HighAvailabilityManagerTestFixture {
+
+ private static final Logger log = LoggerFactory.getLogger(HighAvailabilityManagerInMemoryTest.class);
+
+ protected PersistenceObjectStore newPersistenceObjectStore() {
+ return new InMemoryObjectStore();
+ }
+
+ public void testGetManagementPlaneStatus() throws Exception {
+ super.testGetManagementPlaneStatus();
+ }
+
+ // extra test that promoteToMaster doesn't interfere with what is managed
+ public void testLocationsStillManagedCorrectlyAfterDoublePromotion() throws NoMachinesAvailableException {
+ HighAvailabilityManagerImpl ha = (HighAvailabilityManagerImpl) managementContext.getHighAvailabilityManager();
+ ha.start(HighAvailabilityMode.MASTER);
+
+ TestApplication app = TestApplication.Factory.newManagedInstanceForTests(managementContext);
+
+ LocalhostMachineProvisioningLocation l = app.newLocalhostProvisioningLocation();
+ l.setConfig(TestEntity.CONF_NAME, "sample1");
+ Assert.assertEquals(l.getConfig(TestEntity.CONF_NAME), "sample1");
+
+ SshMachineLocation l2 = l.obtain();
+ Assert.assertEquals(l2.getConfig(TestEntity.CONF_NAME), "sample1");
+ Assert.assertNotNull(l2.getParent(), "Parent not set after dodgy promoteToMaster");
+ Assert.assertEquals(l2.getParent().getConfig(TestEntity.CONF_NAME), "sample1");
+
+ TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class).location(l).location(l2));
+ log.info("Entities managed are: "+managementContext.getEntityManager().getEntities());
+ Collection<Location> le = entity.getLocations();
+ log.info("Locs at entity are: "+le);
+ Collection<Location> lm = managementContext.getLocationManager().getLocations();
+ log.info("Locs managed are: "+lm);
+ log.info(" objs: "+identities(lm));
+ Assert.assertNotNull(entity.getManagementSupport().getManagementContext());
+ Assert.assertNotNull( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext());
+ Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().isDeployed());
+ checkEntitiesHealthy(app, entity);
+
+ managementContext.getRebindManager().forcePersistNow(true, null);
+ log.info("Test deliberately doing unnecessary extra promoteToMaster");
+ ha.promoteToMaster();
+
+ log.info("Entities managed are: "+managementContext.getEntityManager().getEntities());
+ Collection<Location> lle = entity.getLocations();
+ log.info("Locs at entity(old) are: "+lle);
+ log.info(" objs: "+identities(lle));
+ // check entities -- the initial-full promotion previously re-created items,
+ // and plugged them in as children, but only managed the roots
+ checkEntitiesHealthy(app, entity);
+
+ // assert what's in the location manager is accurate
+ Collection<Location> llmm = managementContext.getLocationManager().getLocations();
+ log.info("Locs managed are: "+llmm);
+ log.info(" objs: "+identities(llmm));
+ Assert.assertEquals(llmm, lm);
+ SshMachineLocation ll2a = Iterables.getOnlyElement(Iterables.filter(llmm, SshMachineLocation.class));
+ Assert.assertEquals(ll2a.getConfig(TestEntity.CONF_NAME), "sample1");
+ Assert.assertNotNull(ll2a.getParent(), "Parent not set after dodgy promoteToMaster");
+ Assert.assertEquals(ll2a.getParent().getConfig(TestEntity.CONF_NAME), "sample1");
+
+ // and what's in the location manager is accurate
+ Entity ee = (Entity)managementContext.lookup(entity.getId());
+ Collection<Location> llee = ee.getLocations();
+ log.info("Locs at entity(lookup) are: "+llee);
+ log.info(" objs: "+identities(llee));
+ SshMachineLocation ll2b = Iterables.getOnlyElement(Iterables.filter(llee, SshMachineLocation.class));
+ Assert.assertEquals(ll2b.getConfig(TestEntity.CONF_NAME), "sample1");
+ Assert.assertNotNull(ll2b.getParent(), "Parent not set after dodgy promoteToMaster");
+ Assert.assertEquals(ll2b.getParent().getConfig(TestEntity.CONF_NAME), "sample1");
+ }
+
+ private void checkEntitiesHealthy(TestApplication app, TestEntity entity) {
+ Assert.assertNotNull(app.getManagementSupport().getManagementContext());
+ Assert.assertTrue( app.getManagementSupport().getManagementContext().isRunning() );
+
+ Assert.assertNotNull(entity.getManagementSupport().getManagementContext());
+ Assert.assertNotNull( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext() );
+ Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().isDeployed());
+ Assert.assertTrue( ((EntityInternal)app.getChildren().iterator().next()).getManagementSupport().getManagementContext() instanceof LocalManagementContext );
+ }
+
+ @Test(groups="Integration", invocationCount=50)
+ public void testLocationsStillManagedCorrectlyAfterDoublePromotionManyTimes() throws NoMachinesAvailableException {
+ testLocationsStillManagedCorrectlyAfterDoublePromotion();
+ }
+
+ private List<String> identities(Collection<?> objs) {
+ List<String> result = MutableList.of();
+ for (Object obj: objs)
+ result.add(Integer.toHexString(System.identityHashCode(obj)));
+ return result;
+ }
+
+}
[20/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
deleted file mode 100644
index 2af7e77..0000000
--- a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import org.apache.brooklyn.api.basic.BrooklynObject;
-
-public interface BrooklynObjectManagerInternal<T extends BrooklynObject> {
-
- ManagementTransitionMode getLastManagementTransitionMode(String itemId);
- void setManagementTransitionMode(T item, ManagementTransitionMode mode);
-
- /**
- * Begins management for the given rebinded root, recursively;
- * if rebinding as a read-only copy, {@link #setReadOnly(T, boolean)} should be called prior to this.
- */
- void manageRebindedRoot(T item);
-
- void unmanage(final T e, final ManagementTransitionMode info);
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java b/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java
deleted file mode 100644
index 654debc..0000000
--- a/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-public interface CollectionChangeListener<Item> {
- void onItemAdded(Item item);
- void onItemRemoved(Item item);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EffectorUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/EffectorUtils.java b/core/src/main/java/brooklyn/management/internal/EffectorUtils.java
deleted file mode 100644
index fe38cb6..0000000
--- a/core/src/main/java/brooklyn/management/internal/EffectorUtils.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static brooklyn.util.GroovyJavaMethods.truth;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.Effector;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.ParameterType;
-import org.apache.brooklyn.api.management.Task;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.basic.BasicParameterType;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.PropagatedRuntimeException;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.guava.Maybe;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-/**
- * Utility methods for invoking effectors.
- */
-public class EffectorUtils {
-
- private static final Logger log = LoggerFactory.getLogger(EffectorUtils.class);
-
- /** prepares arguments for an effector either accepting:
- * an array, which should contain the arguments in order, optionally omitting those which have defaults defined;
- * or a map, which should contain the arguments by name, again optionally omitting those which have defaults defined,
- * and in this case also performing type coercion.
- */
- public static Object[] prepareArgsForEffector(Effector<?> eff, Object args) {
- if (args != null && args.getClass().isArray()) {
- return prepareArgsForEffectorFromArray(eff, (Object[]) args);
- }
- if (args instanceof Map) {
- return prepareArgsForEffectorFromMap(eff, (Map) args);
- }
- log.warn("Deprecated effector invocation style for call to "+eff+", expecting a map or an array, got: "+args);
- if (log.isDebugEnabled()) {
- log.debug("Deprecated effector invocation style for call to "+eff+", expecting a map or an array, got: "+args,
- new Throwable("Trace for deprecated effector invocation style"));
- }
- return oldPrepareArgsForEffector(eff, args);
- }
-
- /** method used for calls such as entity.effector(arg1, arg2)
- * get routed here from AbstractEntity.invokeMethod */
- private static Object[] prepareArgsForEffectorFromArray(Effector<?> eff, Object args[]) {
- int newArgsNeeded = eff.getParameters().size();
- if (args.length==1 && args[0] instanceof Map) {
- if (newArgsNeeded!=1 || !eff.getParameters().get(0).getParameterClass().isAssignableFrom(args[0].getClass())) {
- // treat a map in an array as a map passed directly (unless the method takes a single-arg map)
- // this is to support effector(param1: val1)
- return prepareArgsForEffectorFromMap(eff, (Map) args[0]);
- }
- }
- return prepareArgsForEffectorAsMapFromArray(eff, args).values().toArray(new Object[0]);
- }
-
- public static Map prepareArgsForEffectorAsMapFromArray(Effector<?> eff, Object args[]) {
- int newArgsNeeded = eff.getParameters().size();
- List l = Lists.newArrayList();
- l.addAll(Arrays.asList(args));
- Map newArgs = new LinkedHashMap();
-
- for (int index = 0; index < eff.getParameters().size(); index++) {
- ParameterType<?> it = eff.getParameters().get(index);
-
- if (l.size() >= newArgsNeeded) {
- //all supplied (unnamed) arguments must be used; ignore map
- newArgs.put(it.getName(), l.remove(0));
- // TODO do we ignore arguments in the same order that groovy does?
- } else if (!l.isEmpty() && it.getParameterClass().isInstance(l.get(0))) {
- //if there are parameters supplied, and type is correct, they get applied before default values
- //(this is akin to groovy)
- newArgs.put(it.getName(), l.remove(0));
- } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) {
- //finally, default values are used to make up for missing parameters
- newArgs.put(it.getName(), ((BasicParameterType)it).getDefaultValue());
- } else {
- throw new IllegalArgumentException("Invalid arguments (count mismatch) for effector "+eff+": "+args);
- }
-
- newArgsNeeded--;
- }
- if (newArgsNeeded > 0) {
- throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+args);
- }
- if (!l.isEmpty()) {
- throw new IllegalArgumentException("Invalid arguments ("+l.size()+" extra) for effector "+eff+": "+args);
- }
- return newArgs;
- }
-
- private static Object[] prepareArgsForEffectorFromMap(Effector<?> eff, Map m) {
- m = Maps.newLinkedHashMap(m); //make editable copy
- List newArgs = Lists.newArrayList();
- int newArgsNeeded = eff.getParameters().size();
-
- for (int index = 0; index < eff.getParameters().size(); index++) {
- ParameterType<?> it = eff.getParameters().get(index);
- Object v;
- if (truth(it.getName()) && m.containsKey(it.getName())) {
- // argument is in the map
- v = m.remove(it.getName());
- } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) {
- //finally, default values are used to make up for missing parameters
- v = ((BasicParameterType)it).getDefaultValue();
- } else {
- throw new IllegalArgumentException("Invalid arguments (missing argument "+it+") for effector "+eff+": "+m);
- }
-
- newArgs.add(TypeCoercions.coerce(v, it.getParameterClass()));
- newArgsNeeded--;
- }
- if (newArgsNeeded>0)
- throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+m);
- return newArgs.toArray(new Object[newArgs.size()]);
- }
-
- /**
- * Takes arguments, and returns an array of arguments suitable for use by the Effector
- * according to the ParameterTypes it exposes.
- * <p>
- * The args can be:
- * <ol>
- * <li>an array of ordered arguments
- * <li>a collection (which will be automatically converted to an array)
- * <li>a single argument (which will then be wrapped in an array)
- * <li>a map containing the (named) arguments
- * <li>an array or collection single entry of a map (treated same as 5 above)
- * <li>a semi-populated array or collection that also containing a map as first arg -
- * uses ordered args in array, but uses named values from map in preference.
- * <li>semi-populated array or collection, where default values will otherwise be used.
- * </ol>
- */
- public static Object[] oldPrepareArgsForEffector(Effector<?> eff, Object args) {
- //attempt to coerce unexpected types
- Object[] argsArray;
- if (args==null) {
- argsArray = new Object[0];
- } else if (args.getClass().isArray()) {
- argsArray = (Object[]) args;
- } else {
- if (args instanceof Collection) {
- argsArray = ((Collection) args).toArray(new Object[((Collection) args).size()]);
- } else {
- argsArray = new Object[] { args };
- }
- }
-
- //if args starts with a map, assume it contains the named arguments
- //(but only use it when we have insufficient supplied arguments)
- List l = Lists.newArrayList();
- l.addAll(Arrays.asList(argsArray));
- Map m = (argsArray.length > 0 && argsArray[0] instanceof Map ? Maps.newLinkedHashMap((Map) l.remove(0)) : null);
- List newArgs = Lists.newArrayList();
- int newArgsNeeded = eff.getParameters().size();
- boolean mapUsed = false;
-
- for (int index = 0; index < eff.getParameters().size(); index++) {
- ParameterType<?> it = eff.getParameters().get(index);
-
- if (l.size() >= newArgsNeeded) {
- //all supplied (unnamed) arguments must be used; ignore map
- newArgs.add(l.remove(0));
- } else if (truth(m) && truth(it.getName()) && m.containsKey(it.getName())) {
- //some arguments were not supplied, and this one is in the map
- newArgs.add(m.remove(it.getName()));
- } else if (index == 0 && Map.class.isAssignableFrom(it.getParameterClass())) {
- //if first arg is a map it takes the supplied map
- newArgs.add(m);
- mapUsed = true;
- } else if (!l.isEmpty() && it.getParameterClass().isInstance(l.get(0))) {
- //if there are parameters supplied, and type is correct, they get applied before default values
- //(this is akin to groovy)
- newArgs.add(l.remove(0));
- } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) {
- //finally, default values are used to make up for missing parameters
- newArgs.add(((BasicParameterType)it).getDefaultValue());
- } else {
- throw new IllegalArgumentException("Invalid arguments (count mismatch) for effector "+eff+": "+args);
- }
-
- newArgsNeeded--;
- }
- if (newArgsNeeded > 0) {
- throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+args);
- }
- if (!l.isEmpty()) {
- throw new IllegalArgumentException("Invalid arguments ("+l.size()+" extra) for effector "+eff+": "+args);
- }
- if (truth(m) && !mapUsed) {
- throw new IllegalArgumentException("Invalid arguments ("+m.size()+" extra named) for effector "+eff+": "+args);
- }
- return newArgs.toArray(new Object[newArgs.size()]);
- }
-
- /**
- * Invokes a method effector so that its progress is tracked. For internal use only, when we know the effector is backed by a method which is local.
- */
- public static <T> T invokeMethodEffector(Entity entity, Effector<T> eff, Object[] args) {
- String name = eff.getName();
-
- try {
- if (log.isDebugEnabled()) log.debug("Invoking effector {} on {}", new Object[] {name, entity});
- if (log.isTraceEnabled()) log.trace("Invoking effector {} on {} with args {}", new Object[] {name, entity, args});
- EntityManagementSupport mgmtSupport = ((EntityInternal)entity).getManagementSupport();
- if (!mgmtSupport.isDeployed()) {
- mgmtSupport.attemptLegacyAutodeployment(name);
- }
- ManagementContextInternal mgmtContext = (ManagementContextInternal) ((EntityInternal) entity).getManagementContext();
-
- mgmtSupport.getEntityChangeListener().onEffectorStarting(eff, args);
- try {
- return mgmtContext.invokeEffectorMethodSync(entity, eff, args);
- } finally {
- mgmtSupport.getEntityChangeListener().onEffectorCompleted(eff);
- }
- } catch (Exception e) {
- handleEffectorException(entity, eff, e);
- // (won't return below)
- return null;
- }
- }
-
- public static void handleEffectorException(Entity entity, Effector<?> effector, Throwable throwable) {
- String message = "Error invoking " + effector.getName() + " at " + entity;
- // Avoid throwing a PropagatedRuntimeException that just repeats the last PropagatedRuntimeException.
- if (throwable instanceof PropagatedRuntimeException &&
- throwable.getMessage() != null &&
- throwable.getMessage().startsWith(message)) {
- throw PropagatedRuntimeException.class.cast(throwable);
- } else {
- log.warn(message + ": " + Exceptions.collapseText(throwable));
- throw new PropagatedRuntimeException(message, throwable);
- }
- }
-
- public static <T> Task<T> invokeEffectorAsync(Entity entity, Effector<T> eff, Map<String,?> parameters) {
- String name = eff.getName();
-
- if (log.isDebugEnabled()) log.debug("Invoking-async effector {} on {}", new Object[] { name, entity });
- if (log.isTraceEnabled()) log.trace("Invoking-async effector {} on {} with args {}", new Object[] { name, entity, parameters });
- EntityManagementSupport mgmtSupport = ((EntityInternal)entity).getManagementSupport();
- if (!mgmtSupport.isDeployed()) {
- mgmtSupport.attemptLegacyAutodeployment(name);
- }
- ManagementContextInternal mgmtContext = (ManagementContextInternal) ((EntityInternal)entity).getManagementContext();
-
- // FIXME seems brittle to have the listeners in the Utils method; better to move into the context.invokeEff
- // (or whatever the last mile before invoking the effector is - though currently there is not such a canonical place!)
- mgmtSupport.getEntityChangeListener().onEffectorStarting(eff, parameters);
- try {
- return mgmtContext.invokeEffector(entity, eff, parameters);
- } finally {
- // FIXME this is really Effector submitted
- mgmtSupport.getEntityChangeListener().onEffectorCompleted(eff);
- }
- }
-
- /** @deprecated since 0.7.0, not used */
- @Deprecated
- public static Effector<?> findEffectorMatching(Entity entity, Method method) {
- outer: for (Effector<?> effector : entity.getEntityType().getEffectors()) {
- if (!effector.getName().equals(entity)) continue;
- if (effector.getParameters().size() != method.getParameterTypes().length) continue;
- for (int i = 0; i < effector.getParameters().size(); i++) {
- if (effector.getParameters().get(i).getParameterClass() != method.getParameterTypes()[i]) continue outer;
- }
- return effector;
- }
- return null;
- }
-
- /** @deprecated since 0.7.0, expects parameters but does not use them! */
- @Deprecated
- public static Effector<?> findEffectorMatching(Set<Effector<?>> effectors, String effectorName, Map<String, ?> parameters) {
- // TODO Support overloading: check parameters as well
- for (Effector<?> effector : effectors) {
- if (effector.getName().equals(effectorName)) {
- return effector;
- }
- }
- return null;
- }
-
- /** matches effectors by name only (not parameters) */
- public static Maybe<Effector<?>> findEffector(Collection<? extends Effector<?>> effectors, String effectorName) {
- for (Effector<?> effector : effectors) {
- if (effector.getName().equals(effectorName)) {
- return Maybe.<Effector<?>>of(effector);
- }
- }
- return Maybe.absent(new NoSuchElementException("No effector with name "+effectorName+" (contenders "+effectors+")"));
- }
-
- /** matches effectors by name only (not parameters), based on what is declared on the entity static type */
- public static Maybe<Effector<?>> findEffectorDeclared(Entity entity, String effectorName) {
- return findEffector(entity.getEntityType().getEffectors(), effectorName);
- }
-
- /** @deprecated since 0.7.0 use {@link #getTaskFlagsForEffectorInvocation(Entity, Effector, ConfigBag)} */
- public static Map<Object,Object> getTaskFlagsForEffectorInvocation(Entity entity, Effector<?> effector) {
- return getTaskFlagsForEffectorInvocation(entity, effector, null);
- }
-
- /** returns a (mutable) map of the standard flags which should be placed on an effector */
- public static Map<Object,Object> getTaskFlagsForEffectorInvocation(Entity entity, Effector<?> effector, ConfigBag parameters) {
- return MutableMap.builder()
- .put("description", "Invoking effector "+effector.getName()
- +" on "+entity.getDisplayName()
- +(parameters!=null ? " with parameters "+parameters.getAllConfig() : ""))
- .put("displayName", effector.getName())
- .put("tags", MutableList.of(
- BrooklynTaskTags.EFFECTOR_TAG,
- BrooklynTaskTags.tagForEffectorCall(entity, effector.getName(), parameters),
- BrooklynTaskTags.tagForTargetEntity(entity)))
- .build();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EntityChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/EntityChangeListener.java b/core/src/main/java/brooklyn/management/internal/EntityChangeListener.java
deleted file mode 100644
index 1b67d2d..0000000
--- a/core/src/main/java/brooklyn/management/internal/EntityChangeListener.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import org.apache.brooklyn.api.entity.Effector;
-import org.apache.brooklyn.api.entity.Feed;
-import org.apache.brooklyn.api.event.AttributeSensor;
-import org.apache.brooklyn.api.policy.Enricher;
-import org.apache.brooklyn.api.policy.Policy;
-
-import brooklyn.config.ConfigKey;
-
-public interface EntityChangeListener {
-
- // TODO for testing only!
- public static final EntityChangeListener NOOP = new EntityChangeListener() {
- @Override public void onChanged() {}
- @Override public void onAttributeChanged(AttributeSensor<?> attribute) {}
- @Override public void onConfigChanged(ConfigKey<?> key) {}
- @Override public void onLocationsChanged() {}
- @Override public void onMembersChanged() {}
- @Override public void onTagsChanged() {}
- @Override public void onChildrenChanged() {}
- @Override public void onPolicyAdded(Policy policy) {}
- @Override public void onPolicyRemoved(Policy policy) {}
- @Override public void onEnricherAdded(Enricher enricher) {}
- @Override public void onEnricherRemoved(Enricher enricher) {}
- @Override public void onFeedAdded(Feed feed) {}
- @Override public void onFeedRemoved(Feed feed) {}
- @Override public void onEffectorStarting(Effector<?> effector, Object parameters) {}
- @Override public void onEffectorCompleted(Effector<?> effector) {}
- };
-
- void onChanged();
-
- void onAttributeChanged(AttributeSensor<?> attribute);
-
- void onConfigChanged(ConfigKey<?> key);
-
- void onLocationsChanged();
-
- void onTagsChanged();
-
- void onMembersChanged();
-
- void onChildrenChanged();
-
- void onPolicyAdded(Policy policy);
-
- void onPolicyRemoved(Policy policy);
-
- void onEnricherAdded(Enricher enricher);
-
- void onEnricherRemoved(Enricher enricher);
-
- void onFeedAdded(Feed feed);
-
- void onFeedRemoved(Feed feed);
-
- void onEffectorStarting(Effector<?> effector, Object parameters);
-
- void onEffectorCompleted(Effector<?> effector);
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java b/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
deleted file mode 100644
index 596c8b2..0000000
--- a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Effector;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.Feed;
-import org.apache.brooklyn.api.event.AttributeSensor;
-import org.apache.brooklyn.api.management.ExecutionContext;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.SubscriptionContext;
-import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
-import org.apache.brooklyn.api.policy.Enricher;
-import org.apache.brooklyn.api.policy.Policy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.management.entitlement.Entitlements;
-import brooklyn.management.entitlement.Entitlements.EntityAndItem;
-import brooklyn.management.entitlement.Entitlements.StringAndArgument;
-import brooklyn.management.internal.NonDeploymentManagementContext.NonDeploymentManagementContextMode;
-import brooklyn.util.exceptions.Exceptions;
-
-import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-
-/**
- * Encapsulates management activities at an entity.
- * <p>
- * On entity deployment, ManagementContext.manage(entity) causes
- * <p>
- * * onManagementStarting(ManagementContext)
- * * onManagementStartingSubscriptions()
- * * onManagementStartingSensorEmissions()
- * * onManagementStartingExecutions()
- * * onManagementStarted() - when all the above is said and done
- * * onManagementStartingHere();
- * <p>
- * on unmanage it hits onManagementStoppingHere() then onManagementStopping().
- * <p>
- * When an entity's management migrates, it invoked onManagementStoppingHere() at the old location,
- * then onManagementStartingHere() at the new location.
- */
-public class EntityManagementSupport {
-
- private static final Logger log = LoggerFactory.getLogger(EntityManagementSupport.class);
-
- public EntityManagementSupport(AbstractEntity entity) {
- this.entity = entity;
- nonDeploymentManagementContext = new NonDeploymentManagementContext(entity, NonDeploymentManagementContextMode.PRE_MANAGEMENT);
- }
-
- protected transient AbstractEntity entity;
- NonDeploymentManagementContext nonDeploymentManagementContext;
-
- protected transient ManagementContext initialManagementContext;
- protected transient ManagementContext managementContext;
- protected transient SubscriptionContext subscriptionContext;
- protected transient ExecutionContext executionContext;
-
- // TODO the application
- // (elaborate or remove ^^^ ? -AH, Sept 2014)
-
- protected final AtomicBoolean managementContextUsable = new AtomicBoolean(false);
- protected final AtomicBoolean currentlyDeployed = new AtomicBoolean(false);
- protected final AtomicBoolean everDeployed = new AtomicBoolean(false);
- protected Boolean readOnly = null;
- protected final AtomicBoolean managementFailed = new AtomicBoolean(false);
-
- private volatile EntityChangeListener entityChangeListener = EntityChangeListener.NOOP;
-
- /**
- * Whether this entity is managed (i.e. "onManagementStarting" has been called, so the framework knows about it,
- * and it has not been unmanaged).
- */
- public boolean isDeployed() { return currentlyDeployed.get(); }
- public boolean isNoLongerManaged() {
- return wasDeployed() && !isDeployed();
- }
- /** whether entity has ever been deployed (managed) */
- public boolean wasDeployed() { return everDeployed.get(); }
-
- @Beta
- public void setReadOnly(boolean isReadOnly) {
- if (isDeployed())
- throw new IllegalStateException("Cannot set read only after deployment");
- this.readOnly = isReadOnly;
- }
-
- /** Whether the entity and its adjuncts should be treated as read-only;
- * may be null briefly when initializing if RO status is unknown. */
- @Beta
- public Boolean isReadOnlyRaw() {
- return readOnly;
- }
-
- /** Whether the entity and its adjuncts should be treated as read-only;
- * error if initializing and RO status is unknown. */
- @Beta
- public boolean isReadOnly() {
- Preconditions.checkNotNull(readOnly, "Read-only status of %s not yet known", entity);
- return readOnly;
- }
-
- /**
- * Whether the entity's management lifecycle is complete (i.e. both "onManagementStarting" and "onManagementStarted" have
- * been called, and it is has not been unmanaged).
- */
- public boolean isFullyManaged() {
- return (nonDeploymentManagementContext == null) && currentlyDeployed.get();
- }
-
- public synchronized void setManagementContext(ManagementContextInternal val) {
- if (initialManagementContext != null) {
- throw new IllegalStateException("Initial management context is already set for "+entity+"; cannot change");
- }
- if (managementContext != null && !managementContext.equals(val)) {
- throw new IllegalStateException("Management context is already set for "+entity+"; cannot change");
- }
-
- this.initialManagementContext = checkNotNull(val, "managementContext");
- if (nonDeploymentManagementContext != null) {
- nonDeploymentManagementContext.setManagementContext(val);
- }
- }
-
- public void onRebind(ManagementTransitionInfo info) {
- nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_REBINDING);
- }
-
- public void onManagementStarting(ManagementTransitionInfo info) {
- try {
- synchronized (this) {
- boolean alreadyManaging = isDeployed();
-
- if (alreadyManaging) {
- log.warn("Already managed: "+entity+" ("+nonDeploymentManagementContext+"); onManagementStarting is no-op");
- } else if (nonDeploymentManagementContext == null || !nonDeploymentManagementContext.getMode().isPreManaged()) {
- throw new IllegalStateException("Not in expected pre-managed state: "+entity+" ("+nonDeploymentManagementContext+")");
- }
- if (managementContext != null && !managementContext.equals(info.getManagementContext())) {
- throw new IllegalStateException("Already has management context: "+managementContext+"; can't set "+info.getManagementContext());
- }
- if (initialManagementContext != null && !initialManagementContext.equals(info.getManagementContext())) {
- throw new IllegalStateException("Already has different initial management context: "+initialManagementContext+"; can't set "+info.getManagementContext());
- }
- if (alreadyManaging) {
- return;
- }
-
- this.managementContext = info.getManagementContext();
- nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STARTING);
-
- if (!isReadOnly()) {
- nonDeploymentManagementContext.getSubscriptionManager().setDelegate((AbstractSubscriptionManager) managementContext.getSubscriptionManager());
- nonDeploymentManagementContext.getSubscriptionManager().startDelegatingForSubscribing();
- }
-
- managementContextUsable.set(true);
- currentlyDeployed.set(true);
- everDeployed.set(true);
-
- entityChangeListener = new EntityChangeListenerImpl();
- }
-
- /*
- * TODO framework starting events - phase 1, including rebind
- * - establish hierarchy (child, groups, etc; construction if necessary on rebind)
- * - set location
- * - set local config values
- * - set saved sensor values
- * - register subscriptions -- BUT nothing is allowed to execute
- * [these operations may be done before we invoke starting also; above can happen in any order;
- * sensor _publications_ and executor submissions are queued]
- * then: set the management context and the entity is "managed" from the perspective of external viewers (ManagementContext.isManaged(entity) returns true)
- */
-
- if (!isReadOnly()) {
- entity.onManagementStarting();
- }
- } catch (Throwable t) {
- managementFailed.set(true);
- throw Exceptions.propagate(t);
- }
- }
-
- @SuppressWarnings("deprecation")
- public void onManagementStarted(ManagementTransitionInfo info) {
- try {
- synchronized (this) {
- boolean alreadyManaged = isFullyManaged();
-
- if (alreadyManaged) {
- log.warn("Already managed: "+entity+" ("+nonDeploymentManagementContext+"); onManagementStarted is no-op");
- } else if (nonDeploymentManagementContext == null || nonDeploymentManagementContext.getMode() != NonDeploymentManagementContextMode.MANAGEMENT_STARTING) {
- throw new IllegalStateException("Not in expected \"management starting\" state: "+entity+" ("+nonDeploymentManagementContext+")");
- }
- if (managementContext != info.getManagementContext()) {
- throw new IllegalStateException("Already has management context: "+managementContext+"; can't set "+info.getManagementContext());
- }
- if (alreadyManaged) {
- return;
- }
-
- nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STARTED);
-
- /*
- * - set derived/inherited config values
- * - publish all queued sensors
- * - start all queued executions (e.g. subscription delivery)
- * [above happens in exactly this order, at each entity]
- * then: the entity internally knows it fully managed (ManagementSupport.isManaged() returns true -- though not sure we need that);
- * subsequent sensor events and executions occur directly (no queueing)
- */
-
- if (!isReadOnly()) {
- nonDeploymentManagementContext.getSubscriptionManager().startDelegatingForPublishing();
- }
-
- // TODO more of the above
- // TODO custom started activities
- // (elaborate or remove ^^^ ? -AH, Sept 2014)
- }
-
- if (!isReadOnly()) {
- entity.onManagementBecomingMaster();
- entity.onManagementStarted();
- }
-
- synchronized (this) {
- nonDeploymentManagementContext = null;
- }
- } catch (Throwable t) {
- managementFailed.set(true);
- throw Exceptions.propagate(t);
- }
- }
-
- @SuppressWarnings("deprecation")
- public void onManagementStopping(ManagementTransitionInfo info) {
- synchronized (this) {
- if (managementContext != info.getManagementContext()) {
- throw new IllegalStateException("onManagementStopping encountered different management context for "+entity+
- (!wasDeployed() ? " (wasn't deployed)" : !isDeployed() ? " (no longer deployed)" : "")+
- ": "+managementContext+"; expected "+info.getManagementContext()+" (may be a pre-registered entity which was never properly managed)");
- }
- Stopwatch startTime = Stopwatch.createStarted();
- while (!managementFailed.get() && nonDeploymentManagementContext!=null &&
- nonDeploymentManagementContext.getMode()==NonDeploymentManagementContextMode.MANAGEMENT_STARTING) {
- // still becoming managed
- try {
- if (startTime.elapsed(TimeUnit.SECONDS) > 30) {
- // emergency fix, 30s timeout for management starting
- log.error("Management stopping event "+info+" in "+this+" timed out waiting for start; proceeding to stopping");
- break;
- }
- wait(100);
- } catch (InterruptedException e) {
- Exceptions.propagate(e);
- }
- }
- if (nonDeploymentManagementContext==null) {
- nonDeploymentManagementContext = new NonDeploymentManagementContext(entity, NonDeploymentManagementContextMode.MANAGEMENT_STOPPING);
- } else {
- // already stopped? or not started?
- nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STOPPING);
- }
- }
- // TODO custom stopping activities
- // TODO framework stopping events - no more sensors, executions, etc
- // (elaborate or remove ^^^ ? -AH, Sept 2014)
-
- if (!isReadOnly() && info.getMode().isDestroying()) {
- // if we support remote parent of local child, the following call will need to be properly remoted
- if (entity.getParent()!=null) entity.getParent().removeChild(entity.getProxyIfAvailable());
- }
- // new subscriptions will be queued / not allowed
- nonDeploymentManagementContext.getSubscriptionManager().stopDelegatingForSubscribing();
- // new publications will be queued / not allowed
- nonDeploymentManagementContext.getSubscriptionManager().stopDelegatingForPublishing();
-
- if (!isReadOnly()) {
- entity.onManagementNoLongerMaster();
- entity.onManagementStopped();
- }
- }
-
- public void onManagementStopped(ManagementTransitionInfo info) {
- synchronized (this) {
- if (managementContext == null && nonDeploymentManagementContext.getMode() == NonDeploymentManagementContextMode.MANAGEMENT_STOPPED) {
- return;
- }
- if (managementContext != info.getManagementContext()) {
- throw new IllegalStateException("Has different management context: "+managementContext+"; expected "+info.getManagementContext());
- }
- getSubscriptionContext().unsubscribeAll();
- entityChangeListener = EntityChangeListener.NOOP;
- managementContextUsable.set(false);
- currentlyDeployed.set(false);
- executionContext = null;
- subscriptionContext = null;
- }
-
- // TODO framework stopped activities, e.g. serialize state ?
- entity.invalidateReferences();
-
- synchronized (this) {
- managementContext = null;
- nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STOPPED);
- }
- }
-
- @VisibleForTesting
- @Beta
- public boolean isManagementContextReal() {
- return managementContextUsable.get();
- }
-
- public synchronized ManagementContext getManagementContext() {
- return (managementContextUsable.get()) ? managementContext : nonDeploymentManagementContext;
- }
-
- public synchronized ExecutionContext getExecutionContext() {
- if (executionContext!=null) return executionContext;
- if (managementContextUsable.get()) {
- executionContext = managementContext.getExecutionContext(entity);
- return executionContext;
- }
- return nonDeploymentManagementContext.getExecutionContext(entity);
- }
- public synchronized SubscriptionContext getSubscriptionContext() {
- if (subscriptionContext!=null) return subscriptionContext;
- if (managementContextUsable.get()) {
- subscriptionContext = managementContext.getSubscriptionContext(entity);
- return subscriptionContext;
- }
- return nonDeploymentManagementContext.getSubscriptionContext(entity);
- }
- public synchronized EntitlementManager getEntitlementManager() {
- return getManagementContext().getEntitlementManager();
- }
-
- public void attemptLegacyAutodeployment(String effectorName) {
- synchronized (this) {
- if (managementContext != null) {
- log.warn("Autodeployment suggested but not required for " + entity + "." + effectorName);
- return;
- }
- if (entity instanceof Application) {
- log.warn("Autodeployment with new management context triggered for " + entity + "." + effectorName + " -- will not be supported in future. Explicit manage call required.");
- if (initialManagementContext != null) {
- initialManagementContext.getEntityManager().manage(entity);
- } else {
- Entities.startManagement(entity);
- }
- return;
- }
- }
- if ("start".equals(effectorName)) {
- Entity e=entity;
- if (e.getParent()!=null && ((EntityInternal)e.getParent()).getManagementSupport().isDeployed()) {
- log.warn("Autodeployment in parent's management context triggered for "+entity+"."+effectorName+" -- will not be supported in future. Explicit manage call required.");
- ((EntityInternal)e.getParent()).getManagementContext().getEntityManager().manage(entity);
- return;
- }
- }
- log.warn("Autodeployment not available for "+entity+"."+effectorName);
- }
-
- public EntityChangeListener getEntityChangeListener() {
- return entityChangeListener;
- }
-
- private class EntityChangeListenerImpl implements EntityChangeListener {
- @Override
- public void onChanged() {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- }
- @Override
- public void onChildrenChanged() {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- }
- @Override
- public void onLocationsChanged() {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- }
- @Override
- public void onTagsChanged() {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- }
- @Override
- public void onMembersChanged() {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- }
- @Override
- public void onPolicyAdded(Policy policy) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- getManagementContext().getRebindManager().getChangeListener().onManaged(policy);
- }
- @Override
- public void onEnricherAdded(Enricher enricher) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- getManagementContext().getRebindManager().getChangeListener().onManaged(enricher);
- }
- @Override
- public void onFeedAdded(Feed feed) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- getManagementContext().getRebindManager().getChangeListener().onManaged(feed);
- }
- @Override
- public void onPolicyRemoved(Policy policy) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- getManagementContext().getRebindManager().getChangeListener().onUnmanaged(policy);
- }
- @Override
- public void onEnricherRemoved(Enricher enricher) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- getManagementContext().getRebindManager().getChangeListener().onUnmanaged(enricher);
- }
- @Override
- public void onFeedRemoved(Feed feed) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- getManagementContext().getRebindManager().getChangeListener().onUnmanaged(feed);
- }
- @Override
- public void onAttributeChanged(AttributeSensor<?> attribute) {
- // TODO Could make this more efficient by inspecting the attribute to decide if needs persisted
- // immediately, or not important, or transient (e.g. do we really need to persist
- // request-per-second count for rebind purposes?!)
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- }
- @Override
- public void onConfigChanged(ConfigKey<?> key) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- }
- @Override
- public void onEffectorStarting(Effector<?> effector, Object parameters) {
- Entitlements.checkEntitled(getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(entity, StringAndArgument.of(effector.getName(), parameters)));
- }
- @Override
- public void onEffectorCompleted(Effector<?> effector) {
- getManagementContext().getRebindManager().getChangeListener().onChanged(entity);
- }
- }
-
- @Override
- public String toString() {
- return super.toString()+"["+(entity==null ? "null" : entity.getId())+"]";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EntityManagementUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagementUtils.java b/core/src/main/java/brooklyn/management/internal/EntityManagementUtils.java
deleted file mode 100644
index 24ece98..0000000
--- a/core/src/main/java/brooklyn/management/internal/EntityManagementUtils.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import io.brooklyn.camp.CampPlatform;
-import io.brooklyn.camp.spi.Assembly;
-import io.brooklyn.camp.spi.AssemblyTemplate;
-import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
-
-import java.io.StringReader;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Callable;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.basic.EntityLocal;
-import org.apache.brooklyn.api.entity.proxying.EntitySpec;
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityFunctions;
-import brooklyn.entity.effector.Effectors;
-import brooklyn.entity.trait.Startable;
-import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.task.TaskBuilder;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-
-/** Utility methods for working with entities and applications */
-public class EntityManagementUtils {
-
- private static final Logger log = LoggerFactory.getLogger(EntityManagementUtils.class);
-
- /**
- * A marker config value which indicates that an application was created automatically
- * to allow the management of a non-app entity.
- */
- public static final ConfigKey<Boolean> WRAPPER_APP_MARKER = ConfigKeys.newBooleanConfigKey("brooklyn.wrapper_app");
-
- /** creates an application from the given app spec, managed by the given management context */
- public static <T extends Application> T createUnstarted(ManagementContext mgmt, EntitySpec<T> spec) {
- T app = mgmt.getEntityManager().createEntity(spec);
- Entities.startManagement(app, mgmt);
- return app;
- }
-
- /** convenience for accessing camp */
- public static Maybe<CampPlatform> getCampPlatform(ManagementContext mgmt) {
- return BrooklynServerConfig.getCampPlatform(mgmt);
- }
-
- /** as {@link #createApplication(ManagementContext, EntitySpec)} but for a YAML spec */
- public static <T extends Application> T createUnstarted(ManagementContext mgmt, String yaml) {
- AssemblyTemplate at = getCampPlatform(mgmt).get().pdp().registerDeploymentPlan( new StringReader(yaml) );
- return createUnstarted(mgmt, at);
- }
-
- /** as {@link #createApplication(ManagementContext, EntitySpec)} but for an assembly template */
- @SuppressWarnings("unchecked")
- public static <T extends Application> T createUnstarted(ManagementContext mgmt, AssemblyTemplate at) {
- CampPlatform camp = getCampPlatform(mgmt).get();
- AssemblyTemplateInstantiator instantiator;
- try {
- instantiator = at.getInstantiator().newInstance();
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- Assembly assembly;
- if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
- BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
-
- EntitySpec<?> spec = ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, true);
- Entity app = mgmt.getEntityManager().createEntity(spec);
- Entities.startManagement((Application)app, mgmt);
- return (T) app;
- } else {
- // currently, all brooklyn plans should produce the above; currently this will always throw Unsupported
- try {
- assembly = instantiator.instantiate(at, camp);
- return (T) mgmt.getEntityManager().getEntity(assembly.getId());
- } catch (UnsupportedOperationException e) {
- if (at.getPlatformComponentTemplates()==null || at.getPlatformComponentTemplates().isEmpty()) {
- if (at.getCustomAttributes().containsKey("brooklyn.catalog"))
- throw new IllegalArgumentException("Unrecognized application blueprint format: expected an application, not a brooklyn.catalog");
- throw new IllegalArgumentException("Unrecognized application blueprint format: no services defined");
- }
- // map this (expected) error to a nicer message
- throw new IllegalArgumentException("Unrecognized application blueprint format");
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- throw new IllegalArgumentException("Invalid plan: "+at, e);
- }
- }
- }
-
- /** container for operation which creates something and which wants to return both
- * the items created and any pending create/start task */
- public static class CreationResult<T,U> {
- private final T thing;
- @Nullable private final Task<U> task;
- public CreationResult(T thing, Task<U> task) {
- super();
- this.thing = thing;
- this.task = task;
- }
-
- protected static <T,U> CreationResult<T,U> of(T thing, @Nullable Task<U> task) {
- return new CreationResult<T,U>(thing, task);
- }
-
- /** returns the thing/things created */
- @Nullable public T get() { return thing; }
- /** associated task, ie the one doing the creation/starting */
- public Task<U> task() { return task; }
- public CreationResult<T,U> blockUntilComplete(Duration timeout) { if (task!=null) task.blockUntilEnded(timeout); return this; }
- public CreationResult<T,U> blockUntilComplete() { if (task!=null) task.blockUntilEnded(); return this; }
- }
-
- public static <T extends Application> CreationResult<T,Void> createStarting(ManagementContext mgmt, EntitySpec<T> appSpec) {
- return start(createUnstarted(mgmt, appSpec));
- }
-
- public static CreationResult<? extends Application,Void> createStarting(ManagementContext mgmt, String appSpec) {
- return start(createUnstarted(mgmt, appSpec));
- }
-
- public static CreationResult<? extends Application,Void> createStarting(ManagementContext mgmt, AssemblyTemplate at) {
- return start(createUnstarted(mgmt, at));
- }
-
- public static <T extends Application> CreationResult<T,Void> start(T app) {
- Task<Void> task = Entities.invokeEffector((EntityLocal)app, app, Startable.START,
- // locations already set in the entities themselves;
- // TODO make it so that this arg does not have to be supplied to START !
- MutableMap.of("locations", MutableList.of()));
- return CreationResult.of(app, task);
- }
-
- public static CreationResult<List<Entity>, List<String>> addChildren(final EntityLocal parent, String yaml, Boolean start) {
- if (Boolean.FALSE.equals(start))
- return CreationResult.of(addChildrenUnstarted(parent, yaml), null);
- return addChildrenStarting(parent, yaml);
- }
-
- /** adds entities from the given yaml, under the given parent; but does not start them */
- public static List<Entity> addChildrenUnstarted(final EntityLocal parent, String yaml) {
- log.debug("Creating child of "+parent+" from yaml:\n{}", yaml);
-
- ManagementContext mgmt = parent.getApplication().getManagementContext();
- CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get();
-
- AssemblyTemplate at = camp.pdp().registerDeploymentPlan( new StringReader(yaml) );
-
- AssemblyTemplateInstantiator instantiator;
- try {
- instantiator = at.getInstantiator().newInstance();
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
- BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
- EntitySpec<?> specA = ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, false);
-
- // see whether we can promote children
- List<EntitySpec<?>> specs = MutableList.of();
- if (hasNoNameOrCustomKeysOrRoot(at, specA)) {
- // we can promote
- for (EntitySpec<?> specC: specA.getChildren()) {
- collapseSpec(specA, specC);
- specs.add(specC);
- }
- } else {
- // if not promoting, set a nice name if needed
- if (Strings.isEmpty(specA.getDisplayName())) {
- int size = specA.getChildren().size();
- String childrenCountString = size+" "+(size!=1 ? "children" : "child");
- specA.displayName("Dynamically added "+childrenCountString);
- }
- specs.add(specA);
- }
-
- final List<Entity> children = MutableList.of();
- for (EntitySpec<?> spec: specs) {
- Entity child = (Entity)parent.addChild(spec);
- Entities.manage(child);
- children.add(child);
- }
-
- return children;
- } else {
- throw new IllegalStateException("Spec could not be parsed to supply a compatible instantiator");
- }
- }
-
- public static CreationResult<List<Entity>,List<String>> addChildrenStarting(final EntityLocal parent, String yaml) {
- final List<Entity> children = addChildrenUnstarted(parent, yaml);
- String childrenCountString;
-
- int size = children.size();
- childrenCountString = size+" "+(size!=1 ? "children" : "child");
-
- TaskBuilder<List<String>> taskM = Tasks.<List<String>>builder().name("add children")
- .dynamic(true)
- .tag(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG)
- .body(new Callable<List<String>>() {
- @Override public List<String> call() throws Exception {
- return ImmutableList.copyOf(Iterables.transform(children, EntityFunctions.id()));
- }})
- .description("Add and start "+childrenCountString);
-
- TaskBuilder<?> taskS = Tasks.builder().parallel(true).name("add (parallel)").description("Start each new entity");
-
- // autostart if requested
- for (Entity child: children) {
- if (child instanceof Startable) {
- taskS.add(Effectors.invocation(child, Startable.START, ImmutableMap.of("locations", ImmutableList.of())));
- } else {
- // include a task, just to give feedback in the GUI
- taskS.add(Tasks.builder().name("create").description("Skipping start (not a Startable Entity)")
- .body(new Runnable() { public void run() {} })
- .tag(BrooklynTaskTags.tagForTargetEntity(child))
- .build());
- }
- }
- taskM.add(taskS.build());
- Task<List<String>> task = Entities.submit(parent, taskM.build());
-
- return CreationResult.of(children, task);
- }
-
- /** worker method to combine specs */
- @Beta //where should this live long-term?
- public static void collapseSpec(EntitySpec<?> sourceToBeCollapsed, EntitySpec<?> targetToBeExpanded) {
- if (Strings.isEmpty(targetToBeExpanded.getDisplayName()))
- targetToBeExpanded.displayName(sourceToBeCollapsed.getDisplayName());
- if (!sourceToBeCollapsed.getLocations().isEmpty())
- targetToBeExpanded.locations(sourceToBeCollapsed.getLocations());
-
- // NB: this clobbers child config; might prefer to deeply merge maps etc
- // (but this should not be surprising, as unwrapping is often parameterising the nested blueprint, so outer config should dominate)
- targetToBeExpanded.configure(sourceToBeCollapsed.getConfig());
- targetToBeExpanded.configure(sourceToBeCollapsed.getFlags());
-
- // TODO copying tags to all entities is not ideal;
- // in particular the BrooklynTags.YAML_SPEC tag will show all entities if the root has multiple
- targetToBeExpanded.tags(sourceToBeCollapsed.getTags());
- }
-
- /** worker method to help determine whether child/children can be promoted */
- @Beta //where should this live long-term?
- public static boolean hasNoNameOrCustomKeysOrRoot(AssemblyTemplate template, EntitySpec<?> spec) {
- if (Strings.isNonEmpty(template.getName())) {
- if (spec.getChildren().size()==1) {
- String childName = Iterables.getOnlyElement(spec.getChildren()).getDisplayName();
- if (Strings.isEmpty(childName) || childName.equals(template.getName())) {
- // if child has no name, or it's the same, could still promote
- } else {
- return false;
- }
- } else {
- // if name set at root and promoting children would be ambiguous, do not promote
- return false;
- }
- } else if (spec.getChildren().size()>1) {
- // don't allow multiple children if a name is specified as a root
- return false;
- }
-
- Set<String> rootAttrs = template.getCustomAttributes().keySet();
- for (String rootAttr: rootAttrs) {
- if (rootAttr.equals("brooklyn.catalog") || rootAttr.equals("brooklyn.config")) {
- // these do not block promotion
- continue;
- }
- if (rootAttr.startsWith("brooklyn.")) {
- // any others in 'brooklyn' namespace will block promotion
- return false;
- }
- // location is allowed in both, and is copied on promotion
- // (name also copied)
- // others are root currently are ignored on promotion; they are usually metadata
- // TODO might be nice to know what we are excluding
- }
-
- return true;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java b/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java
deleted file mode 100644
index aa55b59..0000000
--- a/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.management.EntityManager;
-
-public interface EntityManagerInternal extends EntityManager, BrooklynObjectManagerInternal<Entity> {
-
- /** gets all entities currently known to the application, including entities that are not yet managed */
- Iterable<Entity> getAllEntitiesInApplication(Application application);
-
- public Iterable<String> getEntityIds();
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java b/core/src/main/java/brooklyn/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java
deleted file mode 100644
index 973e030..0000000
--- a/core/src/main/java/brooklyn/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import groovy.util.ObservableList;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-
-public class GroovyObservablesPropertyChangeToCollectionChangeAdapter implements PropertyChangeListener {
- @SuppressWarnings("rawtypes")
- private final CollectionChangeListener delegate;
-
- public GroovyObservablesPropertyChangeToCollectionChangeAdapter(@SuppressWarnings("rawtypes") CollectionChangeListener delegate) {
- this.delegate = delegate;
- }
-
- @SuppressWarnings("unchecked")
- public void propertyChange(PropertyChangeEvent evt) {
- if (evt instanceof ObservableList.ElementAddedEvent) {
- delegate.onItemAdded(evt.getNewValue());
- } else if (evt instanceof ObservableList.ElementRemovedEvent) {
- delegate.onItemRemoved(evt.getOldValue());
- } else if (evt instanceof ObservableList.ElementUpdatedEvent) {
- delegate.onItemRemoved(evt.getOldValue());
- delegate.onItemAdded(evt.getNewValue());
- } else if (evt instanceof ObservableList.ElementClearedEvent) {
- for (Object value : ((ObservableList.ElementClearedEvent) evt).getValues()) {
- delegate.onItemAdded(value);
- }
- } else if(evt instanceof ObservableList.MultiElementAddedEvent ) {
- for(Object value: ((ObservableList.MultiElementAddedEvent)evt).getValues()){
- delegate.onItemAdded(value);
- }
- }
- }
-
- public int hashCode() {
- return delegate.hashCode();
- }
-
- public boolean equals(Object other) {
- if (other instanceof GroovyObservablesPropertyChangeToCollectionChangeAdapter)
- return delegate.equals(((GroovyObservablesPropertyChangeToCollectionChangeAdapter) other).delegate);
- if (other instanceof CollectionChangeListener)
- return delegate.equals(other);
- return false;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/LocalAccessManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/internal/LocalAccessManager.java b/core/src/main/java/brooklyn/management/internal/LocalAccessManager.java
deleted file mode 100644
index 696d0f0..0000000
--- a/core/src/main/java/brooklyn/management/internal/LocalAccessManager.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.internal;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.AccessController;
-
-import com.google.common.annotations.Beta;
-
-@Beta
-public class LocalAccessManager implements AccessManager {
-
- private volatile boolean locationProvisioningAllowed = true;
- private volatile boolean locationManagementAllowed = true;
- private volatile boolean entityManagementAllowed = true;
-
- private final AtomicReference<AccessControllerImpl> controller = new AtomicReference<AccessControllerImpl>();
-
- public LocalAccessManager() {
- updateAccessController();
- }
-
- @Override
- public AccessController getAccessController() {
- return controller.get();
- }
-
- @Override
- public boolean isLocationProvisioningAllowed() {
- return locationProvisioningAllowed;
- }
-
- @Override
- public boolean isLocationManagementAllowed() {
- return locationManagementAllowed;
- }
-
- @Override
- public boolean isEntityManagementAllowed() {
- return entityManagementAllowed;
- }
-
- @Override
- public void setLocationProvisioningAllowed(boolean allowed) {
- locationProvisioningAllowed = allowed;
- updateAccessController();
- }
-
- @Override
- public void setLocationManagementAllowed(boolean allowed) {
- locationManagementAllowed = allowed;
- updateAccessController();
- }
-
- @Override
- public void setEntityManagementAllowed(boolean allowed) {
- entityManagementAllowed = allowed;
- updateAccessController();
- }
-
- private void updateAccessController() {
- controller.set(new AccessControllerImpl(locationProvisioningAllowed, locationManagementAllowed, entityManagementAllowed));
- }
-
- private static class AccessControllerImpl implements AccessController {
- private final boolean locationProvisioningAllowed;
- private final boolean locationManagementAllowed;
- private final boolean entityManagementAllowed;
-
- public AccessControllerImpl(boolean locationProvisioningAllowed, boolean locationManagementAllowed,
- boolean entityManagementAllowed) {
- this.locationProvisioningAllowed = locationProvisioningAllowed;
- this.locationManagementAllowed = locationManagementAllowed;
- this.entityManagementAllowed = entityManagementAllowed;
- }
-
- @Override
- public Response canProvisionLocation(Location provisioner) {
- return (locationProvisioningAllowed ? Response.allowed() : Response.disallowed("location provisioning disabled"));
- }
-
- @Override
- public Response canManageLocation(Location loc) {
- return (locationManagementAllowed ? Response.allowed() : Response.disallowed("location management disabled"));
- }
-
- @Override
- public Response canManageEntity(Entity entity) {
- return (entityManagementAllowed ? Response.allowed() : Response.disallowed("entity management disabled"));
- }
- }
-}
[22/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
deleted file mode 100644
index c4489fe..0000000
--- a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
+++ /dev/null
@@ -1,1105 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.entity.Application;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.rebind.RebindManager;
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.management.Task;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityManager;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
-import org.apache.brooklyn.api.management.ha.MementoCopyMode;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister.Delta;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.BrooklynVersion;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
-import brooklyn.catalog.internal.CatalogDto;
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.rebind.RebindManagerImpl;
-import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
-import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils.CreateBackupMode;
-import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
-import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
-import brooklyn.entity.rebind.plane.dto.ManagementPlaneSyncRecordImpl;
-import brooklyn.entity.rebind.plane.dto.ManagementPlaneSyncRecordImpl.Builder;
-import brooklyn.internal.BrooklynFeatureEnablement;
-import brooklyn.management.ha.BasicMasterChooser.AlphabeticMasterChooser;
-import brooklyn.management.internal.BrooklynObjectManagementMode;
-import brooklyn.management.internal.LocalEntityManager;
-import brooklyn.management.internal.LocationManagerInternal;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.management.internal.ManagementTransitionMode;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.ReferenceWithError;
-import brooklyn.util.task.ScheduledTask;
-import brooklyn.util.task.Tasks;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Ticker;
-import com.google.common.collect.Iterables;
-
-/**
- * This is the guts of the high-availability solution in Brooklyn.
- * <p>
- * Multiple brooklyn nodes can be started to form a single management plane, where one node is
- * designated master and the others are "warm standbys". On termination or failure of the master,
- * the standbys deterministically decide which standby should become master (see {@link MasterChooser}).
- * That standby promotes itself.
- * <p>
- * The management nodes communicate their health/status via the {@link ManagementPlaneSyncRecordPersister}.
- * For example, if using {@link ManagementPlaneSyncRecordPersisterToObjectStore} with a shared blobstore or
- * filesystem/NFS mount, then each management-node periodically writes its state.
- * This acts as a heartbeat, being read by the other management-nodes.
- * <p>
- * Promotion to master involves:
- * <ol>
- * <li>notifying the other management-nodes that it is now master
- * <li>calling {@link RebindManager#rebind(ClassLoader, org.apache.brooklyn.api.entity.rebind.RebindExceptionHandler, ManagementNodeState)} to read all persisted entity state, and thus reconstitute the entities.
- * </ol>
- * <p>
- * Future improvements in this area will include brooklyn-managing-brooklyn to decide + promote
- * the standby.
- *
- * @since 0.7.0
- *
- * @author aled
- */
-@Beta
-public class HighAvailabilityManagerImpl implements HighAvailabilityManager {
-
- public final ConfigKey<Duration> POLL_PERIOD = ConfigKeys.newConfigKey(Duration.class, "brooklyn.ha.pollPeriod",
- "How often nodes should poll to detect whether master is healthy", Duration.seconds(1));
- public final ConfigKey<Duration> HEARTBEAT_TIMEOUT = ConfigKeys.newConfigKey(Duration.class, "brooklyn.ha.heartbeatTimeout",
- "Maximum allowable time for detection of a peer's heartbeat; if no sign of master after this time, "
- + "another node may promote itself", Duration.THIRTY_SECONDS);
-
- @VisibleForTesting /* only used in tests currently */
- public static interface PromotionListener {
- public void promotingToMaster();
- }
-
- private static final Logger LOG = LoggerFactory.getLogger(HighAvailabilityManagerImpl.class);
-
- private final ManagementContextInternal managementContext;
- private volatile String ownNodeId;
- private volatile ManagementPlaneSyncRecordPersister persister;
- private volatile PromotionListener promotionListener;
- private volatile MasterChooser masterChooser = new AlphabeticMasterChooser();
- private volatile Ticker localTickerUtc = new Ticker() {
- // strictly not a ticker because returns millis UTC, but it works fine even so
- @Override
- public long read() {
- return System.currentTimeMillis();
- }
- };
- private volatile Ticker optionalRemoteTickerUtc = null;
-
- private volatile Task<?> pollingTask;
- private volatile boolean disabled;
- private volatile boolean running;
- private volatile ManagementNodeState nodeState = ManagementNodeState.INITIALIZING;
- private volatile boolean nodeStateTransitionComplete = false;
- private volatile long priority = 0;
-
- private final static int MAX_NODE_STATE_HISTORY = 200;
- private final List<Map<String,Object>> nodeStateHistory = MutableList.of();
-
- private volatile transient Duration pollPeriodLocalOverride;
- private volatile transient Duration heartbeatTimeoutOverride;
-
- private volatile ManagementPlaneSyncRecord lastSyncRecord;
-
- private volatile PersistenceActivityMetrics managementStateWritePersistenceMetrics = new PersistenceActivityMetrics();
- private volatile PersistenceActivityMetrics managementStateReadPersistenceMetrics = new PersistenceActivityMetrics();
- private final long startTimeUtc;
-
- public HighAvailabilityManagerImpl(ManagementContextInternal managementContext) {
- this.managementContext = managementContext;
- startTimeUtc = localTickerUtc.read();
- }
-
- @Override
- public HighAvailabilityManagerImpl setPersister(ManagementPlaneSyncRecordPersister persister) {
- this.persister = checkNotNull(persister, "persister");
- return this;
- }
-
- @Override
- public ManagementPlaneSyncRecordPersister getPersister() {
- return persister;
- }
-
- protected synchronized Duration getPollPeriod() {
- if (pollPeriodLocalOverride!=null) return pollPeriodLocalOverride;
- return managementContext.getBrooklynProperties().getConfig(POLL_PERIOD);
- }
-
- /** Overrides {@link #POLL_PERIOD} from brooklyn config,
- * including e.g. {@link Duration#PRACTICALLY_FOREVER} to disable polling;
- * or <code>null</code> to clear a local override */
- public HighAvailabilityManagerImpl setPollPeriod(Duration val) {
- this.pollPeriodLocalOverride = val;
- if (running) {
- registerPollTask();
- }
- return this;
- }
-
- public HighAvailabilityManagerImpl setMasterChooser(MasterChooser val) {
- this.masterChooser = checkNotNull(val, "masterChooser");
- return this;
- }
-
- public synchronized Duration getHeartbeatTimeout() {
- if (heartbeatTimeoutOverride!=null) return heartbeatTimeoutOverride;
- return managementContext.getBrooklynProperties().getConfig(HEARTBEAT_TIMEOUT);
- }
-
- /** Overrides {@link #HEARTBEAT_TIMEOUT} from brooklyn config,
- * including e.g. {@link Duration#PRACTICALLY_FOREVER} to prevent failover due to heartbeat absence;
- * or <code>null</code> to clear a local override */
- public HighAvailabilityManagerImpl setHeartbeatTimeout(Duration val) {
- this.heartbeatTimeoutOverride = val;
- return this;
- }
-
- /** A ticker that reads in milliseconds, for populating local timestamps.
- * Defaults to System.currentTimeMillis(); may be overridden e.g. for testing. */
- public HighAvailabilityManagerImpl setLocalTicker(Ticker val) {
- this.localTickerUtc = checkNotNull(val);
- return this;
- }
-
- /** A ticker that reads in milliseconds, for overriding remote timestamps.
- * Defaults to null which means to use the remote timestamp.
- * Only for testing as this records the remote timestamp in the object.
- * <p>
- * If this is supplied, one must also set {@link ManagementPlaneSyncRecordPersisterToObjectStore#useRemoteTimestampInMemento()}. */
- @VisibleForTesting
- public HighAvailabilityManagerImpl setRemoteTicker(Ticker val) {
- this.optionalRemoteTickerUtc = val;
- return this;
- }
-
- public HighAvailabilityManagerImpl setPromotionListener(PromotionListener val) {
- this.promotionListener = checkNotNull(val, "promotionListener");
- return this;
- }
-
- @Override
- public boolean isRunning() {
- return running;
- }
-
- @Override
- public void disabled() {
- disabled = true;
- ownNodeId = managementContext.getManagementNodeId();
- // this is notionally the master, just not running; see javadoc for more info
- stop(ManagementNodeState.MASTER);
-
- }
-
- @Override
- public void start(HighAvailabilityMode startMode) {
- nodeStateTransitionComplete = true;
- disabled = false;
- running = true;
- changeMode(startMode, true, true);
- }
-
- @Override
- public void changeMode(HighAvailabilityMode startMode) {
- changeMode(startMode, false, false);
- }
-
- @VisibleForTesting
- @Beta
- public void changeMode(HighAvailabilityMode startMode, boolean preventElectionOnExplicitStandbyMode, boolean failOnExplicitModesIfUnusual) {
- if (!running) {
- // if was not running then start as disabled mode, then proceed as normal
- LOG.info("HA changing mode to "+startMode+" from "+getInternalNodeState()+" when not running, forcing an intermediate start as DISABLED then will convert to "+startMode);
- start(HighAvailabilityMode.DISABLED);
- }
- if (getNodeState()==ManagementNodeState.FAILED || getNodeState()==ManagementNodeState.INITIALIZING) {
- if (startMode!=HighAvailabilityMode.DISABLED) {
- // if coming from FAILED (or INITIALIZING because we skipped start call) then treat as initializing
- setInternalNodeState(ManagementNodeState.INITIALIZING);
- }
- }
-
- ownNodeId = managementContext.getManagementNodeId();
- // TODO Small race in that we first check, and then we'll do checkMaster() on first poll,
- // so another node could have already become master or terminated in that window.
- ManagementNodeSyncRecord existingMaster = hasHealthyMaster();
- boolean weAreRecognisedAsMaster = existingMaster!=null && ownNodeId.equals(existingMaster.getNodeId());
- boolean weAreMasterLocally = getInternalNodeState()==ManagementNodeState.MASTER;
-
- // catch error in some tests where mgmt context has a different mgmt context
- if (managementContext.getHighAvailabilityManager()!=this)
- throw new IllegalStateException("Cannot start an HA manager on a management context with a different HA manager!");
-
- if (weAreMasterLocally) {
- // demotion may be required; do this before triggering an election
- switch (startMode) {
- case MASTER:
- case AUTO:
- case DISABLED:
- // no action needed, will do anything necessary below (or above)
- break;
- case HOT_STANDBY:
- case HOT_BACKUP:
- case STANDBY:
- demoteTo(ManagementNodeState.of(startMode).get()); break;
- default:
- throw new IllegalStateException("Unexpected high availability mode "+startMode+" requested for "+this);
- }
- }
-
- ManagementNodeState oldState = getInternalNodeState();
-
- // now do election
- switch (startMode) {
- case AUTO:
- // don't care; let's start and see if we promote ourselves
- if (getInternalNodeState()==ManagementNodeState.INITIALIZING) {
- setInternalNodeState(ManagementNodeState.STANDBY);
- }
- publishAndCheck(true);
- switch (getInternalNodeState()) {
- case HOT_BACKUP:
- if (!nodeStateTransitionComplete) throw new IllegalStateException("Cannot switch to AUTO when in the middle of a transition to "+getInternalNodeState());
- // else change us to standby, desiring to go to hot standby, and continue to below
- setInternalNodeState(ManagementNodeState.STANDBY);
- startMode = HighAvailabilityMode.HOT_BACKUP;
- case HOT_STANDBY:
- case STANDBY:
- if (getInternalNodeState()==ManagementNodeState.STANDBY && oldState==ManagementNodeState.INITIALIZING && startMode!=HighAvailabilityMode.HOT_BACKUP
- && BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY)) {
- // auto requested; not promoted; so it should become hot standby
- startMode = HighAvailabilityMode.HOT_STANDBY;
- }
- ManagementPlaneSyncRecord newState = loadManagementPlaneSyncRecord(true);
- String masterNodeId = newState.getMasterNodeId();
- ManagementNodeSyncRecord masterNodeDetails = newState.getManagementNodes().get(masterNodeId);
- LOG.info("Management node "+ownNodeId+" running as HA " + getInternalNodeState() + " autodetected"
- + (startMode == HighAvailabilityMode.HOT_STANDBY || startMode == HighAvailabilityMode.HOT_BACKUP ?
- " (will change to "+startMode+")" : "")
- + ", " +
- (Strings.isBlank(masterNodeId) ? "no master currently (other node should promote itself soon)" : "master "
- + (existingMaster==null ? "(new) " : "")
- + "is "+masterNodeId +
- (masterNodeDetails==null || masterNodeDetails.getUri()==null ? " (no url)" : " at "+masterNodeDetails.getUri())));
- break;
- case MASTER:
- LOG.info("Management node "+ownNodeId+" running as HA MASTER autodetected");
- break;
- default:
- throw new IllegalStateException("Management node "+ownNodeId+" set to HA AUTO, encountered unexpected mode "+getInternalNodeState());
- }
- break;
- case MASTER:
- if (!failOnExplicitModesIfUnusual || existingMaster==null) {
- promoteToMaster();
- if (existingMaster!=null) {
- LOG.info("Management node "+ownNodeId+" running as HA MASTER explicitly");
- } else {
- LOG.info("Management node "+ownNodeId+" running as HA MASTER explicitly, stealing from "+existingMaster);
- }
- } else if (!weAreRecognisedAsMaster) {
- throw new IllegalStateException("Master already exists; cannot run as master (master "+existingMaster.toVerboseString()+"); "
- + "to trigger a promotion, set a priority and demote the current master");
- } else {
- LOG.info("Management node "+ownNodeId+" already running as HA MASTER, when set explicitly");
- }
- break;
- case HOT_BACKUP:
- setInternalNodeState(ManagementNodeState.HOT_BACKUP);
- // then continue into next block
- case STANDBY:
- case HOT_STANDBY:
- if (startMode!=HighAvailabilityMode.HOT_BACKUP) {
- if (ManagementNodeState.isHotProxy(getInternalNodeState()) && startMode==HighAvailabilityMode.HOT_STANDBY) {
- // if was hot_backup, we can immediately go hot_standby
- setInternalNodeState(ManagementNodeState.HOT_STANDBY);
- } else {
- // from any other state, set standby, then perhaps switch to hot_standby later on (or might become master in the next block)
- setInternalNodeState(ManagementNodeState.STANDBY);
- }
- }
- if (ManagementNodeState.isStandby(getInternalNodeState())) {
- if (!preventElectionOnExplicitStandbyMode) {
- publishAndCheck(true);
- }
- if (failOnExplicitModesIfUnusual && existingMaster==null) {
- LOG.error("Management node "+ownNodeId+" detected no master when "+startMode+" requested and existing master required; failing.");
- throw new IllegalStateException("No existing master; cannot start as "+startMode);
- }
- }
- String message = "Management node "+ownNodeId+" running as HA "+getNodeState()+" (";
- if (getNodeState().toString().equals(startMode.toString()))
- message += "explicitly requested";
- else if (startMode==HighAvailabilityMode.HOT_STANDBY && getNodeState()==ManagementNodeState.STANDBY)
- message += "caller requested "+startMode+", will attempt rebind for HOT_STANDBY next";
- else
- message += "caller requested "+startMode;
-
- if (getNodeState()==ManagementNodeState.MASTER) {
- message += " but election re-promoted this node)";
- } else {
- ManagementPlaneSyncRecord newState = loadManagementPlaneSyncRecord(true);
- if (Strings.isBlank(newState.getMasterNodeId())) {
- message += "); no master currently";
- if (startMode != HighAvailabilityMode.HOT_BACKUP) message += " (subsequent election may repair)";
- } else {
- message += "); master "+newState.getMasterNodeId();
- }
- }
- LOG.info(message);
- break;
- case DISABLED:
- // safe just to run even if we weren't master
- LOG.info("Management node "+ownNodeId+" HA DISABLED (was "+getInternalNodeState()+")");
- demoteTo(ManagementNodeState.FAILED);
- if (pollingTask!=null) pollingTask.cancel(true);
- break;
- default:
- throw new IllegalStateException("Unexpected high availability mode "+startMode+" requested for "+this);
- }
-
- if ((startMode==HighAvailabilityMode.HOT_STANDBY || startMode==HighAvailabilityMode.HOT_BACKUP)) {
- if (!ManagementNodeState.isHotProxy(oldState)) {
- // now transition to hot proxy
- nodeStateTransitionComplete = false;
- if (startMode==HighAvailabilityMode.HOT_STANDBY) {
- // if it should be hot standby, then we may need to promote
- // inform the world that we are transitioning (but not eligible for promotion while going in to hot standby)
- // (no harm in doing this twice)
- publishHealth();
- }
- try {
- activateHotProxy(ManagementNodeState.of(startMode).get()).get();
- // error above now throws
- nodeStateTransitionComplete = true;
- publishHealth();
-
- if (getNodeState()==ManagementNodeState.HOT_STANDBY || getNodeState()==ManagementNodeState.HOT_BACKUP) {
- LOG.info("Management node "+ownNodeId+" now running as HA "+getNodeState()+"; "
- + managementContext.getApplications().size()+" application"+Strings.s(managementContext.getApplications().size())+" loaded");
- } else {
- // shouldn't come here, we should have gotten an error above
- LOG.warn("Management node "+ownNodeId+" unable to promote to "+startMode+" (currently "+getNodeState()+"); "
- + "(see log for further details)");
- }
- } catch (Exception e) {
- LOG.warn("Management node "+ownNodeId+" unable to promote to "+startMode+" (currently "+getNodeState()+"); rethrowing: "+Exceptions.collapseText(e));
- nodeStateTransitionComplete = true;
- throw Exceptions.propagate(e);
- }
- } else {
- // transitioning among hot proxy states - tell the rebind manager
- managementContext.getRebindManager().stopReadOnly();
- managementContext.getRebindManager().startReadOnly(ManagementNodeState.of(startMode).get());
- nodeStateTransitionComplete = true;
- }
- } else {
- nodeStateTransitionComplete = true;
- }
- if (startMode!=HighAvailabilityMode.DISABLED)
- registerPollTask();
- }
-
- @Override
- public void setPriority(long priority) {
- this.priority = priority;
- if (persister!=null) publishHealth();
- }
-
- @Override
- public long getPriority() {
- return priority;
- }
-
- @Override
- public void stop() {
- LOG.debug("Stopping "+this);
- stop(ManagementNodeState.TERMINATED);
- }
-
- private void stop(ManagementNodeState newState) {
- boolean wasRunning = running;
-
- running = false;
- setInternalNodeState(newState);
- if (pollingTask != null) pollingTask.cancel(true);
-
- if (wasRunning) {
- try {
- publishHealth();
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- LOG.error("Problem publishing manager-node health on termination (continuing)", e);
- }
- }
- }
-
- /** returns the node state this node is trying to be in */
- public ManagementNodeState getTransitionTargetNodeState() {
- return getInternalNodeState();
- }
-
- protected ManagementNodeState getInternalNodeState() {
- return nodeState;
- }
-
- protected void setInternalNodeState(ManagementNodeState newState) {
- ManagementNodeState oldState = getInternalNodeState();
- synchronized (nodeStateHistory) {
- if (this.nodeState != newState) {
- nodeStateHistory.add(0, MutableMap.<String,Object>of("state", newState, "timestamp", currentTimeMillis()));
- while (nodeStateHistory.size()>MAX_NODE_STATE_HISTORY) {
- nodeStateHistory.remove(nodeStateHistory.size()-1);
- }
- }
- ((RebindManagerImpl)managementContext.getRebindManager()).setAwaitingInitialRebind(running &&
- (ManagementNodeState.isHotProxy(newState) || newState==ManagementNodeState.MASTER));
- this.nodeState = newState;
- }
-
- if (ManagementNodeState.isHotProxy(oldState) && !ManagementNodeState.isHotProxy(newState)) {
- // could perhaps promote standby items on some transitions; but for now we stop the old read-only and re-load them
- // TODO ideally there'd be an incremental rebind as well as an incremental persist
- managementContext.getRebindManager().stopReadOnly();
- clearManagedItems(ManagementTransitionMode.transitioning(BrooklynObjectManagementMode.LOADED_READ_ONLY, BrooklynObjectManagementMode.UNMANAGED_PERSISTED));
- }
- }
-
- @Override
- public ManagementNodeState getNodeState() {
- ManagementNodeState myNodeState = getInternalNodeState();
- if (myNodeState==ManagementNodeState.FAILED) return getInternalNodeState();
- // if target is master then we claim already being master, to prevent other nodes from taking it
- // (we may fail subsequently of course)
- if (myNodeState==ManagementNodeState.MASTER) return myNodeState;
-
- if (!nodeStateTransitionComplete) return ManagementNodeState.INITIALIZING;
- return myNodeState;
- }
-
- public ManagementPlaneSyncRecord getLastManagementPlaneSyncRecord() {
- return lastSyncRecord;
- }
-
- @SuppressWarnings("unchecked")
- protected void registerPollTask() {
- final Runnable job = new Runnable() {
- @Override public void run() {
- try {
- publishAndCheck(false);
- } catch (Exception e) {
- if (running) {
- LOG.error("Problem in HA-poller: "+e, e);
- } else {
- if (LOG.isDebugEnabled()) LOG.debug("Problem in HA-poller, but no longer running: "+e, e);
- }
- } catch (Throwable t) {
- LOG.error("Problem in HA-poller: "+t, t);
- throw Exceptions.propagate(t);
- }
- }
- };
- Callable<Task<?>> taskFactory = new Callable<Task<?>>() {
- @Override public Task<?> call() {
- return Tasks.builder().dynamic(false).body(job).name("HA poller task").tag(BrooklynTaskTags.TRANSIENT_TASK_TAG)
- .description("polls HA status to see whether this node should promote").build();
- }
- };
-
- LOG.debug("Registering poll task for "+this+", period "+getPollPeriod());
- if (getPollPeriod().equals(Duration.PRACTICALLY_FOREVER)) {
- // don't schedule - used for tests
- // (scheduling fires off one initial task in the background before the delay,
- // which affects tests that want to know exactly when publishing happens;
- // TODO would be nice if scheduled task had a "no initial submission" flag )
- } else {
- if (pollingTask!=null) pollingTask.cancel(true);
-
- ScheduledTask task = new ScheduledTask(MutableMap.of("period", getPollPeriod(), "displayName", "scheduled:[HA poller task]"), taskFactory);
- pollingTask = managementContext.getExecutionManager().submit(task);
- }
- }
-
- /** invoked manually when initializing, and periodically thereafter */
- @VisibleForTesting
- public synchronized void publishAndCheck(boolean initializing) {
- publishHealth();
- checkMaster(initializing);
- }
-
- protected synchronized void publishHealth() {
- if (persister == null) {
- LOG.info("Cannot publish management-node health as no persister");
- return;
- }
-
- Stopwatch timer = Stopwatch.createStarted();
- try {
- ManagementNodeSyncRecord memento = createManagementNodeSyncRecord(false);
- Delta delta = ManagementPlaneSyncRecordDeltaImpl.builder().node(memento).build();
- persister.delta(delta);
- managementStateWritePersistenceMetrics.noteSuccess(Duration.of(timer));
- if (LOG.isTraceEnabled()) LOG.trace("Published management-node health: {}", memento);
- } catch (Throwable t) {
- managementStateWritePersistenceMetrics.noteFailure(Duration.of(timer));
- managementStateWritePersistenceMetrics.noteError(t.toString());
- LOG.debug("Error publishing management-node health (rethrowing): "+t);
- throw Exceptions.propagate(t);
- }
- }
-
- public void publishClearNonMaster() {
- ManagementPlaneSyncRecord plane = getLastManagementPlaneSyncRecord();
- if (plane==null || persister==null) {
- LOG.warn("Cannot clear HA node records; HA not active (or not yet loaded)");
- return;
- }
- brooklyn.management.ha.ManagementPlaneSyncRecordDeltaImpl.Builder db = ManagementPlaneSyncRecordDeltaImpl.builder();
- for (Map.Entry<String,ManagementNodeSyncRecord> node: plane.getManagementNodes().entrySet()) {
- // only keep a node if it both claims master and is recognised as master;
- // else ex-masters who died are kept around!
- if (!ManagementNodeState.MASTER.equals(node.getValue().getStatus()) ||
- !Objects.equal(plane.getMasterNodeId(), node.getValue().getNodeId())) {
- db.removedNodeId(node.getKey());
- }
- }
- persister.delta(db.build());
- // then get, so model is updated
- loadManagementPlaneSyncRecord(true);
- }
-
- protected synchronized void publishDemotion(boolean demotingFromMaster) {
- checkState(getNodeState() != ManagementNodeState.MASTER, "node status must not be master when demoting", getNodeState());
-
- if (persister == null) {
- LOG.info("Cannot publish management-node health as no persister");
- return;
- }
-
- ManagementNodeSyncRecord memento = createManagementNodeSyncRecord(false);
- ManagementPlaneSyncRecordDeltaImpl.Builder deltaBuilder = ManagementPlaneSyncRecordDeltaImpl.builder()
- .node(memento);
- if (demotingFromMaster) {
- deltaBuilder.clearMaster(ownNodeId);
- }
-
- Delta delta = deltaBuilder.build();
- persister.delta(delta);
- if (LOG.isTraceEnabled()) LOG.trace("Published management-node health: {}", memento);
- }
-
- /**
- * Publishes (via {@link #persister}) the state of this management node with itself set to master.
- */
- protected synchronized void publishPromotionToMaster() {
- checkState(getNodeState() == ManagementNodeState.MASTER, "node status must be master on publish, but is %s", getNodeState());
-
- if (persister == null) {
- LOG.info("Cannot publish management-node health as no persister");
- return;
- }
-
- ManagementNodeSyncRecord memento = createManagementNodeSyncRecord(false);
- Delta delta = ManagementPlaneSyncRecordDeltaImpl.builder()
- .node(memento)
- .setMaster(ownNodeId)
- .build();
- persister.delta(delta);
- if (LOG.isTraceEnabled()) LOG.trace("Published management-node health: {}", memento);
- }
-
- protected boolean isHeartbeatOk(ManagementNodeSyncRecord masterNode, ManagementNodeSyncRecord meNode) {
- if (masterNode==null) return false;
- if (meNode==null) {
- // we can't confirm it's healthy, but it appears so as far as we can tell
- return true;
- }
- Long timestampMaster = masterNode.getRemoteTimestamp();
- Long timestampMe = meNode.getRemoteTimestamp();
- if (timestampMaster==null || timestampMe==null) return false;
- return (timestampMe - timestampMaster) <= getHeartbeatTimeout().toMilliseconds();
- }
-
- protected ManagementNodeSyncRecord hasHealthyMaster() {
- ManagementPlaneSyncRecord memento = loadManagementPlaneSyncRecord(false);
-
- String nodeId = memento.getMasterNodeId();
- ManagementNodeSyncRecord masterMemento = (nodeId == null) ? null : memento.getManagementNodes().get(nodeId);
-
- ManagementNodeSyncRecord ourMemento = memento.getManagementNodes().get(ownNodeId);
- boolean result = masterMemento != null && masterMemento.getStatus() == ManagementNodeState.MASTER
- && isHeartbeatOk(masterMemento, ourMemento);
-
- if (LOG.isDebugEnabled()) LOG.debug("Healthy-master check result={}; masterId={}; masterMemento={}; ourMemento={}",
- new Object[] {result, nodeId, (masterMemento == null ? "<none>" : masterMemento.toVerboseString()), (ourMemento == null ? "<none>" : ourMemento.toVerboseString())});
-
- return (result ? masterMemento : null);
- }
-
- /**
- * Looks up the state of all nodes in the management plane, and checks if the master is still ok.
- * If it's not then determines which node should be promoted to master. If it is ourself, then promotes.
- */
- protected void checkMaster(boolean initializing) {
- ManagementPlaneSyncRecord memento = loadManagementPlaneSyncRecord(false);
-
- if (getNodeState()==ManagementNodeState.FAILED || getNodeState()==ManagementNodeState.HOT_BACKUP) {
- // if failed or hot backup then we can't promote ourselves, so no point in checking who is master
- return;
- }
-
- String currMasterNodeId = memento.getMasterNodeId();
- ManagementNodeSyncRecord currMasterNodeRecord = memento.getManagementNodes().get(currMasterNodeId);
- ManagementNodeSyncRecord ownNodeRecord = memento.getManagementNodes().get(ownNodeId);
-
- ManagementNodeSyncRecord newMasterNodeRecord = null;
- boolean demotingSelfInFavourOfOtherMaster = false;
-
- if (currMasterNodeRecord != null && currMasterNodeRecord.getStatus() == ManagementNodeState.MASTER && isHeartbeatOk(currMasterNodeRecord, ownNodeRecord)) {
- // master seems healthy
- if (ownNodeId.equals(currMasterNodeId)) {
- if (LOG.isTraceEnabled()) LOG.trace("Existing master healthy (us): master={}", currMasterNodeRecord.toVerboseString());
- return;
- } else {
- if (ownNodeRecord!=null && ownNodeRecord.getStatus() == ManagementNodeState.MASTER) {
- LOG.error("Management node "+ownNodeId+" detected master change, stolen from us, deferring to "+currMasterNodeId);
- newMasterNodeRecord = currMasterNodeRecord;
- demotingSelfInFavourOfOtherMaster = true;
- } else {
- if (LOG.isTraceEnabled()) LOG.trace("Existing master healthy (remote): master={}", currMasterNodeRecord.toVerboseString());
- return;
- }
- }
- } else if (ownNodeRecord == null || !isHeartbeatOk(ownNodeRecord, ownNodeRecord)) {
- // our heartbeats are also out-of-date! perhaps something wrong with persistence? just log, and don't over-react!
- if (ownNodeRecord == null) {
- LOG.error("No management node memento for self ("+ownNodeId+"); perhaps persister unwritable? "
- + "Master ("+currMasterNodeId+") reported failed but no-op as cannot tell conclusively");
- } else {
- LOG.error("This management node ("+ownNodeId+") memento heartbeats out-of-date; perhaps perister unwritable? "
- + "Master ("+currMasterNodeId+") reported failed but no-op as cannot tell conclusively"
- + ": self="+ownNodeRecord.toVerboseString());
- }
- return;
- } else if (ownNodeId.equals(currMasterNodeId)) {
- // we are supposed to be the master, but seem to be unhealthy!
- LOG.warn("This management node ("+ownNodeId+") supposed to be master but reportedly unhealthy? "
- + "no-op as expect other node to fix: self="+ownNodeRecord.toVerboseString());
- return;
- }
-
- if (demotingSelfInFavourOfOtherMaster) {
- LOG.debug("Master-change for this node only, demoting "+ownNodeRecord.toVerboseString()+" in favour of official master "+newMasterNodeRecord.toVerboseString());
- demoteTo(
- BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY) ?
- ManagementNodeState.HOT_STANDBY : ManagementNodeState.STANDBY);
- return;
- } else {
- LOG.debug("Detected master heartbeat timeout. Initiating a new master election. Master was " + currMasterNodeRecord);
- }
-
- // Need to choose a new master
- newMasterNodeRecord = masterChooser.choose(memento, getHeartbeatTimeout(), ownNodeId);
-
- String newMasterNodeId = (newMasterNodeRecord == null) ? null : newMasterNodeRecord.getNodeId();
- URI newMasterNodeUri = (newMasterNodeRecord == null) ? null : newMasterNodeRecord.getUri();
- boolean weAreNewMaster = ownNodeId.equals(newMasterNodeId);
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Management node master-change required: newMaster={}; oldMaster={}; plane={}, self={}; heartbeatTimeout={}",
- new Object[] {
- (newMasterNodeRecord == null ? "<none>" : newMasterNodeRecord.toVerboseString()),
- (currMasterNodeRecord == null ? currMasterNodeId+" (no memento)": currMasterNodeRecord.toVerboseString()),
- memento,
- ownNodeRecord.toVerboseString(),
- getHeartbeatTimeout()
- });
- }
- String message = "Management node "+ownNodeId+" detected ";
- String currMasterSummary = currMasterNodeId + "(" + (currMasterNodeRecord==null ? "<none>" : timestampString(currMasterNodeRecord.getRemoteTimestamp())) + ")";
- if (weAreNewMaster && (ownNodeRecord.getStatus() == ManagementNodeState.MASTER)) {
- LOG.warn(message + "we must reassert master status, as was stolen and then failed at "+
- (currMasterNodeRecord==null ? "a node which has gone away" : currMasterSummary));
- publishPromotionToMaster();
- publishHealth();
- return;
- }
-
- if (!initializing) {
- if (weAreNewMaster) {
- message += "we should be master, changing from ";
- }
- else if (currMasterNodeRecord==null && newMasterNodeId==null) message += "master change attempted but no candidates ";
- else message += "master change, from ";
- message += currMasterSummary + " to "
- + (newMasterNodeId == null ? "<none>" :
- (weAreNewMaster ? "us " : "")
- + newMasterNodeId + " (" + timestampString(newMasterNodeRecord.getRemoteTimestamp()) + ")"
- + (newMasterNodeUri!=null ? " "+newMasterNodeUri : "") );
- // always log, if you're looking at a standby node it's useful to see the new master's URL
- LOG.info(message);
- }
-
- // New master is ourself: promote
- if (weAreNewMaster) {
- promoteToMaster();
- }
- }
-
- private static String timestampString(Long remoteTimestamp) {
- if (remoteTimestamp==null) return null;
- return remoteTimestamp+" / "+Time.makeTimeStringRounded( Duration.sinceUtc(remoteTimestamp))+" ago";
- }
-
- protected void promoteToMaster() {
- if (!running) {
- LOG.warn("Ignoring promote-to-master request, as HighAvailabilityManager is not running");
- return;
- }
-
- if (promotionListener != null) {
- try {
- promotionListener.promotingToMaster();
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- LOG.warn("Problem in promption-listener (continuing)", e);
- }
- }
- setInternalNodeState(ManagementNodeState.MASTER);
- publishPromotionToMaster();
- try {
- managementContext.getRebindManager().rebind(managementContext.getCatalogClassLoader(), null, getInternalNodeState());
- } catch (Exception e) {
- LOG.error("Management node "+managementContext.getManagementNodeId()+" enountered problem during rebind when promoting self to master; demoting to FAILED and rethrowing: "+e);
- demoteTo(ManagementNodeState.FAILED);
- throw Exceptions.propagate(e);
- }
- managementContext.getRebindManager().start();
- }
-
- protected void backupOnDemotionIfNeeded() {
- if (managementContext.getBrooklynProperties().getConfig(BrooklynServerConfig.PERSISTENCE_BACKUPS_REQUIRED_ON_DEMOTION)) {
- BrooklynPersistenceUtils.createBackup(managementContext, CreateBackupMode.DEMOTION, MementoCopyMode.LOCAL);
- }
- }
-
- /** @deprecated since 0.7.0, use {@link #demoteTo(ManagementNodeState)} */ @Deprecated
- protected void demoteToFailed() {
- demoteTo(ManagementNodeState.FAILED);
- }
- /** @deprecated since 0.7.0, use {@link #demoteTo(ManagementNodeState)} */ @Deprecated
- protected void demoteToStandby(boolean hot) {
- demoteTo(hot ? ManagementNodeState.HOT_STANDBY : ManagementNodeState.STANDBY);
- }
-
- protected void demoteTo(ManagementNodeState toState) {
- if (toState!=ManagementNodeState.FAILED && !running) {
- LOG.warn("Ignoring demote-from-master request, as HighAvailabilityManager is no longer running");
- return;
- }
- boolean wasMaster = (getInternalNodeState() == ManagementNodeState.MASTER);
- if (wasMaster) backupOnDemotionIfNeeded();
- // TODO target may be RO ?
- ManagementTransitionMode mode = ManagementTransitionMode.transitioning(
- wasMaster ? BrooklynObjectManagementMode.MANAGED_PRIMARY : BrooklynObjectManagementMode.LOADED_READ_ONLY,
- BrooklynObjectManagementMode.UNMANAGED_PERSISTED);
-
- nodeStateTransitionComplete = false;
-
- switch (toState) {
- case FAILED:
- case HOT_BACKUP:
- case STANDBY:
- setInternalNodeState(toState); break;
- case HOT_STANDBY:
- setInternalNodeState(ManagementNodeState.STANDBY); break;
- default:
- throw new IllegalStateException("Illegal target state: "+toState);
- }
- onDemotionStopItems(mode);
- nodeStateTransitionComplete = true;
- publishDemotion(wasMaster);
-
- if (toState==ManagementNodeState.HOT_BACKUP || toState==ManagementNodeState.HOT_STANDBY) {
- nodeStateTransitionComplete = false;
- try {
- activateHotProxy(toState).get();
- } finally {
- nodeStateTransitionComplete = true;
- }
- publishHealth();
- }
- }
-
- protected void onDemotionStopItems(ManagementTransitionMode mode) {
- // stop persistence and remove all apps etc
- managementContext.getRebindManager().stopPersistence();
- managementContext.getRebindManager().stopReadOnly();
- clearManagedItems(mode);
-
- // tasks are cleared as part of unmanaging entities above
- }
-
- /** clears all managed items from the management context; same items destroyed as in the course of a rebind cycle */
- protected void clearManagedItems(ManagementTransitionMode mode) {
- // start with the root applications
- for (Application app: managementContext.getApplications()) {
- if (((EntityInternal)app).getManagementSupport().isDeployed()) {
- ((LocalEntityManager)((EntityInternal)app).getManagementContext().getEntityManager()).unmanage(app, mode);
- }
- }
- // for active management, call above will remove recursively at present,
- // but for read-only, and if we stop recursively, go through them all
- for (Entity entity: managementContext.getEntityManager().getEntities()) {
- ((LocalEntityManager)managementContext.getEntityManager()).unmanage(entity, mode);
- }
-
- // again, for locations, call unmanage on parents first
- for (Location loc: managementContext.getLocationManager().getLocations()) {
- if (loc.getParent()==null)
- ((LocationManagerInternal)managementContext.getLocationManager()).unmanage(loc, mode);
- }
- for (Location loc: managementContext.getLocationManager().getLocations()) {
- ((LocationManagerInternal)managementContext.getLocationManager()).unmanage(loc, mode);
- }
-
- ((BasicBrooklynCatalog)managementContext.getCatalog()).reset(CatalogDto.newEmptyInstance("<reset-by-ha-status-change>"));
- }
-
- /** @deprecated since 0.7.0, use {@link #activateHotProxy(ManagementNodeState)} */ @Deprecated
- protected boolean attemptHotStandby() {
- return activateHotProxy(ManagementNodeState.HOT_STANDBY).getWithoutError();
- }
-
- /** Starts hot standby or hot backup, in foreground
- * <p>
- * In the case of the former, the caller is responsible for publishing health afterwards,
- * but if it fails, this method will {@link #demoteTo(ManagementNodeState)} {@link ManagementNodeState#FAILED}.
- * <p>
- * @return whether the requested {@link ManagementNodeState} was possible;
- * (if not, errors should be stored elsewhere), callers may want to rethrow */
- protected ReferenceWithError<Boolean> activateHotProxy(ManagementNodeState toState) {
- try {
- Preconditions.checkState(nodeStateTransitionComplete==false, "Must be in transitioning state to go into "+toState);
- setInternalNodeState(toState);
- managementContext.getRebindManager().startReadOnly(toState);
-
- return ReferenceWithError.newInstanceWithoutError(true);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- LOG.warn("Unable to change "+ownNodeId+" to "+toState+", switching to FAILED: "+e, e);
- demoteTo(ManagementNodeState.FAILED);
- return ReferenceWithError.newInstanceThrowingError(false, e);
- }
- }
-
- @Override
- public ManagementPlaneSyncRecord loadManagementPlaneSyncRecord(boolean useLocalKnowledgeForThisNode) {
- ManagementPlaneSyncRecord record = loadManagementPlaneSyncRecordInternal(useLocalKnowledgeForThisNode);
- lastSyncRecord = record;
- return record;
- }
-
- private ManagementPlaneSyncRecord loadManagementPlaneSyncRecordInternal(boolean useLocalKnowledgeForThisNode) {
- if (disabled) {
- // if HA is disabled, then we are the only node - no persistence; just load a memento to describe this node
- Builder builder = ManagementPlaneSyncRecordImpl.builder()
- .node(createManagementNodeSyncRecord(true));
- if (getTransitionTargetNodeState() == ManagementNodeState.MASTER) {
- builder.masterNodeId(ownNodeId);
- }
- return builder.build();
- }
- if (persister == null) {
- // e.g. web-console may be polling before we've started up
- LOG.debug("High availablity manager has no persister; returning empty record");
- return ManagementPlaneSyncRecordImpl.builder().build();
- }
-
- int maxLoadAttempts = 5;
- Exception lastException = null;
- Stopwatch timer = Stopwatch.createStarted();
-
- for (int i = 0; i < maxLoadAttempts; i++) {
- try {
- ManagementPlaneSyncRecord result = persister.loadSyncRecord();
-
- if (useLocalKnowledgeForThisNode) {
- // Report this node's most recent state, and detect AWOL nodes
- ManagementNodeSyncRecord me = BasicManagementNodeSyncRecord.builder()
- .from(result.getManagementNodes().get(ownNodeId), true)
- .from(createManagementNodeSyncRecord(false), true)
- .build();
- Iterable<ManagementNodeSyncRecord> allNodes = result.getManagementNodes().values();
- if (me.getRemoteTimestamp()!=null)
- allNodes = Iterables.transform(allNodes, new MarkAwolNodes(me));
- Builder builder = ManagementPlaneSyncRecordImpl.builder()
- .masterNodeId(result.getMasterNodeId())
- .nodes(allNodes);
- builder.node(me);
- if (getTransitionTargetNodeState() == ManagementNodeState.MASTER) {
- builder.masterNodeId(ownNodeId);
- }
- result = builder.build();
- }
-
- if (i>0) {
- managementStateReadPersistenceMetrics.noteError("Succeeded only on attempt "+(i+1)+": "+lastException);
- }
- managementStateReadPersistenceMetrics.noteSuccess(Duration.of(timer));
- return result;
- } catch (IOException e) {
- if (i < (maxLoadAttempts - 1)) {
- if (LOG.isDebugEnabled()) LOG.debug("Problem loading mangement-plane memento attempt "+(i+1)+"/"+maxLoadAttempts+"; retrying", e);
- }
- lastException = e;
- }
- }
- String message = "Failed to load mangement-plane memento "+maxLoadAttempts+" consecutive times";
- managementStateReadPersistenceMetrics.noteError(message+": "+lastException);
- managementStateReadPersistenceMetrics.noteFailure(Duration.of(timer));
-
- throw new IllegalStateException(message, lastException);
- }
-
- protected ManagementNodeSyncRecord createManagementNodeSyncRecord(boolean useLocalTimestampAsRemoteTimestamp) {
- long timestamp = currentTimeMillis();
- brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord.Builder builder = BasicManagementNodeSyncRecord.builder()
- .brooklynVersion(BrooklynVersion.get())
- .nodeId(ownNodeId)
- .status(getNodeState())
- .priority(getPriority())
- .localTimestamp(timestamp)
- .uri(managementContext.getManagementNodeUri().orNull());
- if (useLocalTimestampAsRemoteTimestamp)
- builder.remoteTimestamp(timestamp);
- else if (optionalRemoteTickerUtc!=null) {
- builder.remoteTimestamp(optionalRemoteTickerUtc.read());
- }
- return builder.build();
- }
-
- /**
- * Gets the current time, using the {@link #localTickerUtc}. Normally this is equivalent of {@link System#currentTimeMillis()},
- * but in test environments a custom {@link Ticker} can be injected via {@link #setLocalTicker(Ticker)} to allow testing of
- * specific timing scenarios.
- */
- protected long currentTimeMillis() {
- return localTickerUtc.read();
- }
-
- /**
- * Infers the health of a node - if it last reported itself as healthy (standby or master), but we haven't heard
- * from it in a long time then report that node as failed; otherwise report its health as-is.
- */
- private class MarkAwolNodes implements Function<ManagementNodeSyncRecord, ManagementNodeSyncRecord> {
- private final ManagementNodeSyncRecord referenceNode;
- private MarkAwolNodes(ManagementNodeSyncRecord referenceNode) {
- this.referenceNode = referenceNode;
- }
- @Nullable
- @Override
- public ManagementNodeSyncRecord apply(@Nullable ManagementNodeSyncRecord input) {
- if (input == null) return null;
- if (!(input.getStatus() == ManagementNodeState.STANDBY || input.getStatus() == ManagementNodeState.HOT_STANDBY || input.getStatus() == ManagementNodeState.MASTER || input.getStatus() == ManagementNodeState.HOT_BACKUP)) return input;
- if (isHeartbeatOk(input, referenceNode)) return input;
- return BasicManagementNodeSyncRecord.builder()
- .from(input)
- .status(ManagementNodeState.FAILED)
- .build();
- }
- }
-
- @Override
- public String toString() {
- return super.toString()+"[node:"+ownNodeId+";running="+running+"]";
- }
-
- @Override
- public Map<String,Object> getMetrics() {
- Map<String,Object> result = MutableMap.of();
-
- result.put("state", getNodeState());
- result.put("uptime", Time.makeTimeStringRounded(Duration.millis(currentTimeMillis()-startTimeUtc)));
- result.put("currentTimeUtc", currentTimeMillis());
- result.put("startTimeUtc", startTimeUtc);
- result.put("highAvailability", MutableMap.<String,Object>of(
- "priority", getPriority(),
- "pollPeriod", getPollPeriod().toMilliseconds(),
- "heartbeatTimeout", getHeartbeatTimeout().toMilliseconds(),
- "history", nodeStateHistory));
-
- result.putAll(managementContext.getRebindManager().getMetrics());
- result.put("managementStatePersistence",
- MutableMap.of("read", managementStateReadPersistenceMetrics, "write", managementStateWritePersistenceMetrics));
-
- return result;
- }
-
- @Override
- public long getLastStateChange() {
- if (nodeStateHistory.size() > 0) {
- return (Long)nodeStateHistory.get(0).get("timestamp");
- } else {
- return 0;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/ha/ManagementPlaneSyncRecordDeltaImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/ManagementPlaneSyncRecordDeltaImpl.java b/core/src/main/java/brooklyn/management/ha/ManagementPlaneSyncRecordDeltaImpl.java
deleted file mode 100644
index 029ffb0..0000000
--- a/core/src/main/java/brooklyn/management/ha/ManagementPlaneSyncRecordDeltaImpl.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Collection;
-
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister.Delta;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.Sets;
-
-/**
- * @since 0.7.0
- *
- * @author aled
- */
-@Beta
-public class ManagementPlaneSyncRecordDeltaImpl implements Delta {
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static class Builder {
- private Collection<ManagementNodeSyncRecord> nodes = Sets.newLinkedHashSet();
- private Collection <String> removedNodeIds = Sets.newLinkedHashSet();
- private MasterChange masterChange = MasterChange.NO_CHANGE;
- private String master;
- private String expectedOldMaster;
-
- public Builder node(ManagementNodeSyncRecord node) {
- nodes.add(checkNotNull(node, "node")); return this;
- }
- public Builder removedNodeId(String id) {
- removedNodeIds.add(checkNotNull(id, "id")); return this;
- }
- public Builder setMaster(String nodeId) {
- masterChange = MasterChange.SET_MASTER;
- master = checkNotNull(nodeId, "masterId");
- return this;
- }
- public Builder clearMaster(String optionalExpectedNodeId) {
- masterChange = MasterChange.CLEAR_MASTER;
- this.expectedOldMaster = optionalExpectedNodeId;
- return this;
- }
- public Delta build() {
- return new ManagementPlaneSyncRecordDeltaImpl(this);
- }
- }
-
- private final Collection<ManagementNodeSyncRecord> nodes;
- private final Collection <String> removedNodeIds;
- private final MasterChange masterChange;
- private String masterId;
- private String expectedOldMaster;
-
- ManagementPlaneSyncRecordDeltaImpl(Builder builder) {
- nodes = builder.nodes;
- removedNodeIds = builder.removedNodeIds;
- masterChange = builder.masterChange;
- masterId = builder.master;
- this.expectedOldMaster = builder.expectedOldMaster;
- checkState((masterChange == MasterChange.SET_MASTER) ? (masterId != null) : (masterId == null),
- "invalid combination: change=%s; masterId=%s", masterChange, masterId);
- }
-
- @Override
- public Collection<ManagementNodeSyncRecord> getNodes() {
- return nodes;
- }
-
- @Override
- public Collection<String> getRemovedNodeIds() {
- return removedNodeIds;
- }
-
- @Override
- public MasterChange getMasterChange() {
- return masterChange;
- }
-
- @Override
- public String getNewMasterOrNull() {
- return masterId;
- }
-
- @Override
- public String getExpectedMasterToClear() {
- return expectedOldMaster;
- }
-
- @Override
- public String toString() {
- return getClass().getCanonicalName()+"["+
- (masterChange!=null && masterChange != MasterChange.NO_CHANGE ?
- masterChange+": "+expectedOldMaster+"->"+masterId+"; " : "")+
- "nodes: "+nodes+
- (removedNodeIds!=null && !removedNodeIds.isEmpty() ? "; removing: "+removedNodeIds : "")
- +"]";
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java b/core/src/main/java/brooklyn/management/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java
deleted file mode 100644
index dff815e..0000000
--- a/core/src/main/java/brooklyn/management/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.IOException;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.apache.brooklyn.api.management.ManagementContext;
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.apache.brooklyn.api.management.ha.ManagementNodeState;
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.rebind.persister.MementoSerializer;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore.StoreObjectAccessorWithLock;
-import brooklyn.entity.rebind.persister.RetryingMementoSerializer;
-import brooklyn.entity.rebind.persister.StoreObjectAccessorLocking;
-import brooklyn.entity.rebind.persister.XmlMementoSerializer;
-import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
-import brooklyn.entity.rebind.plane.dto.ManagementPlaneSyncRecordImpl;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-
-import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Maps;
-
-/**
- * Structure of files is:
- * <ul>
- * <li>{@code plane/} - top-level directory
- * <ul>
- * <li>{@code master} - contains the id of the management-node that is currently master
- * <li>{@code change.log} - log of changes made
- * <li>{@code nodes/} - sub-directory, containing one file per management-node
- * <ul>
- * <li>{@code a9WiuVKp} - file named after the management-node's id, containing the management node's current state
- * <li>{@code E1eDXQF3}
- * </ul>
- * </ul>
- * </ul>
- *
- * All writes are done synchronously.
- *
- * @since 0.7.0
- *
- * @author aled
- */
-@Beta
-public class ManagementPlaneSyncRecordPersisterToObjectStore implements ManagementPlaneSyncRecordPersister {
-
- // TODO Multiple node appending to change.log could cause strange interleaving, or perhaps even data loss?
- // But this file is not critical to functionality.
-
- // TODO Should ManagementPlaneSyncRecordPersister.Delta be different so can tell what is a significant event,
- // and thus log it in change.log - currently only subset of significant things being logged.
-
- private static final Logger LOG = LoggerFactory.getLogger(ManagementPlaneSyncRecordPersisterToObjectStore.class);
-
- private static final Duration SHUTDOWN_TIMEOUT = Duration.TEN_SECONDS;
- private static final Duration SYNC_WRITE_TIMEOUT = Duration.TEN_SECONDS;
- public static final String NODES_SUB_PATH = "nodes";
-
- // TODO Leak if we go through lots of managers; but tiny!
- private final ConcurrentMap<String, StoreObjectAccessorWithLock> nodeWriters = Maps.newConcurrentMap();
-
- private StoreObjectAccessorWithLock masterWriter;
- private StoreObjectAccessorWithLock changeLogWriter;
-
- private ManagementContext mgmt;
- private final PersistenceObjectStore objectStore;
- private final MementoSerializer<Object> serializer;
-
- private static final int MAX_SERIALIZATION_ATTEMPTS = 5;
-
- private boolean started = false;
- private volatile boolean running = true;
-
- @VisibleForTesting
- /** allows, when testing, to be able to override file times / blobstore times with time from the ticker */
- private boolean preferRemoteTimestampInMemento = false;
-
- /**
- * @param mgmt not used much at present but handy to ensure we know it so that obj store is prepared
- * @param objectStore the objectStore use to read/write management-plane data;
- * this must have been {@link PersistenceObjectStore#prepareForSharedUse(brooklyn.entity.rebind.persister.PersistMode, HighAvailabilityMode)}
- * @param classLoader ClassLoader to use when deserializing data
- */
- public ManagementPlaneSyncRecordPersisterToObjectStore(ManagementContext mgmt, PersistenceObjectStore objectStore, ClassLoader classLoader) {
- this.mgmt = mgmt;
- this.objectStore = checkNotNull(objectStore, "objectStore");
-
- MementoSerializer<Object> rawSerializer = new XmlMementoSerializer<Object>(checkNotNull(classLoader, "classLoader"));
- this.serializer = new RetryingMementoSerializer<Object>(rawSerializer, MAX_SERIALIZATION_ATTEMPTS);
-
- objectStore.createSubPath(NODES_SUB_PATH);
-
- LOG.debug("ManagementPlaneMemento-persister will use store "+objectStore);
- }
-
- protected synchronized void init() {
- if (!started) {
- started = true;
- //Leading slash causes problems in SL, it's not a correct file name so remove it.
- //But once removed we can't load the master file from existing persistence stores.
- //Try to detect if the old file exists, if so use old-style names, otherwise use the correct names.
- masterWriter = new StoreObjectAccessorLocking(objectStore.newAccessor("/master"));
- if (masterWriter.get() != null) {
- changeLogWriter = new StoreObjectAccessorLocking(objectStore.newAccessor("/change.log"));
- } else {
- masterWriter = new StoreObjectAccessorLocking(objectStore.newAccessor("master"));
- changeLogWriter = new StoreObjectAccessorLocking(objectStore.newAccessor("change.log"));
- }
- }
- }
-
- @VisibleForTesting
- public void preferRemoteTimestampInMemento() {
- preferRemoteTimestampInMemento = true;
- }
-
- @Override
- public void stop() {
- running = false;
- try {
- for (StoreObjectAccessorWithLock writer : nodeWriters.values()) {
- try {
- writer.waitForCurrentWrites(SHUTDOWN_TIMEOUT);
- } catch (TimeoutException e) {
- LOG.warn("Timeout during shutdown, waiting for write of "+writer+"; continuing");
- }
- }
- try {
- masterWriter.waitForCurrentWrites(SHUTDOWN_TIMEOUT);
- } catch (TimeoutException e) {
- LOG.warn("Timeout during shutdown, waiting for write of "+masterWriter+"; continuing");
- }
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- public ManagementPlaneSyncRecord loadSyncRecord() throws IOException {
- if (!running) {
- throw new IllegalStateException("Persister not running; cannot load memento from "+ objectStore.getSummaryName());
- }
- init();
-
- // Note this is called a lot - every time we check the heartbeats
- if (LOG.isTraceEnabled()) LOG.trace("Loading management-plane memento from {}", objectStore.getSummaryName());
-
- Stopwatch stopwatch = Stopwatch.createStarted();
-
- ManagementPlaneSyncRecordImpl.Builder builder = ManagementPlaneSyncRecordImpl.builder();
-
- // Be careful about order: if the master-file says nodeX then nodeX's file must have an up-to-date timestamp.
- // Therefore read master file first, followed by the other node-files.
- String masterNodeId = masterWriter.get();
- if (masterNodeId == null) {
- LOG.debug("No master-memento deserialized from file "+masterWriter+"; ignoring and continuing (normal on startup, should cause an error later in live operation)");
- } else {
- builder.masterNodeId(masterNodeId);
- }
-
- // Load node-files
- List<String> nodeFiles = objectStore.listContentsWithSubPath(NODES_SUB_PATH);
- LOG.trace("Loading nodes from {}; {} nodes.",
- new Object[]{objectStore.getSummaryName(), nodeFiles.size()});
-
- for (String nodeFile : nodeFiles) {
- PersistenceObjectStore.StoreObjectAccessor objectAccessor = objectStore.newAccessor(nodeFile);
- String nodeContents = null;
- Exception problem = null;
- try {
- nodeContents = objectAccessor.get();
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- problem = e;
- }
- if (problem!=null || Strings.isBlank(nodeContents)) {
- // happens if node has gone away, or if FileBasedObjectStore.moveFile is not atomic,
- // i.e. it has deleted but not updated it yet
- if (objectAccessor.exists()) {
- throw Exceptions.propagate(new IllegalStateException("Node record "+nodeFile+" could not be read when "+mgmt.getManagementNodeId()+" was scanning", problem));
- } else {
- LOG.warn("Node record "+nodeFile+" went away while "+mgmt.getManagementNodeId()+" was scanning, ignoring (it has probably been terminated)");
- // if file was deleted, silently ignore
- continue;
- }
- }
- ManagementNodeSyncRecord memento = (ManagementNodeSyncRecord) serializer.fromString(nodeContents);
- if (memento == null) {
- // shouldn't happen
- throw Exceptions.propagate(new IllegalStateException("Node record "+nodeFile+" could not be deserialized when "+mgmt.getManagementNodeId()+" was scanning: "+nodeContents, problem));
- } else {
- if (memento.getRemoteTimestamp()!=null && preferRemoteTimestampInMemento) {
- // in test mode, the remote timestamp is stored in the file
- } else {
- if (memento.getRemoteTimestamp()!=null) {
- LOG.debug("Ignoring remote timestamp in memento file ("+memento+"); looks like this data has been manually copied in");
- }
- Date lastModifiedDate = objectAccessor.getLastModifiedDate();
- ((BasicManagementNodeSyncRecord)memento).setRemoteTimestamp(lastModifiedDate!=null ? lastModifiedDate.getTime() : null);
- }
- builder.node(memento);
- }
- }
-
- if (LOG.isDebugEnabled()) LOG.trace("Loaded management-plane memento; {} nodes, took {}",
- nodeFiles.size(),
- Time.makeTimeStringRounded(stopwatch.elapsed(TimeUnit.MILLISECONDS)));
- return builder.build();
- }
-
- @Override
- public void delta(Delta delta) {
- if (!running) {
- if (LOG.isDebugEnabled()) LOG.debug("Persister not running; ignoring checkpointed delta of manager-memento");
- return;
- }
- init();
-
- Stopwatch stopwatch = Stopwatch.createStarted();
- if (LOG.isTraceEnabled()) LOG.trace("Checkpointing delta of manager-memento; updating {}", delta);
-
- for (ManagementNodeSyncRecord m : delta.getNodes()) {
- persist(m);
- }
- for (String id : delta.getRemovedNodeIds()) {
- deleteNode(id);
- }
- switch (delta.getMasterChange()) {
- case NO_CHANGE:
- break; // no-op
- case SET_MASTER:
- persistMaster(checkNotNull(delta.getNewMasterOrNull()), null);
- break;
- case CLEAR_MASTER:
- persistMaster("", delta.getExpectedMasterToClear());
- break; // no-op
- default:
- throw new IllegalStateException("Unknown state for master-change: "+delta.getMasterChange());
- }
- if (LOG.isDebugEnabled()) LOG.debug("Checkpointed delta of manager-memento in "+Time.makeTimeStringRounded(stopwatch)+": "+delta);
- }
-
- private void persistMaster(String nodeId, String optionalExpectedId) {
- if (optionalExpectedId!=null) {
- String currentRemoteMaster = masterWriter.get();
- if (currentRemoteMaster==null) {
- // okay to have nothing at remote
- } else if (!currentRemoteMaster.trim().equals(optionalExpectedId.trim())) {
- LOG.warn("Master at server is "+(Strings.isBlank(currentRemoteMaster) ? "<none>" : currentRemoteMaster)+"; expected "+optionalExpectedId+" "
- + (Strings.isNonBlank(nodeId) ? "and would set as "+nodeId : "and would clear")
- + ", so not applying (yet)");
- return;
- }
- }
- masterWriter.put(nodeId);
- try {
- masterWriter.waitForCurrentWrites(SYNC_WRITE_TIMEOUT);
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- changeLogWriter.append(Time.makeDateString() + ": set master to " + nodeId + "\n");
- try {
- changeLogWriter.waitForCurrentWrites(SYNC_WRITE_TIMEOUT);
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- @Override
- @VisibleForTesting
- public void waitForWritesCompleted(Duration timeout) throws InterruptedException, TimeoutException {
- for (StoreObjectAccessorWithLock writer : nodeWriters.values()) {
- writer.waitForCurrentWrites(timeout);
- }
- masterWriter.waitForCurrentWrites(timeout);
- }
-
- public void checkpoint(ManagementPlaneSyncRecord record) {
- init();
- for (ManagementNodeSyncRecord node : record.getManagementNodes().values()) {
- // Check included in case the node in the memento is the one being initialised by
- // BrooklynLauncher in the copy state command.
- if (!ManagementNodeState.INITIALIZING.equals(node.getStatus()) && node.getNodeId() != null) {
- persist(node);
- }
- }
- }
-
- private void persist(ManagementNodeSyncRecord node) {
- StoreObjectAccessorWithLock writer = getOrCreateNodeWriter(node.getNodeId());
- boolean fileExists = writer.exists();
- writer.put(serializer.toString(node));
- try {
- writer.waitForCurrentWrites(SYNC_WRITE_TIMEOUT);
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- if (!fileExists) {
- changeLogWriter.append(Time.makeDateString()+": created node "+node.getNodeId()+"\n");
- }
- if (node.getStatus() == ManagementNodeState.TERMINATED || node.getStatus() == ManagementNodeState.FAILED) {
- changeLogWriter.append(Time.makeDateString()+": set node "+node.getNodeId()+" status to "+node.getStatus()+"\n");
- }
- }
-
- private void deleteNode(String nodeId) {
- getOrCreateNodeWriter(nodeId).delete();
- changeLogWriter.append(Time.makeDateString()+": deleted node "+nodeId+"\n");
- }
-
- private StoreObjectAccessorWithLock getOrCreateNodeWriter(String nodeId) {
- PersistenceObjectStore.StoreObjectAccessorWithLock writer = nodeWriters.get(nodeId);
- if (writer == null) {
- nodeWriters.putIfAbsent(nodeId,
- new StoreObjectAccessorLocking(objectStore.newAccessor(NODES_SUB_PATH+"/"+nodeId)));
- writer = nodeWriters.get(nodeId);
- }
- return writer;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/ha/MasterChooser.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/MasterChooser.java b/core/src/main/java/brooklyn/management/ha/MasterChooser.java
deleted file mode 100644
index fdde8b9..0000000
--- a/core/src/main/java/brooklyn/management/ha/MasterChooser.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.ha;
-
-import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
-import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
-
-import brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-
-/**
- * For choosing which management node to promote, when master detected as failed or stopped.
- *
- * @since 0.7.0
- *
- * @author aled
- */
-@Beta
-public interface MasterChooser {
-
- ManagementNodeSyncRecord choose(ManagementPlaneSyncRecord memento, Duration heartbeatTimeout, String ownNodeId);
-
-}
[14/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/management
Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java
new file mode 100644
index 0000000..6a133fc
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/OsgiManager.java
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.ha;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.BrooklynVersion;
+
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
+import org.apache.brooklyn.api.management.ManagementContext;
+
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.config.BrooklynServerPaths;
+import brooklyn.config.ConfigKey;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.os.Os;
+import brooklyn.util.os.Os.DeletionResult;
+import brooklyn.util.osgi.Osgis;
+import brooklyn.util.osgi.Osgis.BundleFinder;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class OsgiManager {
+
+ private static final Logger log = LoggerFactory.getLogger(OsgiManager.class);
+
+ public static final ConfigKey<Boolean> USE_OSGI = BrooklynServerConfig.USE_OSGI;
+
+ /* see Osgis for info on starting framework etc */
+
+ protected ManagementContext mgmt;
+ protected Framework framework;
+ protected File osgiCacheDir;
+
+ public OsgiManager(ManagementContext mgmt) {
+ this.mgmt = mgmt;
+ }
+
+ public void start() {
+ try {
+ osgiCacheDir = BrooklynServerPaths.getOsgiCacheDirCleanedIfNeeded(mgmt);
+
+ // any extra OSGi startup args could go here
+ framework = Osgis.newFrameworkStarted(osgiCacheDir.getAbsolutePath(), false, MutableMap.of());
+
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ public void stop() {
+ try {
+ if (framework!=null) {
+ framework.stop();
+ framework.waitForStop(0); // 0 means indefinite
+ }
+ } catch (BundleException e) {
+ throw Exceptions.propagate(e);
+ } catch (InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ if (BrooklynServerPaths.isOsgiCacheForCleaning(mgmt, osgiCacheDir)) {
+ // See exception reported in https://issues.apache.org/jira/browse/BROOKLYN-72
+ // We almost always fail to delete he OSGi temp directory due to a concurrent modification.
+ // Therefore keep trying.
+ final AtomicReference<DeletionResult> deletionResult = new AtomicReference<DeletionResult>();
+ Repeater.create("Delete OSGi cache dir")
+ .until(new Callable<Boolean>() {
+ public Boolean call() {
+ deletionResult.set(Os.deleteRecursively(osgiCacheDir));
+ return deletionResult.get().wasSuccessful();
+ }})
+ .limitTimeTo(Duration.ONE_SECOND)
+ .backoffTo(Duration.millis(50))
+ .run();
+ if (deletionResult.get().getThrowable()!=null) {
+ log.debug("Unable to delete "+osgiCacheDir+" (possibly being modified concurrently?): "+deletionResult.get().getThrowable());
+ }
+ }
+ osgiCacheDir = null;
+ framework = null;
+ }
+
+ public synchronized void registerBundle(CatalogBundle bundle) {
+ try {
+ if (checkBundleInstalledThrowIfInconsistent(bundle)) {
+ return;
+ }
+
+ Bundle b = Osgis.install(framework, bundle.getUrl());
+
+ checkCorrectlyInstalled(bundle, b);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalStateException("Bundle from "+bundle.getUrl()+" failed to install: " + e.getMessage(), e);
+ }
+ }
+
+ private void checkCorrectlyInstalled(CatalogBundle bundle, Bundle b) {
+ String nv = b.getSymbolicName()+":"+b.getVersion().toString();
+
+ if (!isBundleNameEqualOrAbsent(bundle, b)) {
+ throw new IllegalStateException("Bundle already installed as "+nv+" but user explicitly requested "+bundle);
+ }
+
+ List<Bundle> matches = Osgis.bundleFinder(framework)
+ .symbolicName(b.getSymbolicName())
+ .version(b.getVersion().toString())
+ .findAll();
+ if (matches.isEmpty()) {
+ log.error("OSGi could not find bundle "+nv+" in search after installing it from "+bundle.getUrl());
+ } else if (matches.size()==1) {
+ log.debug("Bundle from "+bundle.getUrl()+" successfully installed as " + nv + " ("+b+")");
+ } else {
+ log.warn("OSGi has multiple bundles matching "+nv+", when just installed from "+bundle.getUrl()+": "+matches+"; "
+ + "brooklyn will prefer the URL-based bundle for top-level references but any dependencies or "
+ + "import-packages will be at the mercy of OSGi. "
+ + "It is recommended to use distinct versions for different bundles, and the same URL for the same bundles.");
+ }
+ }
+
+ private boolean checkBundleInstalledThrowIfInconsistent(CatalogBundle bundle) {
+ String bundleUrl = bundle.getUrl();
+ if (bundleUrl != null) {
+ Maybe<Bundle> installedBundle = Osgis.bundleFinder(framework).requiringFromUrl(bundleUrl).find();
+ if (installedBundle.isPresent()) {
+ Bundle b = installedBundle.get();
+ String nv = b.getSymbolicName()+":"+b.getVersion().toString();
+ if (!isBundleNameEqualOrAbsent(bundle, b)) {
+ throw new IllegalStateException("User requested bundle " + bundle + " but already installed as "+nv);
+ } else {
+ log.trace("Bundle from "+bundleUrl+" already installed as "+nv+"; not re-registering");
+ }
+ return true;
+ }
+ } else {
+ Maybe<Bundle> installedBundle = Osgis.bundleFinder(framework).symbolicName(bundle.getSymbolicName()).version(bundle.getVersion()).find();
+ if (installedBundle.isPresent()) {
+ log.trace("Bundle "+bundle+" installed from "+installedBundle.get().getLocation());
+ } else {
+ throw new IllegalStateException("Bundle "+bundle+" not previously registered, but URL is empty.");
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isBundleNameEqualOrAbsent(CatalogBundle bundle, Bundle b) {
+ return !bundle.isNamed() ||
+ (bundle.getSymbolicName().equals(b.getSymbolicName()) &&
+ bundle.getVersion().equals(b.getVersion().toString()));
+ }
+
+ public <T> Maybe<Class<T>> tryResolveClass(String type, CatalogBundle... catalogBundles) {
+ return tryResolveClass(type, Arrays.asList(catalogBundles));
+ }
+ public <T> Maybe<Class<T>> tryResolveClass(String type, Iterable<CatalogBundle> catalogBundles) {
+ Map<CatalogBundle,Throwable> bundleProblems = MutableMap.of();
+ Set<String> extraMessages = MutableSet.of();
+ for (CatalogBundle catalogBundle: catalogBundles) {
+ try {
+ Maybe<Bundle> bundle = findBundle(catalogBundle);
+ if (bundle.isPresent()) {
+ Bundle b = bundle.get();
+ Class<T> clazz;
+ //Extension bundles don't support loadClass.
+ //Instead load from the app classpath.
+ if (Osgis.isExtensionBundle(b)) {
+ @SuppressWarnings("unchecked")
+ Class<T> c = (Class<T>)Class.forName(type);
+ clazz = c;
+ } else {
+ @SuppressWarnings("unchecked")
+ Class<T> c = (Class<T>)b.loadClass(type);
+ clazz = c;
+ }
+ return Maybe.of(clazz);
+ } else {
+ bundleProblems.put(catalogBundle, ((Maybe.Absent<?>)bundle).getException());
+ }
+
+ } catch (Exception e) {
+ // should come from classloading now; name formatting or missing bundle errors will be caught above
+ Exceptions.propagateIfFatal(e);
+ bundleProblems.put(catalogBundle, e);
+
+ Throwable cause = e.getCause();
+ if (cause != null && cause.getMessage().contains("Unresolved constraint in bundle")) {
+ if (BrooklynVersion.INSTANCE.getVersionFromOsgiManifest()==null) {
+ extraMessages.add("No brooklyn-core OSGi manifest available. OSGi will not work.");
+ }
+ if (BrooklynVersion.isDevelopmentEnvironment()) {
+ extraMessages.add("Your development environment may not have created necessary files. Doing a maven build then retrying may fix the issue.");
+ }
+ if (!extraMessages.isEmpty()) log.warn(Strings.join(extraMessages, " "));
+ log.warn("Unresolved constraint resolving OSGi bundle "+catalogBundle+" to load "+type+": "+cause.getMessage());
+ if (log.isDebugEnabled()) log.debug("Trace for OSGi resolution failure", e);
+ }
+ }
+ }
+ if (bundleProblems.size()==1) {
+ Throwable error = Iterables.getOnlyElement(bundleProblems.values());
+ if (error instanceof ClassNotFoundException && error.getCause()!=null && error.getCause().getMessage()!=null) {
+ error = Exceptions.collapseIncludingAllCausalMessages(error);
+ }
+ return Maybe.absent("Unable to resolve class "+type+" in "+Iterables.getOnlyElement(bundleProblems.keySet())
+ + (extraMessages.isEmpty() ? "" : " ("+Strings.join(extraMessages, " ")+")"), error);
+ } else {
+ return Maybe.absent(Exceptions.create("Unable to resolve class "+type+": "+bundleProblems
+ + (extraMessages.isEmpty() ? "" : " ("+Strings.join(extraMessages, " ")+")"), bundleProblems.values()));
+ }
+ }
+
+ public Maybe<Bundle> findBundle(CatalogBundle catalogBundle) {
+ //Either fail at install time when the user supplied name:version is different
+ //from the one reported from the bundle
+ //or
+ //Ignore user supplied name:version when URL is supplied to be able to find the
+ //bundle even if it's with a different version.
+ //
+ //For now we just log a warning if there's a version discrepancy at install time,
+ //so prefer URL if supplied.
+ BundleFinder bundleFinder = Osgis.bundleFinder(framework);
+ if (catalogBundle.getUrl() != null) {
+ bundleFinder.requiringFromUrl(catalogBundle.getUrl());
+ } else {
+ bundleFinder.symbolicName(catalogBundle.getSymbolicName()).version(catalogBundle.getVersion());
+ }
+ return bundleFinder.find();
+ }
+
+ /**
+ * Iterates through catalogBundles until one contains a resource with the given name.
+ */
+ public URL getResource(String name, Iterable<CatalogBundle> catalogBundles) {
+ for (CatalogBundle catalogBundle: catalogBundles) {
+ try {
+ Maybe<Bundle> bundle = findBundle(catalogBundle);
+ if (bundle.isPresent()) {
+ URL result = bundle.get().getResource(name);
+ if (result!=null) return result;
+ }
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return An iterable of all resources matching name in catalogBundles.
+ */
+ public Iterable<URL> getResources(String name, Iterable<CatalogBundle> catalogBundles) {
+ List<URL> resources = Lists.newArrayList();
+ for (CatalogBundle catalogBundle : catalogBundles) {
+ try {
+ Maybe<Bundle> bundle = findBundle(catalogBundle);
+ if (bundle.isPresent()) {
+ Enumeration<URL> result = bundle.get().getResources(name);
+ resources.addAll(Collections.list(result));
+ }
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ }
+ }
+ return resources;
+ }
+
+ public Framework getFramework() {
+ return framework;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
new file mode 100644
index 0000000..1758846
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractManagementContext.java
@@ -0,0 +1,485 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.brooklyn.api.basic.BrooklynObject;
+import org.apache.brooklyn.api.catalog.BrooklynCatalog;
+import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.entity.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.drivers.EntityDriverManager;
+import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolverManager;
+import org.apache.brooklyn.api.entity.rebind.RebindManager;
+import org.apache.brooklyn.api.location.LocationRegistry;
+import org.apache.brooklyn.api.management.ExecutionContext;
+import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.api.management.SubscriptionContext;
+import org.apache.brooklyn.api.management.Task;
+import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.management.entitlement.EntitlementManager;
+import org.apache.brooklyn.api.management.ha.HighAvailabilityManager;
+import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.management.entitlement.Entitlements;
+import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
+
+import brooklyn.catalog.internal.BasicBrooklynCatalog;
+import brooklyn.catalog.internal.CatalogInitialization;
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.StringConfigMap;
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.drivers.BasicEntityDriverManager;
+import brooklyn.entity.drivers.downloads.BasicDownloadsManager;
+import brooklyn.entity.rebind.RebindManagerImpl;
+import brooklyn.internal.storage.BrooklynStorage;
+import brooklyn.internal.storage.DataGrid;
+import brooklyn.internal.storage.DataGridFactory;
+import brooklyn.internal.storage.impl.BrooklynStorageImpl;
+import brooklyn.internal.storage.impl.inmemory.InMemoryDataGridFactory;
+
+import org.apache.brooklyn.location.basic.BasicLocationRegistry;
+
+import brooklyn.util.GroovyJavaMethods;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.task.BasicExecutionContext;
+import brooklyn.util.task.Tasks;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractManagementContext implements ManagementContextInternal {
+ private static final Logger log = LoggerFactory.getLogger(AbstractManagementContext.class);
+
+ private static DataGridFactory loadDataGridFactory(BrooklynProperties properties) {
+ String clazzName = properties.getFirst(DataGridFactory.class.getName());
+ if(clazzName == null){
+ clazzName = InMemoryDataGridFactory.class.getName();
+ }
+
+ Class<?> clazz;
+ try{
+ //todo: which classloader should we use?
+ clazz = LocalManagementContext.class.getClassLoader().loadClass(clazzName);
+ }catch(ClassNotFoundException e){
+ throw new IllegalStateException(format("Could not load class [%s]",clazzName),e);
+ }
+
+ Object instance;
+ try {
+ instance = clazz.newInstance();
+ } catch (InstantiationException e) {
+ throw new IllegalStateException(format("Could not instantiate class [%s]",clazzName),e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(format("Could not instantiate class [%s]",clazzName),e);
+ }
+
+ if(!(instance instanceof DataGridFactory)){
+ throw new IllegalStateException(format("Class [%s] not an instantiate of class [%s]",clazzName, DataGridFactory.class.getName()));
+ }
+
+ return (DataGridFactory)instance;
+ }
+
+ static {
+ ResourceUtils.addClassLoaderProvider(new Function<Object, BrooklynClassLoadingContext>() {
+ @Override
+ public BrooklynClassLoadingContext apply(@Nullable Object input) {
+ if (input instanceof EntityInternal) {
+ EntityInternal internal = (EntityInternal)input;
+ if (internal.getCatalogItemId() != null) {
+ CatalogItem<?, ?> item = CatalogUtils.getCatalogItemOptionalVersion(internal.getManagementContext(), internal.getCatalogItemId());
+ if (item != null) {
+ return CatalogUtils.newClassLoadingContext(internal.getManagementContext(), item);
+ } else {
+ log.error("Can't find catalog item " + internal.getCatalogItemId() +
+ " used for instantiating entity " + internal +
+ ". Falling back to application classpath.");
+ }
+ }
+ return apply(internal.getManagementSupport());
+ }
+
+ if (input instanceof EntityManagementSupport)
+ return apply(((EntityManagementSupport)input).getManagementContext());
+ if (input instanceof ManagementContext)
+ return JavaBrooklynClassLoadingContext.create((ManagementContext) input);
+ return null;
+ }
+ });
+ }
+
+ private final AtomicLong totalEffectorInvocationCount = new AtomicLong();
+
+ protected BrooklynProperties configMap;
+ protected BasicLocationRegistry locationRegistry;
+ protected final BasicBrooklynCatalog catalog;
+ protected ClassLoader baseClassLoader;
+ protected Iterable<URL> baseClassPathForScanning;
+
+ private final RebindManager rebindManager;
+ private final HighAvailabilityManager highAvailabilityManager;
+
+ protected volatile BrooklynGarbageCollector gc;
+
+ private final EntityDriverManager entityDriverManager;
+ protected DownloadResolverManager downloadsManager;
+
+ protected EntitlementManager entitlementManager;
+
+ private final BrooklynStorage storage;
+
+ private volatile boolean running = true;
+ protected boolean startupComplete = false;
+ protected final List<Throwable> errors = Collections.synchronizedList(MutableList.<Throwable>of());
+
+ protected Maybe<URI> uri = Maybe.absent();
+ protected CatalogInitialization catalogInitialization;
+
+ public AbstractManagementContext(BrooklynProperties brooklynProperties){
+ this(brooklynProperties, null);
+ }
+
+ public AbstractManagementContext(BrooklynProperties brooklynProperties, DataGridFactory datagridFactory) {
+ this.configMap = brooklynProperties;
+ this.entityDriverManager = new BasicEntityDriverManager();
+ this.downloadsManager = BasicDownloadsManager.newDefault(configMap);
+ if (datagridFactory == null) {
+ datagridFactory = loadDataGridFactory(brooklynProperties);
+ }
+ DataGrid datagrid = datagridFactory.newDataGrid(this);
+
+ this.catalog = new BasicBrooklynCatalog(this);
+
+ this.storage = new BrooklynStorageImpl(datagrid);
+ this.rebindManager = new RebindManagerImpl(this); // TODO leaking "this" reference; yuck
+ this.highAvailabilityManager = new HighAvailabilityManagerImpl(this); // TODO leaking "this" reference; yuck
+
+ this.entitlementManager = Entitlements.newManager(this, brooklynProperties);
+ }
+
+ @Override
+ public void terminate() {
+ highAvailabilityManager.stop();
+ running = false;
+ rebindManager.stop();
+ storage.terminate();
+ // Don't unmanage everything; different entities get given their events at different times
+ // so can cause problems (e.g. a group finds out that a member is unmanaged, before the
+ // group itself has been told that it is unmanaged).
+ }
+
+ @Override
+ public boolean isRunning() {
+ return running;
+ }
+
+ @Override
+ public boolean isStartupComplete() {
+ return startupComplete;
+ }
+
+ @Override
+ public BrooklynStorage getStorage() {
+ return storage;
+ }
+
+ @Override
+ public RebindManager getRebindManager() {
+ return rebindManager;
+ }
+
+ @Override
+ public HighAvailabilityManager getHighAvailabilityManager() {
+ return highAvailabilityManager;
+ }
+
+ @Override
+ public long getTotalEffectorInvocations() {
+ return totalEffectorInvocationCount.get();
+ }
+
+ @Override
+ public ExecutionContext getExecutionContext(Entity e) {
+ // BEC is a thin wrapper around EM so fine to create a new one here; but make sure it gets the real entity
+ if (e instanceof AbstractEntity) {
+ return new BasicExecutionContext(MutableMap.of("tag", BrooklynTaskTags.tagForContextEntity(e)), getExecutionManager());
+ } else {
+ return ((EntityInternal)e).getManagementSupport().getExecutionContext();
+ }
+ }
+
+ @Override
+ public ExecutionContext getServerExecutionContext() {
+ // BEC is a thin wrapper around EM so fine to create a new one here
+ return new BasicExecutionContext(MutableMap.of("tag", BrooklynTaskTags.BROOKLYN_SERVER_TASK_TAG), getExecutionManager());
+ }
+
+ @Override
+ public SubscriptionContext getSubscriptionContext(Entity e) {
+ // BSC is a thin wrapper around SM so fine to create a new one here
+ return new BasicSubscriptionContext(getSubscriptionManager(), e);
+ }
+
+ @Override
+ public EntityDriverManager getEntityDriverManager() {
+ return entityDriverManager;
+ }
+
+ @Override
+ public DownloadResolverManager getEntityDownloadsManager() {
+ return downloadsManager;
+ }
+
+ @Override
+ public EntitlementManager getEntitlementManager() {
+ return entitlementManager;
+ }
+
+ protected abstract void manageIfNecessary(Entity entity, Object context);
+
+ @Override
+ public <T> Task<T> invokeEffector(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters) {
+ return runAtEntity(entity, eff, parameters);
+ }
+
+ protected <T> T invokeEffectorMethodLocal(Entity entity, Effector<T> eff, Object args) {
+ assert isManagedLocally(entity) : "cannot invoke effector method at "+this+" because it is not managed here";
+ totalEffectorInvocationCount.incrementAndGet();
+ Object[] transformedArgs = EffectorUtils.prepareArgsForEffector(eff, args);
+ return GroovyJavaMethods.invokeMethodOnMetaClass(entity, eff.getName(), transformedArgs);
+ }
+
+ /**
+ * Method for entity to make effector happen with correct semantics (right place, right task context),
+ * when a method is called on that entity.
+ * @throws ExecutionException
+ */
+ @Override
+ public <T> T invokeEffectorMethodSync(final Entity entity, final Effector<T> eff, final Object args) throws ExecutionException {
+ try {
+ Task<?> current = Tasks.current();
+ if (current == null || !entity.equals(BrooklynTaskTags.getContextEntity(current)) || !isManagedLocally(entity)) {
+ manageIfNecessary(entity, eff.getName());
+ // Wrap in a task if we aren't already in a task that is tagged with this entity
+ Task<T> task = runAtEntity( EffectorUtils.getTaskFlagsForEffectorInvocation(entity, eff,
+ ConfigBag.newInstance().configureStringKey("args", args)),
+ entity,
+ new Callable<T>() {
+ public T call() {
+ return invokeEffectorMethodLocal(entity, eff, args);
+ }});
+ return task.get();
+ } else {
+ return invokeEffectorMethodLocal(entity, eff, args);
+ }
+ } catch (Exception e) {
+ // don't need to attach any message or warning because the Effector impl hierarchy does that (see calls to EffectorUtils.handleException)
+ throw new ExecutionException(e);
+ }
+ }
+
+ /**
+ * Whether the master entity record is local, and sensors and effectors can be properly accessed locally.
+ */
+ public abstract boolean isManagedLocally(Entity e);
+
+ /**
+ * Causes the indicated runnable to be run at the right location for the given entity.
+ *
+ * Returns the actual task (if it is local) or a proxy task (if it is remote);
+ * if management for the entity has not yet started this may start it.
+ *
+ * @deprecated since 0.6.0 use effectors (or support {@code runAtEntity(Entity, Effector, Map)} if something else is needed);
+ * (Callable with Map flags is too open-ended, bothersome to support, and not used much)
+ */
+ @Deprecated
+ public abstract <T> Task<T> runAtEntity(@SuppressWarnings("rawtypes") Map flags, Entity entity, Callable<T> c);
+
+ /** Runs the given effector in the right place for the given entity.
+ * The task is immediately submitted in the background, but also recorded in the queueing context (if present)
+ * so it appears as a child, but marked inessential so it does not fail the parent task, who will ordinarily
+ * call {@link Task#get()} on the object and may do their own failure handling.
+ */
+ protected abstract <T> Task<T> runAtEntity(final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters);
+
+ @Override
+ public StringConfigMap getConfig() {
+ return configMap;
+ }
+
+ @Override
+ public BrooklynProperties getBrooklynProperties() {
+ return configMap;
+ }
+
+ @Override
+ public synchronized LocationRegistry getLocationRegistry() {
+ if (locationRegistry==null) locationRegistry = new BasicLocationRegistry(this);
+ return locationRegistry;
+ }
+
+ @Override
+ public BrooklynCatalog getCatalog() {
+ if (!getCatalogInitialization().hasRunAnyInitialization()) {
+ // catalog init is needed; normally this will be done from start sequence,
+ // but if accessed early -- and in tests -- we will load it here
+ getCatalogInitialization().injectManagementContext(this);
+ getCatalogInitialization().populateUnofficial(catalog);
+ }
+ return catalog;
+ }
+
+ @Override
+ public ClassLoader getCatalogClassLoader() {
+ // catalog does not have to be initialized
+ return catalog.getRootClassLoader();
+ }
+
+ /**
+ * Optional class-loader that this management context should use as its base,
+ * as the first-resort in the catalog, and for scanning (if scanning the default in the catalog).
+ * In most instances the default classloader (ManagementContext.class.getClassLoader(), assuming
+ * this was in the JARs used at boot time) is fine, and in those cases this method normally returns null.
+ * (Surefire does some weird stuff, but the default classloader is fine for loading;
+ * however it requires a custom base classpath to be set for scanning.)
+ */
+ @Override
+ public ClassLoader getBaseClassLoader() {
+ return baseClassLoader;
+ }
+
+ /** See {@link #getBaseClassLoader()}. Only settable once and must be invoked before catalog is loaded. */
+ public void setBaseClassLoader(ClassLoader cl) {
+ if (baseClassLoader==cl) return;
+ if (baseClassLoader!=null) throw new IllegalStateException("Cannot change base class loader (in "+this+")");
+ if (catalog!=null) throw new IllegalStateException("Cannot set base class after catalog has been loaded (in "+this+")");
+ this.baseClassLoader = cl;
+ }
+
+ /** Optional mechanism for setting the classpath which should be scanned by the catalog, if the catalog
+ * is scanning the default classpath. Usually it infers the right thing, but some classloaders
+ * (e.g. surefire) do funny things which the underlying org.reflections.Reflections library can't see in to.
+ * <p>
+ * This should normally be invoked early in the server startup. Setting it after the catalog is loaded will not
+ * take effect without an explicit internal call to do so. Once set, it can be changed prior to catalog loading
+ * but it cannot be <i>changed</i> once the catalog is loaded.
+ * <p>
+ * ClasspathHelper.forJavaClassPath() is often a good argument to pass, and is used internally in some places
+ * when no items are found on the catalog. */
+ @Override
+ public void setBaseClassPathForScanning(Iterable<URL> urls) {
+ if (Objects.equal(baseClassPathForScanning, urls)) return;
+ if (baseClassPathForScanning != null) {
+ if (catalog==null)
+ log.warn("Changing scan classpath to "+urls+" from "+baseClassPathForScanning);
+ else
+ throw new IllegalStateException("Cannot change base class path for scanning (in "+this+")");
+ }
+ this.baseClassPathForScanning = urls;
+ }
+ /**
+ * @see #setBaseClassPathForScanning(Iterable)
+ */
+ @Override
+ public Iterable<URL> getBaseClassPathForScanning() {
+ return baseClassPathForScanning;
+ }
+
+ public BrooklynGarbageCollector getGarbageCollector() {
+ return gc;
+ }
+
+ @Override
+ public void setManagementNodeUri(URI uri) {
+ this.uri = Maybe.of(checkNotNull(uri, "uri"));
+ }
+
+ @Override
+ public Maybe<URI> getManagementNodeUri() {
+ return uri;
+ }
+
+ private Object catalogInitMutex = new Object();
+ @Override
+ public CatalogInitialization getCatalogInitialization() {
+ synchronized (catalogInitMutex) {
+ if (catalogInitialization!=null) return catalogInitialization;
+ CatalogInitialization ci = new CatalogInitialization();
+ setCatalogInitialization(ci);
+ return ci;
+ }
+ }
+
+ @Override
+ public void setCatalogInitialization(CatalogInitialization catalogInitialization) {
+ synchronized (catalogInitMutex) {
+ Preconditions.checkNotNull(catalogInitialization, "initialization must not be null");
+ if (this.catalogInitialization!=null && this.catalogInitialization != catalogInitialization)
+ throw new IllegalStateException("Changing catalog init from "+this.catalogInitialization+" to "+catalogInitialization+"; changes not permitted");
+ catalogInitialization.injectManagementContext(this);
+ this.catalogInitialization = catalogInitialization;
+ }
+ }
+
+ public BrooklynObject lookup(String id) {
+ return lookup(id, BrooklynObject.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends BrooklynObject> T lookup(String id, Class<T> type) {
+ Object result;
+ result = getEntityManager().getEntity(id);
+ if (result!=null && type.isInstance(result)) return (T)result;
+
+ result = getLocationManager().getLocation(id);
+ if (result!=null && type.isInstance(result)) return (T)result;
+
+ // TODO policies, enrichers, feeds
+ return null;
+ }
+
+ @Override
+ public List<Throwable> errors() {
+ return errors;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractSubscriptionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractSubscriptionManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractSubscriptionManager.java
new file mode 100644
index 0000000..bec041d
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/AbstractSubscriptionManager.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+import org.apache.brooklyn.api.management.SubscriptionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+
+public abstract class AbstractSubscriptionManager implements SubscriptionManager {
+
+ // TODO Perhaps could use guava's SynchronizedSetMultimap? But need to check its synchronization guarantees.
+ // That would replace the utils used for subscriptionsBySubscriber etc.
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractSubscriptionManager.class);
+
+ /** performs the actual subscription; should return the subscription parameter as the handle */
+ protected abstract <T> SubscriptionHandle subscribe(Map<String, Object> flags, Subscription<T> s);
+ /** performs the actual publishing -- ie distribution to subscriptions */
+ public abstract <T> void publish(final SensorEvent<T> event);
+
+ public static class EntitySensorToken {
+ Entity e;
+ Sensor<?> s;
+ String sName;
+ public EntitySensorToken(Entity e, Sensor<?> s) {
+ this.e = e;
+ this.s = s;
+ this.sName = (s == null) ? null : checkNotNull(s.getName(), "sensor must have non-null name: %s", s);
+ }
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(e, sName);
+ }
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof EntitySensorToken)) return false;
+ if (!Objects.equal(e, ((EntitySensorToken)obj).e)) return false;
+ if (!Objects.equal(sName, ((EntitySensorToken)obj).sName)) return false;
+ return true;
+ }
+ @Override
+ public String toString() {
+ return (e != null ? e.getId() : "*")+":"+(s != null ? sName : "*");
+ }
+ }
+ static Object makeEntitySensorToken(Entity e, Sensor<?> s) {
+ return new EntitySensorToken(e, s);
+ }
+ static Object makeEntitySensorToken(SensorEvent<?> se) {
+ return makeEntitySensorToken(se.getSource(), se.getSensor());
+ }
+
+ /** @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener) */
+ public final <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ return subscribe(Collections.<String,Object>emptyMap(), producer, sensor, listener);
+ }
+
+ /**
+ * This implementation handles the following flags, in addition to those described in the {@link SubscriptionManager}
+ * interface:
+ * <ul>
+ * <li>subscriberExecutionManagerTag - a tag to pass to execution manager (without setting any execution semantics / TaskPreprocessor);
+ * if not supplied and there is a subscriber, this will be inferred from the subscriber and set up with SingleThreadedScheduler
+ * <li>eventFilter - a Predicate<SensorEvent> instance to filter what events are delivered
+ * </ul>
+ *
+ * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener)
+ */
+ public final <T> SubscriptionHandle subscribe(Map<String, Object> flags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ return subscribe(flags, new Subscription<T>(producer, sensor, listener));
+ }
+
+ /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
+ public final <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ return subscribeToChildren(Collections.<String,Object>emptyMap(), parent, sensor, listener);
+ }
+
+ /** @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener) */
+ public final <T> SubscriptionHandle subscribeToChildren(Map<String, Object> flags, final Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ Predicate<SensorEvent<T>> eventFilter = new Predicate<SensorEvent<T>>() {
+ public boolean apply(SensorEvent<T> input) {
+ return parent != null && input.getSource() != null && parent.equals(input.getSource().getParent());
+ }
+ };
+ flags.put("eventFilter", eventFilter);
+ return subscribe(flags, null, sensor, listener);
+ }
+
+ /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */
+ public final <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ return subscribeToMembers(Collections.<String,Object>emptyMap(), parent, sensor, listener);
+ }
+
+ /** @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener) */
+ public final <T> SubscriptionHandle subscribeToMembers(Map<String, Object> flags, final Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ Predicate<SensorEvent<T>> eventFilter = new Predicate<SensorEvent<T>>() {
+ public boolean apply(SensorEvent<T> input) {
+ return parent.getMembers().contains(input.getSource());
+ }
+ };
+ flags.put("eventFilter", eventFilter);
+ return subscribe(flags, null, sensor, listener);
+ }
+
+ protected <T> Object getSubscriber(Map<String, Object> flags, Subscription<T> s) {
+ return s.subscriber!=null ? s.subscriber : flags.containsKey("subscriber") ? flags.remove("subscriber") : s.listener;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/AccessManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/AccessManager.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/AccessManager.java
new file mode 100644
index 0000000..5d6a057
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/AccessManager.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import org.apache.brooklyn.api.management.AccessController;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public interface AccessManager {
+
+ AccessController getAccessController();
+
+ boolean isLocationProvisioningAllowed();
+
+ boolean isLocationManagementAllowed();
+
+ boolean isEntityManagementAllowed();
+
+ void setLocationProvisioningAllowed(boolean allowed);
+
+ void setLocationManagementAllowed(boolean allowed);
+
+ void setEntityManagementAllowed(boolean allowed);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java
new file mode 100644
index 0000000..038ec90
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/AsyncCollectionChangeAdapter.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.apache.brooklyn.api.management.ExecutionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.task.BasicExecutionManager;
+import brooklyn.util.task.SingleThreadedScheduler;
+
+public class AsyncCollectionChangeAdapter<Item> implements CollectionChangeListener<Item> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AsyncCollectionChangeAdapter.class);
+
+ private final ExecutionManager executor;
+ private final CollectionChangeListener<Item> delegate;
+
+ public AsyncCollectionChangeAdapter(ExecutionManager executor, CollectionChangeListener<Item> delegate) {
+ this.executor = checkNotNull(executor, "executor");
+ this.delegate = checkNotNull(delegate, "delegate");
+ ((BasicExecutionManager) executor).setTaskSchedulerForTag(delegate, SingleThreadedScheduler.class);
+ }
+
+ @Override
+ public void onItemAdded(final Item item) {
+ executor.submit(MutableMap.of("tag", delegate), new Runnable() {
+ public void run() {
+ try {
+ delegate.onItemAdded(item);
+ } catch (Throwable t) {
+ LOG.warn("Error notifying listener of itemAdded("+item+")", t);
+ Exceptions.propagate(t);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onItemRemoved(final Item item) {
+ executor.submit(MutableMap.of("tag", delegate), new Runnable() {
+ public void run() {
+ try {
+ delegate.onItemRemoved(item);
+ } catch (Throwable t) {
+ LOG.warn("Error notifying listener of itemAdded("+item+")", t);
+ Exceptions.propagate(t);
+ }
+ }
+ });
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return (other instanceof AsyncCollectionChangeAdapter) &&
+ delegate.equals(((AsyncCollectionChangeAdapter<?>) other).delegate);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/BasicSubscriptionContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/BasicSubscriptionContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/BasicSubscriptionContext.java
new file mode 100644
index 0000000..04aa18f
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/BasicSubscriptionContext.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import static brooklyn.util.JavaGroovyEquivalents.mapOf;
+import groovy.lang.Closure;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.Group;
+import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.api.event.SensorEvent;
+import org.apache.brooklyn.api.event.SensorEventListener;
+import org.apache.brooklyn.api.management.SubscriptionContext;
+import org.apache.brooklyn.api.management.SubscriptionHandle;
+import org.apache.brooklyn.api.management.SubscriptionManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+/**
+ * A {@link SubscriptionContext} for an entity or other user of a {@link SubscriptionManager}.
+ */
+public class BasicSubscriptionContext implements SubscriptionContext {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BasicSubscriptionContext.class);
+
+ private final SubscriptionManager manager;
+ private final Object subscriber;
+ private final Map<String,Object> flags;
+
+ public BasicSubscriptionContext(SubscriptionManager manager, Object subscriber) {
+ this(Collections.<String,Object>emptyMap(), manager, subscriber);
+ }
+
+ public BasicSubscriptionContext(Map<String, ?> flags, SubscriptionManager manager, Object subscriber) {
+ this.manager = manager;
+ this.subscriber = subscriber;
+ this.flags = mapOf("subscriber", subscriber);
+ if (flags!=null) this.flags.putAll(flags);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, Closure c) {
+ return subscribe(Collections.<String,Object>emptyMap(), producer, sensor, c);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public <T> SubscriptionHandle subscribe(Map<String, Object> newFlags, Entity producer, Sensor<T> sensor, Closure c) {
+ return subscribe(newFlags, producer, sensor, toSensorEventListener(c));
+ }
+
+ @Override
+ public <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ return subscribe(Collections.<String,Object>emptyMap(), producer, sensor, listener);
+ }
+
+ @Override
+ public <T> SubscriptionHandle subscribe(Map<String, Object> newFlags, Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ Map<String,Object> subscriptionFlags = Maps.newLinkedHashMap(flags);
+ if (newFlags != null) subscriptionFlags.putAll(newFlags);
+ return manager.subscribe(subscriptionFlags, producer, sensor, listener);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, Closure c) {
+ return subscribeToChildren(Collections.<String,Object>emptyMap(), parent, sensor, c);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public <T> SubscriptionHandle subscribeToChildren(Map<String, Object> newFlags, Entity parent, Sensor<T> sensor, Closure c) {
+ return subscribeToChildren(newFlags, parent, sensor, toSensorEventListener(c));
+ }
+
+ @Override
+ public <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ return subscribeToChildren(Collections.<String,Object>emptyMap(), parent, sensor, listener);
+ }
+
+ @Override
+ public <T> SubscriptionHandle subscribeToChildren(Map<String, Object> newFlags, Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ Map<String,Object> subscriptionFlags = Maps.newLinkedHashMap(flags);
+ if (newFlags != null) subscriptionFlags.putAll(newFlags);
+ return manager.subscribeToChildren(subscriptionFlags, parent, sensor, listener);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, Closure c) {
+ return subscribeToMembers(Collections.<String,Object>emptyMap(), parent, sensor, c);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public <T> SubscriptionHandle subscribeToMembers(Map<String, Object> newFlags, Group parent, Sensor<T> sensor, Closure c) {
+ return subscribeToMembers(newFlags, parent, sensor, toSensorEventListener(c));
+ }
+
+ @Override
+ public <T> SubscriptionHandle subscribeToMembers(Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ return subscribeToMembers(Collections.<String,Object>emptyMap(), parent, sensor, listener);
+ }
+
+ @Override
+ public <T> SubscriptionHandle subscribeToMembers(Map<String, Object> newFlags, Group parent, Sensor<T> sensor, SensorEventListener<? super T> listener) {
+ Map<String,Object> subscriptionFlags = Maps.newLinkedHashMap(flags);
+ if (newFlags != null) subscriptionFlags.putAll(newFlags);
+ return manager.subscribeToMembers(subscriptionFlags, parent, sensor, listener);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public boolean unsubscribe(SubscriptionHandle subscriptionId) {
+ Preconditions.checkNotNull(subscriptionId, "subscriptionId must not be null");
+ Preconditions.checkArgument(Objects.equal(subscriber, ((Subscription) subscriptionId).subscriber), "The subscriptionId is for a different "+subscriber+"; expected "+((Subscription) subscriptionId).subscriber);
+ return manager.unsubscribe(subscriptionId);
+ }
+
+ /** @see SubscriptionManager#publish(SensorEvent) */
+ @Override
+ public <T> void publish(SensorEvent<T> event) {
+ manager.publish(event);
+ }
+
+ /** Return the subscriptions associated with this context */
+ @Override
+ public Set<SubscriptionHandle> getSubscriptions() {
+ return manager.getSubscriptionsForSubscriber(subscriber);
+ }
+
+ @Override
+ public int unsubscribeAll() {
+ int count = 0;
+
+ // To avoid ConcurrentModificationException when copying subscriptions, need to synchronize on it
+ Set<SubscriptionHandle> subscriptions = getSubscriptions();
+ Collection<SubscriptionHandle> subscriptionsCopy;
+ synchronized (subscriptions) {
+ subscriptionsCopy = ImmutableList.copyOf(subscriptions);
+ }
+
+ for (SubscriptionHandle s : subscriptionsCopy) {
+ count++;
+ boolean result = unsubscribe(s);
+ if (!result) LOG.warn("When unsubscribing from all of {}, unsubscribe of {} return false", subscriber, s);
+ }
+ return count;
+ }
+
+ @SuppressWarnings("rawtypes")
+ private <T> SensorEventListener<T> toSensorEventListener(final Closure c) {
+ return new SensorEventListener<T>() {
+ @Override public void onEvent(SensorEvent<T> event) {
+ c.call(event);
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java
new file mode 100644
index 0000000..c02ff81
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynGarbageCollector.java
@@ -0,0 +1,626 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.management.HasTaskChildren;
+import org.apache.brooklyn.api.management.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.BrooklynTaskTags.WrappedEntity;
+import brooklyn.entity.basic.BrooklynTaskTags.WrappedStream;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.internal.storage.BrooklynStorage;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.javalang.MemoryUsageTracker;
+import brooklyn.util.task.BasicExecutionManager;
+import brooklyn.util.task.ExecutionListener;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Objects;
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Iterables;
+
+/**
+ * Deletes record of old tasks, to prevent space leaks and the eating up of more and more memory.
+ *
+ * The deletion policy is configurable:
+ * <ul>
+ * <li>Period - how frequently to look at the existing tasks to delete some, if required
+ * <li>Max task age - the time after which a completed task will be automatically deleted
+ * (i.e. any root task completed more than maxTaskAge ago will be deleted)
+ * <li>Max tasks per <various categories> - the maximum number of tasks to be kept for a given tag,
+ * split into categories based on what is seeming to be useful
+ * </ul>
+ *
+ * The default is to check with a period of one minute, deleting tasks after 30 days,
+ * and keeping at most 100000 tasks in the system,
+ * max 1000 tasks per entity, 50 per effector within that entity, and 50 per other non-effector tag
+ * within that entity (or global if not attached to an entity).
+ *
+ * @author aled
+ */
+public class BrooklynGarbageCollector {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BrooklynGarbageCollector.class);
+
+ public static final ConfigKey<Duration> GC_PERIOD = ConfigKeys.newDurationConfigKey(
+ "brooklyn.gc.period", "the period for checking if any tasks need to be deleted",
+ Duration.minutes(1));
+
+ public static final ConfigKey<Boolean> DO_SYSTEM_GC = ConfigKeys.newBooleanConfigKey(
+ "brooklyn.gc.doSystemGc", "whether to periodically call System.gc()", false);
+
+ /**
+ * should we check for tasks which are submitted by another but backgrounded, i.e. not a child of that task?
+ * default to yes, despite it can be some extra loops, to make sure we GC them promptly.
+ * @since 0.7.0 */
+ // work offender is {@link DynamicSequentialTask} internal job tracker, but it is marked
+ // transient so it is destroyed prompty; there may be others, however;
+ // but OTOH it might be expensive to check for these all the time!
+ // TODO probably we can set this false (remove this and related code),
+ // and just rely on usual GC to pick up background tasks; the lifecycle of background task
+ // should normally be independent of the submitter. (DST was the exception, and marking
+ // transient there fixes the main problem, which is when the submitter is GC'd but the submitted is not,
+ // and we don't want the submitted to show up at the root in the GUI, which it will if its
+ // submitter has been GC'd)
+ @Beta
+ public static final ConfigKey<Boolean> CHECK_SUBTASK_SUBMITTERS = ConfigKeys.newBooleanConfigKey(
+ "brooklyn.gc.checkSubtaskSubmitters", "whether for subtasks to check the submitters", true);
+
+ public static final ConfigKey<Integer> MAX_TASKS_PER_TAG = ConfigKeys.newIntegerConfigKey(
+ "brooklyn.gc.maxTasksPerTag",
+ "the maximum number of tasks to be kept for a given tag "
+ + "within an execution context (e.g. entity); "
+ + "some broad-brush tags are excluded, and if an entity has multiple tags all tag counts must be full",
+ 50);
+
+ public static final ConfigKey<Integer> MAX_TASKS_PER_ENTITY = ConfigKeys.newIntegerConfigKey(
+ "brooklyn.gc.maxTasksPerEntity",
+ "the maximum number of tasks to be kept for a given entity",
+ 1000);
+
+ public static final ConfigKey<Integer> MAX_TASKS_GLOBAL = ConfigKeys.newIntegerConfigKey(
+ "brooklyn.gc.maxTasksGlobal",
+ "the maximum number of tasks to be kept across the entire system",
+ 100000);
+
+ public static final ConfigKey<Duration> MAX_TASK_AGE = ConfigKeys.newDurationConfigKey(
+ "brooklyn.gc.maxTaskAge",
+ "the duration after which a completed task will be automatically deleted",
+ Duration.days(30));
+
+ protected final static Comparator<Task<?>> TASKS_OLDEST_FIRST_COMPARATOR = new Comparator<Task<?>>() {
+ @Override public int compare(Task<?> t1, Task<?> t2) {
+ long end1 = t1.getEndTimeUtc();
+ long end2 = t2.getEndTimeUtc();
+ return (end1 < end2) ? -1 : ((end1 == end2) ? 0 : 1);
+ }
+ };
+
+ private final BasicExecutionManager executionManager;
+ private final BrooklynStorage storage;
+ private final BrooklynProperties brooklynProperties;
+ private final ScheduledExecutorService executor;
+ private ScheduledFuture<?> activeCollector;
+ private Map<Entity,Task<?>> unmanagedEntitiesNeedingGc = new LinkedHashMap<Entity, Task<?>>();
+
+ private Duration gcPeriod;
+ private final boolean doSystemGc;
+ private volatile boolean running = true;
+
+ public BrooklynGarbageCollector(BrooklynProperties brooklynProperties, BasicExecutionManager executionManager, BrooklynStorage storage) {
+ this.executionManager = executionManager;
+ this.storage = storage;
+ this.brooklynProperties = brooklynProperties;
+
+ doSystemGc = brooklynProperties.getConfig(DO_SYSTEM_GC);
+
+ executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+ @Override public Thread newThread(Runnable r) {
+ return new Thread(r, "brooklyn-gc");
+ }});
+
+ executionManager.addListener(new ExecutionListener() {
+ @Override public void onTaskDone(Task<?> task) {
+ BrooklynGarbageCollector.this.onTaskDone(task);
+ }});
+
+ scheduleCollector(true);
+ }
+
+ protected synchronized void scheduleCollector(boolean canInterruptCurrent) {
+ if (activeCollector != null) activeCollector.cancel(canInterruptCurrent);
+
+ gcPeriod = brooklynProperties.getConfig(GC_PERIOD);
+ if (gcPeriod!=null) {
+ activeCollector = executor.scheduleWithFixedDelay(
+ new Runnable() {
+ @Override public void run() {
+ gcIteration();
+ }
+ },
+ gcPeriod.toMillisecondsRoundingUp(),
+ gcPeriod.toMillisecondsRoundingUp(),
+ TimeUnit.MILLISECONDS);
+ }
+ }
+
+ /** force a round of Brooklyn garbage collection */
+ public void gcIteration() {
+ try {
+ logUsage("brooklyn gc (before)");
+ gcTasks();
+ logUsage("brooklyn gc (after)");
+
+ if (doSystemGc) {
+ // Can be very useful when tracking down OOMEs etc, where a lot of tasks are executing
+ // Empirically observed that (on OS X jvm at least) calling twice blocks - logs a significant
+ // amount of memory having been released, as though a full-gc had been run. But this is highly
+ // dependent on the JVM implementation.
+ System.gc(); System.gc();
+ logUsage("brooklyn gc (after system gc)");
+ }
+ } catch (Throwable t) {
+ Exceptions.propagateIfFatal(t);
+ LOG.warn("Error during management-context GC: "+t, t);
+ // previously we bailed on all errors, but I don't think we should do that -Alex
+ }
+ }
+
+ public void logUsage(String prefix) {
+ if (LOG.isDebugEnabled())
+ LOG.debug(prefix+" - using "+getUsageString());
+ }
+
+ public static String makeBasicUsageString() {
+ return Strings.makeSizeString(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())+" / "+
+ Strings.makeSizeString(Runtime.getRuntime().totalMemory()) + " memory" +
+ " ("+Strings.makeSizeString(MemoryUsageTracker.SOFT_REFERENCES.getBytesUsed()) + " soft); "+
+ Thread.activeCount()+" threads";
+ }
+
+ public String getUsageString() {
+ return makeBasicUsageString()+"; "+
+ "storage: " + storage.getStorageMetrics() + "; " +
+ "tasks: " +
+ executionManager.getNumActiveTasks()+" active, "+
+ executionManager.getNumIncompleteTasks()+" unfinished; "+
+ executionManager.getNumInMemoryTasks()+" remembered, "+
+ executionManager.getTotalTasksSubmitted()+" total submitted)";
+ }
+
+ public void shutdownNow() {
+ running = false;
+ if (activeCollector != null) activeCollector.cancel(true);
+ if (executor != null) executor.shutdownNow();
+ }
+
+ public void onUnmanaged(Entity entity) {
+ // defer task deletions until the entity is completely unmanaged
+ // (this is usually invoked during the stop sequence)
+ synchronized (unmanagedEntitiesNeedingGc) {
+ unmanagedEntitiesNeedingGc.put(entity, Tasks.current());
+ }
+ }
+
+ public void deleteTasksForEntity(Entity entity) {
+ // remove all references to this entity from tasks
+ executionManager.deleteTag(entity);
+ executionManager.deleteTag(BrooklynTaskTags.tagForContextEntity(entity));
+ executionManager.deleteTag(BrooklynTaskTags.tagForCallerEntity(entity));
+ executionManager.deleteTag(BrooklynTaskTags.tagForTargetEntity(entity));
+ }
+
+ public void onUnmanaged(Location loc) {
+ // No-op currently; no tasks are tracked through their location
+ }
+
+ public void onTaskDone(Task<?> task) {
+ if (shouldDeleteTaskImmediately(task)) {
+ executionManager.deleteTask(task);
+ }
+ }
+
+ /** @deprecated since 0.7.0, method moved internal until semantics are clarified; see also {@link #shouldDeleteTaskImmediately(Task)} */
+ @Deprecated
+ public boolean shouldDeleteTask(Task<?> task) {
+ return shouldDeleteTaskImmediately(task);
+ }
+ /** whether this task should be deleted on completion,
+ * because it is transient, or because it is submitted background without much context information */
+ protected boolean shouldDeleteTaskImmediately(Task<?> task) {
+ if (!task.isDone()) return false;
+
+ Set<Object> tags = task.getTags();
+ if (tags.contains(ManagementContextInternal.TRANSIENT_TASK_TAG))
+ return true;
+ if (tags.contains(ManagementContextInternal.EFFECTOR_TAG) || tags.contains(ManagementContextInternal.NON_TRANSIENT_TASK_TAG))
+ return false;
+
+ if (task.getSubmittedByTask()!=null) {
+ Task<?> parent = task.getSubmittedByTask();
+ if (executionManager.getTask(parent.getId())==null) {
+ // parent is already cleaned up
+ return true;
+ }
+ if (parent instanceof HasTaskChildren && Iterables.contains(((HasTaskChildren)parent).getChildren(), task)) {
+ // it is a child, let the parent manage this task's death
+ return false;
+ }
+ Entity associatedEntity = BrooklynTaskTags.getTargetOrContextEntity(task);
+ if (associatedEntity!=null) {
+ // this is associated to an entity; destroy only if the entity is unmanaged
+ return !Entities.isManaged(associatedEntity);
+ }
+ // if not associated to an entity, then delete immediately
+ return true;
+ }
+
+ // e.g. scheduled tasks, sensor events, etc
+ // TODO (in future may keep some of these with another limit, based on a new TagCategory)
+ // there may also be a server association for server-side tasks which should be kept
+ // (but be careful not to keep too many subscriptions!)
+
+ return true;
+ }
+
+ /**
+ * Deletes old tasks. The age/number of tasks to keep is controlled by fields like
+ * {@link #maxTasksPerTag} and {@link #maxTaskAge}.
+ */
+ protected synchronized int gcTasks() {
+ // TODO Must be careful with memory usage here: have seen OOME if we get crazy lots of tasks.
+ // hopefully the use new limits, filters, and use of live lists in some places (added Sep 2014) will help.
+ //
+ // An option is for getTasksWithTag(tag) to return an ArrayList rather than a LinkedHashSet. That
+ // is a far more memory efficient data structure (e.g. 4 bytes overhead per object rather than
+ // 32 bytes overhead per object for HashSet).
+ //
+ // More notes on optimization is in the history of this file.
+
+ if (!running) return 0;
+
+ Duration newPeriod = brooklynProperties.getConfig(GC_PERIOD);
+ if (!Objects.equal(gcPeriod, newPeriod)) {
+ // caller has changed period, reschedule on next run
+ scheduleCollector(false);
+ }
+
+ expireUnmanagedEntityTasks();
+ expireAgedTasks();
+ expireTransientTasks();
+
+ // now look at overcapacity tags, non-entity tags first
+
+ Set<Object> taskTags = executionManager.getTaskTags();
+
+ int maxTasksPerEntity = brooklynProperties.getConfig(MAX_TASKS_PER_ENTITY);
+ int maxTasksPerTag = brooklynProperties.getConfig(MAX_TASKS_PER_TAG);
+
+ Map<Object,AtomicInteger> taskNonEntityTagsOverCapacity = MutableMap.of();
+ Map<Object,AtomicInteger> taskEntityTagsOverCapacity = MutableMap.of();
+
+ Map<Object,AtomicInteger> taskAllTagsOverCapacity = MutableMap.of();
+
+ for (Object tag : taskTags) {
+ if (isTagIgnoredForGc(tag)) continue;
+
+ Set<Task<?>> tasksWithTag = executionManager.tasksWithTagLiveOrNull(tag);
+ if (tasksWithTag==null) continue;
+ AtomicInteger overA = null;
+ if (tag instanceof WrappedEntity) {
+ int over = tasksWithTag.size() - maxTasksPerEntity;
+ if (over>0) {
+ overA = new AtomicInteger(over);
+ taskEntityTagsOverCapacity.put(tag, overA);
+ }
+ } else {
+ int over = tasksWithTag.size() - maxTasksPerTag;
+ if (over>0) {
+ overA = new AtomicInteger(over);
+ taskNonEntityTagsOverCapacity.put(tag, overA);
+ }
+ }
+ if (overA!=null) {
+ taskAllTagsOverCapacity.put(tag, overA);
+ }
+ }
+
+ int deletedCount = 0;
+ deletedCount += expireOverCapacityTagsInCategory(taskNonEntityTagsOverCapacity, taskAllTagsOverCapacity, TagCategory.NON_ENTITY_NORMAL, false);
+ deletedCount += expireOverCapacityTagsInCategory(taskEntityTagsOverCapacity, taskAllTagsOverCapacity, TagCategory.ENTITY, true);
+ deletedCount += expireSubTasksWhoseSubmitterIsExpired();
+
+ int deletedGlobally = expireIfOverCapacityGlobally();
+ deletedCount += deletedGlobally;
+ if (deletedGlobally>0) deletedCount += expireSubTasksWhoseSubmitterIsExpired();
+
+ return deletedCount;
+ }
+
+ protected static boolean isTagIgnoredForGc(Object tag) {
+ if (tag == null) return true;
+ if (tag.equals(ManagementContextInternal.EFFECTOR_TAG)) return true;
+ if (tag.equals(ManagementContextInternal.SUB_TASK_TAG)) return true;
+ if (tag.equals(ManagementContextInternal.NON_TRANSIENT_TASK_TAG)) return true;
+ if (tag.equals(ManagementContextInternal.TRANSIENT_TASK_TAG)) return true;
+ if (tag instanceof WrappedStream) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected void expireUnmanagedEntityTasks() {
+ Iterator<Entry<Entity, Task<?>>> ei;
+ synchronized (unmanagedEntitiesNeedingGc) {
+ ei = MutableSet.copyOf(unmanagedEntitiesNeedingGc.entrySet()).iterator();
+ }
+ while (ei.hasNext()) {
+ Entry<Entity, Task<?>> ee = ei.next();
+ if (Entities.isManaged(ee.getKey())) continue;
+ if (ee.getValue()!=null && !ee.getValue().isDone()) continue;
+ deleteTasksForEntity(ee.getKey());
+ synchronized (unmanagedEntitiesNeedingGc) {
+ unmanagedEntitiesNeedingGc.remove(ee.getKey());
+ }
+ }
+ }
+
+ protected void expireAgedTasks() {
+ Duration maxTaskAge = brooklynProperties.getConfig(MAX_TASK_AGE);
+
+ Collection<Task<?>> allTasks = executionManager.allTasksLive();
+ Collection<Task<?>> tasksToDelete = MutableList.of();
+
+ try {
+ for (Task<?> task: allTasks) {
+ if (!task.isDone()) continue;
+ if (BrooklynTaskTags.isSubTask(task)) continue;
+
+ if (maxTaskAge.isShorterThan(Duration.sinceUtc(task.getEndTimeUtc())))
+ tasksToDelete.add(task);
+ }
+
+ } catch (ConcurrentModificationException e) {
+ // delete what we've found so far
+ LOG.debug("Got CME inspecting aged tasks, with "+tasksToDelete.size()+" found for deletion: "+e);
+ }
+
+ for (Task<?> task: tasksToDelete) {
+ executionManager.deleteTask(task);
+ }
+ }
+
+ protected void expireTransientTasks() {
+ Set<Task<?>> transientTasks = executionManager.getTasksWithTag(BrooklynTaskTags.TRANSIENT_TASK_TAG);
+ for (Task<?> t: transientTasks) {
+ if (!t.isDone()) continue;
+ executionManager.deleteTask(t);
+ }
+ }
+
+ protected int expireSubTasksWhoseSubmitterIsExpired() {
+ // ideally we wouldn't have this; see comments on CHECK_SUBTASK_SUBMITTERS
+ if (!brooklynProperties.getConfig(CHECK_SUBTASK_SUBMITTERS))
+ return 0;
+
+ Collection<Task<?>> allTasks = executionManager.allTasksLive();
+ Collection<Task<?>> tasksToDelete = MutableList.of();
+ try {
+ for (Task<?> task: allTasks) {
+ if (!task.isDone()) continue;
+ Task<?> submitter = task.getSubmittedByTask();
+ // if we've leaked, ie a subtask which is not a child task,
+ // and the submitter is GC'd, then delete this also
+ if (submitter!=null && submitter.isDone() && executionManager.getTask(submitter.getId())==null) {
+ tasksToDelete.add(task);
+ }
+ }
+
+ } catch (ConcurrentModificationException e) {
+ // delete what we've found so far
+ LOG.debug("Got CME inspecting aged tasks, with "+tasksToDelete.size()+" found for deletion: "+e);
+ }
+
+ for (Task<?> task: tasksToDelete) {
+ executionManager.deleteTask(task);
+ }
+ return tasksToDelete.size();
+ }
+
+ protected enum TagCategory {
+ ENTITY, NON_ENTITY_NORMAL;
+
+ public boolean acceptsTag(Object tag) {
+ if (isTagIgnoredForGc(tag)) return false;
+ if (tag instanceof WrappedEntity) return this==ENTITY;
+ if (this==ENTITY) return false;
+ return true;
+ }
+ }
+
+
+ /** expires tasks which are over-capacity in all their non-entity tag categories, returned count */
+ protected int expireOverCapacityTagsInCategory(Map<Object, AtomicInteger> taskTagsInCategoryOverCapacity, Map<Object, AtomicInteger> taskAllTagsOverCapacity, TagCategory category, boolean emptyFilterNeeded) {
+ if (emptyFilterNeeded) {
+ // previous run may have decremented counts
+ MutableList<Object> nowOkayTags = MutableList.of();
+ for (Map.Entry<Object,AtomicInteger> entry: taskTagsInCategoryOverCapacity.entrySet()) {
+ if (entry.getValue().get()<=0) nowOkayTags.add(entry.getKey());
+ }
+ for (Object tag: nowOkayTags) taskTagsInCategoryOverCapacity.remove(tag);
+ }
+
+ if (taskTagsInCategoryOverCapacity.isEmpty())
+ return 0;
+
+ Collection<Task<?>> tasks = executionManager.allTasksLive();
+ List<Task<?>> tasksToConsiderDeleting = MutableList.of();
+ try {
+ for (Task<?> task: tasks) {
+ if (!task.isDone()) continue;
+
+ Set<Object> tags = task.getTags();
+
+ int categoryTags = 0, tooFullCategoryTags = 0;
+ for (Object tag: tags) {
+ if (category.acceptsTag(tag)) {
+ categoryTags++;
+ if (taskTagsInCategoryOverCapacity.containsKey(tag))
+ tooFullCategoryTags++;
+ }
+ }
+ if (tooFullCategoryTags>0) {
+ if (categoryTags==tooFullCategoryTags) {
+ // all buckets are full, delete this one
+ tasksToConsiderDeleting.add(task);
+ } else {
+ // if any bucket is under capacity, then give grace to the other buckets in this category
+ for (Object tag: tags) {
+ if (category.acceptsTag(tag)) {
+ AtomicInteger over = taskTagsInCategoryOverCapacity.get(tag);
+ if (over!=null) {
+ if (over.decrementAndGet()<=0) {
+ // and remove it from over-capacity if so
+ taskTagsInCategoryOverCapacity.remove(tag);
+ if (taskTagsInCategoryOverCapacity.isEmpty())
+ return 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ } catch (ConcurrentModificationException e) {
+ // do CME's happen with these data structures?
+ // if so, let's just delete what we've found so far
+ LOG.debug("Got CME inspecting tasks, with "+tasksToConsiderDeleting.size()+" found for deletion: "+e);
+ }
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("brooklyn-gc detected "+taskTagsInCategoryOverCapacity.size()+" "+category+" "
+ + "tags over capacity, expiring old tasks; "
+ + tasksToConsiderDeleting.size()+" tasks under consideration; categories are: "
+ + taskTagsInCategoryOverCapacity);
+
+ Collections.sort(tasksToConsiderDeleting, TASKS_OLDEST_FIRST_COMPARATOR);
+ // now try deleting tasks which are overcapacity for each (non-entity) tag
+ int deleted = 0;
+ for (Task<?> task: tasksToConsiderDeleting) {
+ boolean delete = true;
+ for (Object tag: task.getTags()) {
+ if (!category.acceptsTag(tag))
+ continue;
+ if (taskTagsInCategoryOverCapacity.get(tag)==null) {
+ // no longer over capacity in this tag
+ delete = false;
+ break;
+ }
+ }
+ if (delete) {
+ // delete this and update overcapacity info
+ deleted++;
+ executionManager.deleteTask(task);
+ for (Object tag: task.getTags()) {
+ AtomicInteger counter = taskAllTagsOverCapacity.get(tag);
+ if (counter!=null && counter.decrementAndGet()<=0)
+ taskTagsInCategoryOverCapacity.remove(tag);
+ }
+ if (LOG.isTraceEnabled())
+ LOG.trace("brooklyn-gc deleted "+task+", buckets now "+taskTagsInCategoryOverCapacity);
+ if (taskTagsInCategoryOverCapacity.isEmpty())
+ break;
+ }
+ }
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("brooklyn-gc deleted "+deleted+" tasks in over-capacity " + category+" tag categories; "
+ + "capacities now: " + taskTagsInCategoryOverCapacity);
+ return deleted;
+ }
+
+ protected int expireIfOverCapacityGlobally() {
+ Collection<Task<?>> tasksLive = executionManager.allTasksLive();
+ if (tasksLive.size() <= brooklynProperties.getConfig(MAX_TASKS_GLOBAL))
+ return 0;
+ LOG.debug("brooklyn-gc detected "+tasksLive.size()+" tasks in memory, over global limit, looking at deleting some");
+
+ try {
+ tasksLive = MutableList.copyOf(tasksLive);
+ } catch (ConcurrentModificationException e) {
+ tasksLive = executionManager.getTasksWithAllTags(MutableList.of());
+ }
+
+ MutableList<Task<?>> tasks = MutableList.of();
+ for (Task<?> task: tasksLive) {
+ if (task.isDone()) {
+ tasks.add(task);
+ }
+ }
+
+ int numToDelete = tasks.size() - brooklynProperties.getConfig(MAX_TASKS_GLOBAL);
+ if (numToDelete <= 0) {
+ LOG.debug("brooklyn-gc detected only "+tasks.size()+" completed tasks in memory, not over global limit, so not deleting any");
+ return 0;
+ }
+
+ Collections.sort(tasks, TASKS_OLDEST_FIRST_COMPARATOR);
+
+ int numDeleted = 0;
+ while (numDeleted < numToDelete && tasks.size()>numDeleted) {
+ executionManager.deleteTask( tasks.get(numDeleted++) );
+ }
+ if (LOG.isDebugEnabled())
+ LOG.debug("brooklyn-gc deleted "+numDeleted+" tasks as was over global limit, now have "+executionManager.allTasksLive().size());
+ return numDeleted;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynObjectManagementMode.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynObjectManagementMode.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynObjectManagementMode.java
new file mode 100644
index 0000000..49afe27
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/BrooklynObjectManagementMode.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.management.internal;
+
+/** Indicates how an entity/location/adjunct is treated at a given {@link ManagementContext} */
+public enum BrooklynObjectManagementMode {
+ /** item does not exist, not in memory, nor persisted (e.g. creating for first time, or finally destroying) */
+ NONEXISTENT,
+ /** item exists or existed elsewhere, i.e. there is persisted state, but is not loaded here */
+ UNMANAGED_PERSISTED,
+ /** item is loaded but read-only (ie not actively managed here) */
+ LOADED_READ_ONLY,
+ /** item is actively managed here */
+ MANAGED_PRIMARY
+}
\ No newline at end of file
[25/33] incubator-brooklyn git commit: [BROOKLYN-162] Refactor
package in ./core/internal
Posted by ha...@apache.org.
[BROOKLYN-162] Refactor package in ./core/internal
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/9cf456dc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/9cf456dc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/9cf456dc
Branch: refs/heads/master
Commit: 9cf456dca3110c308c11bd4b5fdedbbe74b4236d
Parents: 6602f69
Author: Hadrian Zbarcea <ha...@apache.org>
Authored: Sat Aug 15 00:05:56 2015 -0400
Committer: Hadrian Zbarcea <ha...@apache.org>
Committed: Sat Aug 15 00:05:56 2015 -0400
----------------------------------------------------------------------
.../brooklyn/entity/basic/AbstractEntity.java | 4 +-
.../entity/basic/AbstractGroupImpl.java | 2 +-
.../rebind/PeriodicDeltaChangeListener.java | 2 +-
.../brooklyn/entity/rebind/RebindIteration.java | 2 +-
.../entity/rebind/RebindManagerImpl.java | 2 +-
.../basic/PortAttributeSensorAndConfigKey.java | 2 +-
.../java/brooklyn/event/feed/AbstractFeed.java | 2 +-
.../internal/BrooklynFeatureEnablement.java | 210 -------------------
.../internal/BrooklynInitialization.java | 81 -------
.../util/BrooklynLanguageExtensions.java | 3 +-
.../main/java/brooklyn/util/ResourceUtils.java | 2 +-
.../brooklyn/util/crypto/FluentKeySigner.java | 2 +-
.../java/brooklyn/util/crypto/SecureKeys.java | 2 +-
.../java/brooklyn/util/flags/TypeCoercions.java | 2 +-
.../util/internal/ssh/sshj/SshjTool.java | 2 +-
.../util/task/BasicExecutionManager.java | 2 +-
.../internal/BrooklynFeatureEnablement.java | 210 +++++++++++++++++++
.../core/internal/BrooklynInitialization.java | 81 +++++++
.../ha/HighAvailabilityManagerImpl.java | 2 +-
.../internal/LocalManagementContext.java | 2 +-
.../location/basic/AbstractLocation.java | 2 +-
.../location/basic/LocationConfigUtils.java | 4 +-
.../entity/rebind/RebindCatalogItemTest.java | 2 +-
...talogWhenCatalogPersistenceDisabledTest.java | 2 +-
.../internal/BrooklynFeatureEnablementTest.java | 118 -----------
.../sshj/SshjToolAsyncStubIntegrationTest.java | 2 +-
.../ssh/sshj/SshjToolIntegrationTest.java | 2 +-
.../internal/BrooklynFeatureEnablementTest.java | 119 +++++++++++
.../HighAvailabilityManagerSplitBrainTest.java | 2 +-
.../nginx/NginxRebindWithHaIntegrationTest.java | 2 +-
.../brooklyn/catalog/CatalogYamlRebindTest.java | 2 +-
.../brooklyn/launcher/BrooklynWebServer.java | 2 +-
32 files changed, 440 insertions(+), 436 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index dc005d8..2860b82 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -53,6 +53,8 @@ import org.apache.brooklyn.api.policy.EnricherSpec;
import org.apache.brooklyn.api.policy.EntityAdjunct;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.apache.brooklyn.core.management.internal.EffectorUtils;
import org.apache.brooklyn.core.management.internal.EntityManagementSupport;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
@@ -76,8 +78,6 @@ import brooklyn.event.basic.BasicNotificationSensor;
import brooklyn.event.basic.Sensors;
import brooklyn.event.feed.AbstractFeed;
import brooklyn.event.feed.ConfigToAttributes;
-import brooklyn.internal.BrooklynFeatureEnablement;
-import brooklyn.internal.BrooklynInitialization;
import brooklyn.internal.storage.BrooklynStorage;
import brooklyn.internal.storage.Reference;
import brooklyn.internal.storage.impl.BasicReference;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java b/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java
index 79abdb0..a300f39 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractGroupImpl.java
@@ -28,11 +28,11 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.Group;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.util.collections.SetFromLiveMap;
import com.google.common.base.Optional;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java b/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
index 98906e9..d204ecc 100644
--- a/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
+++ b/core/src/main/java/brooklyn/entity/rebind/PeriodicDeltaChangeListener.java
@@ -45,12 +45,12 @@ import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import brooklyn.entity.basic.BrooklynTaskTags;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 30803e2..8c6a402 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -64,6 +64,7 @@ import org.apache.brooklyn.api.mementos.TreeNode;
import org.apache.brooklyn.api.mementos.BrooklynMementoManifest.EntityMementoManifest;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.BrooklynObjectManagementMode;
import org.apache.brooklyn.core.management.internal.BrooklynObjectManagerInternal;
import org.apache.brooklyn.core.management.internal.EntityManagerInternal;
@@ -86,7 +87,6 @@ import brooklyn.entity.proxying.InternalPolicyFactory;
import brooklyn.entity.rebind.RebindManagerImpl.RebindTracker;
import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
import brooklyn.event.feed.AbstractFeed;
-import brooklyn.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.location.basic.AbstractLocation;
import org.apache.brooklyn.location.basic.LocationInternal;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 8221472..862c86b 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -43,6 +43,7 @@ import org.apache.brooklyn.api.management.ha.MementoCopyMode;
import org.apache.brooklyn.api.mementos.BrooklynMementoPersister;
import org.apache.brooklyn.api.mementos.BrooklynMementoRawData;
import org.apache.brooklyn.api.mementos.TreeNode;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
@@ -58,7 +59,6 @@ import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils.CreateBackupMode;
import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
import brooklyn.entity.rebind.transformer.CompoundTransformer;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.QuorumCheck;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java b/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java
index b086b98..fd7100a 100644
--- a/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java
+++ b/core/src/main/java/brooklyn/event/basic/PortAttributeSensorAndConfigKey.java
@@ -28,12 +28,12 @@ import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.location.PortSupplier;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.BrooklynConfigKeys;
-import brooklyn.internal.BrooklynInitialization;
import org.apache.brooklyn.location.basic.Locations;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/event/feed/AbstractFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/AbstractFeed.java b/core/src/main/java/brooklyn/event/feed/AbstractFeed.java
index 5f5229c..23037a7 100644
--- a/core/src/main/java/brooklyn/event/feed/AbstractFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/AbstractFeed.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.Feed;
import org.apache.brooklyn.api.entity.basic.EntityLocal;
import org.apache.brooklyn.api.entity.rebind.RebindSupport;
import org.apache.brooklyn.api.mementos.FeedMemento;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,7 +34,6 @@ import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.rebind.BasicFeedRebindSupport;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.policy.basic.AbstractEntityAdjunct;
import brooklyn.util.javalang.JavaClassNames;
import brooklyn.util.text.Strings;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java b/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
deleted file mode 100644
index 10a6e4a..0000000
--- a/core/src/main/java/brooklyn/internal/BrooklynFeatureEnablement.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.internal;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.internal.storage.BrooklynStorage;
-import brooklyn.util.internal.ssh.ShellTool;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.Maps;
-
-/**
- * For enabling/disabling experimental features.
- * They can be enabled via java system properties, or by explicitly calling {@link #setEnablement(String, boolean)}.
- * <p>
- * For example, start brooklyn with {@code -Dbrooklyn.experimental.feature.policyPersistence=true}
- *
- * @author aled
- */
-@Beta
-public class BrooklynFeatureEnablement {
-
- private static final Logger LOG = LoggerFactory.getLogger(BrooklynFeatureEnablement.class);
-
- public static final String FEATURE_PROPERTY_PREFIX = "brooklyn.experimental.feature";
-
- public static final String FEATURE_POLICY_PERSISTENCE_PROPERTY = FEATURE_PROPERTY_PREFIX+".policyPersistence";
-
- public static final String FEATURE_ENRICHER_PERSISTENCE_PROPERTY = FEATURE_PROPERTY_PREFIX+".enricherPersistence";
-
- public static final String FEATURE_FEED_PERSISTENCE_PROPERTY = FEATURE_PROPERTY_PREFIX+".feedPersistence";
-
- /** whether feeds are automatically registered when set on entities, so that they are persisted */
- public static final String FEATURE_FEED_REGISTRATION_PROPERTY = FEATURE_PROPERTY_PREFIX+".feedRegistration";
-
- public static final String FEATURE_CATALOG_PERSISTENCE_PROPERTY = FEATURE_PROPERTY_PREFIX+".catalogPersistence";
-
- /** whether the default standby mode is {@link HighAvailabilityMode#HOT_STANDBY} or falling back to the traditional
- * {@link HighAvailabilityMode#STANDBY} */
- public static final String FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY = FEATURE_PROPERTY_PREFIX+".defaultStandbyIsHot";
-
- /** whether to attempt to use {@link BrooklynStorage} (datagrid) as a backing store for data;
- * note this is <b>not</b> compatible with {@link #FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY}
- * which uses a blob/file store and a larger-granularity rebind process than was intended with the datagrid */
- /* not sure if we still even need this? now the rebind/read-only feature reloads on demand from the persistence store;
- * the data-grid backing */
- public static final String FEATURE_USE_BROOKLYN_LIVE_OBJECTS_DATAGRID_STORAGE = FEATURE_PROPERTY_PREFIX+".useBrooklynLiveObjectsDatagridStorage";
-
- /**
- * Renaming threads can really helps with debugging etc; however it's a massive performance hit (2x)
- * <p>
- * We get 55000 tasks per sec with this off, 28k/s with this on.
- * <p>
- * Defaults to false if system property is not set.
- */
- public static final String FEATURE_RENAME_THREADS = "brooklyn.executionManager.renameThreads";
-
- /**
- * When rebinding to state created from very old versions, the catalogItemId properties will be missing which
- * results in errors when OSGi bundles are used. When enabled the code tries to infer the catalogItemId from
- * <ul>
- * <li> parent entities
- * <li> catalog items matching the type that needs to be deserialized
- * <li> iterating through all catalog items and checking if they can provide the needed type
- * </ul>
- */
- public static final String FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND = "brooklyn.backwardCompatibility.feature.inferCatalogItemOnRebind";
-
- /**
- * When rebinding, an entity could reference a catalog item that no longer exists. This option
- * will automatically update the catalog item reference to what is inferred as the most
- * suitable catalog symbolicName:version.
- */
- public static final String FEATURE_AUTO_FIX_CATALOG_REF_ON_REBIND = "brooklyn.quickfix.fixDanglingCatalogItemOnRebind";
-
- /**
- * When executing over ssh, whether to support the "async exec" approach, or only the classic approach.
- *
- * If this feature is disabled, then even if the {@link ShellTool#PROP_EXEC_ASYNC} is configured it
- * will still use the classic ssh approach.
- */
- public static final String FEATURE_SSH_ASYNC_EXEC = FEATURE_PROPERTY_PREFIX+".ssh.asyncExec";
-
- public static final String FEATURE_VALIDATE_LOCATION_SSH_KEYS = "brooklyn.validate.locationSshKeys";
-
- private static final Map<String, Boolean> FEATURE_ENABLEMENTS = Maps.newLinkedHashMap();
-
- private static final Object MUTEX = new Object();
-
- static void setDefaults() {
- // Idea is here one can put experimental features that are *enabled* by default, but
- // that can be turned off via system properties, or vice versa.
- // Typically this is useful where a feature is deemed risky!
-
- setDefault(FEATURE_POLICY_PERSISTENCE_PROPERTY, true);
- setDefault(FEATURE_ENRICHER_PERSISTENCE_PROPERTY, true);
- setDefault(FEATURE_FEED_PERSISTENCE_PROPERTY, true);
- setDefault(FEATURE_FEED_REGISTRATION_PROPERTY, false);
- setDefault(FEATURE_CATALOG_PERSISTENCE_PROPERTY, true);
- setDefault(FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY, false);
- setDefault(FEATURE_USE_BROOKLYN_LIVE_OBJECTS_DATAGRID_STORAGE, false);
- setDefault(FEATURE_RENAME_THREADS, false);
- setDefault(FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND, true);
- setDefault(FEATURE_AUTO_FIX_CATALOG_REF_ON_REBIND, false);
- setDefault(FEATURE_SSH_ASYNC_EXEC, false);
- setDefault(FEATURE_VALIDATE_LOCATION_SSH_KEYS, true);
- }
-
- static {
- setDefaults();
- }
-
- /**
- * Initialises the feature-enablement from brooklyn properties. For each
- * property, prefer a system-property if present; otherwise use the value
- * from brooklyn properties.
- */
- public static void init(BrooklynProperties props) {
- boolean changed = false;
- for (Map.Entry<String, Object> entry : props.asMapWithStringKeys().entrySet()) {
- String property = entry.getKey();
- if (property.startsWith(FEATURE_PROPERTY_PREFIX)) {
- if (!FEATURE_ENABLEMENTS.containsKey(property)) {
- Object rawVal = System.getProperty(property);
- if (rawVal == null) {
- rawVal = entry.getValue();
- }
- boolean val = Boolean.parseBoolean(""+rawVal);
- FEATURE_ENABLEMENTS.put(property, val);
-
- changed = true;
- LOG.debug("Init feature enablement of "+property+" set to "+val);
- }
- }
- }
- if (!changed) {
- LOG.debug("Init feature enablement did nothing, as no settings in brooklyn properties");
- }
- }
-
- public static boolean isEnabled(String property) {
- synchronized (MUTEX) {
- if (!FEATURE_ENABLEMENTS.containsKey(property)) {
- String rawVal = System.getProperty(property);
- boolean val = Boolean.parseBoolean(rawVal);
- FEATURE_ENABLEMENTS.put(property, val);
- }
- return FEATURE_ENABLEMENTS.get(property);
- }
- }
-
- public static boolean enable(String property) {
- return setEnablement(property, true);
- }
-
- public static boolean disable(String property) {
- return setEnablement(property, false);
- }
-
- public static boolean setEnablement(String property, boolean val) {
- synchronized (MUTEX) {
- boolean oldVal = isEnabled(property);
- FEATURE_ENABLEMENTS.put(property, val);
- return oldVal;
- }
- }
-
- static void setDefault(String property, boolean val) {
- synchronized (MUTEX) {
- if (!FEATURE_ENABLEMENTS.containsKey(property)) {
- String rawVal = System.getProperty(property);
- if (rawVal == null) {
- FEATURE_ENABLEMENTS.put(property, val);
- LOG.debug("Default enablement of "+property+" set to "+val);
- } else {
- LOG.debug("Not setting default enablement of "+property+" to "+val+", because system property is "+rawVal);
- }
- }
- }
- }
-
- static void clearCache() {
- synchronized (MUTEX) {
- FEATURE_ENABLEMENTS.clear();
- setDefaults();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/internal/BrooklynInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/internal/BrooklynInitialization.java b/core/src/main/java/brooklyn/internal/BrooklynInitialization.java
deleted file mode 100644
index 70eea9f..0000000
--- a/core/src/main/java/brooklyn/internal/BrooklynInitialization.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.internal;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.brooklyn.location.basic.PortRanges;
-import brooklyn.util.crypto.SecureKeys;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.net.Networking;
-
-import com.google.common.annotations.Beta;
-
-/** Various static initialization tasks are routed through this class,
- * to give us better traceability of their invocation. */
-@Beta
-public class BrooklynInitialization {
-
- private static AtomicBoolean done = new AtomicBoolean(false);
-
- public static void initTypeCoercionStandardAdapters() {
- TypeCoercions.initStandardAdapters();
- }
-
- public static void initSecureKeysBouncyCastleProvider() {
- SecureKeys.initBouncyCastleProvider();
- }
-
- public static void initNetworking() {
- Networking.init();
- }
-
- public static void initPortRanges() {
- PortRanges.init();
- }
-
- @SuppressWarnings("deprecation")
- public static void initLegacyLanguageExtensions() {
- brooklyn.util.BrooklynLanguageExtensions.init();
- }
-
- /* other things:
- *
- * RendererHints - done by the entity classes which need them, including Sensors
- *
- */
-
- public synchronized static void initAll() {
- if (done.get()) return;
- initTypeCoercionStandardAdapters();
- initSecureKeysBouncyCastleProvider();
- initNetworking();
- initPortRanges();
- initLegacyLanguageExtensions();
- done.set(true);
- }
-
- @SuppressWarnings("deprecation")
- public synchronized static void reinitAll() {
- done.set(false);
- brooklyn.util.BrooklynLanguageExtensions.reinit();
- initAll();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java b/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java
index dd25090..86aac7e 100644
--- a/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java
+++ b/core/src/main/java/brooklyn/util/BrooklynLanguageExtensions.java
@@ -20,7 +20,8 @@ package brooklyn.util;
import java.util.concurrent.atomic.AtomicBoolean;
-import brooklyn.internal.BrooklynInitialization;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
+
import brooklyn.util.internal.TimeExtras;
/** @deprecated since 0.7.0 use {@link BrooklynInitialization} */
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/util/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/ResourceUtils.java b/core/src/main/java/brooklyn/util/ResourceUtils.java
index 53264e3..9b23b7a 100644
--- a/core/src/main/java/brooklyn/util/ResourceUtils.java
+++ b/core/src/main/java/brooklyn/util/ResourceUtils.java
@@ -40,6 +40,7 @@ import java.util.regex.Pattern;
import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.apache.brooklyn.core.management.classloading.JavaBrooklynClassLoadingContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@@ -53,7 +54,6 @@ import org.slf4j.LoggerFactory;
import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.internal.BrooklynInitialization;
import org.apache.brooklyn.location.basic.SshMachineLocation;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java b/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java
index 983a3d6..a1bc125 100644
--- a/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java
+++ b/core/src/main/java/brooklyn/util/crypto/FluentKeySigner.java
@@ -28,11 +28,11 @@ import java.util.Date;
import javax.security.auth.x500.X500Principal;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.jce.X509Principal;
-import brooklyn.internal.BrooklynInitialization;
import brooklyn.util.exceptions.Exceptions;
/** A fluent API which simplifies generating certificates (signed keys) */
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/util/crypto/SecureKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/crypto/SecureKeys.java b/core/src/main/java/brooklyn/util/crypto/SecureKeys.java
index 23a46d0..29fcf32 100644
--- a/core/src/main/java/brooklyn/util/crypto/SecureKeys.java
+++ b/core/src/main/java/brooklyn/util/crypto/SecureKeys.java
@@ -28,6 +28,7 @@ import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -42,7 +43,6 @@ import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.internal.BrooklynInitialization;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.stream.Streams;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
index 7bfb770..31f27be 100644
--- a/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
+++ b/core/src/main/java/brooklyn/util/flags/TypeCoercions.java
@@ -45,6 +45,7 @@ import javax.annotation.concurrent.GuardedBy;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.event.AttributeSensor;
import org.apache.brooklyn.api.event.Sensor;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,7 +54,6 @@ import brooklyn.entity.basic.ClosureEntityFactory;
import brooklyn.entity.basic.ConfigurableEntityFactory;
import brooklyn.entity.basic.ConfigurableEntityFactoryFromEntityFactory;
import brooklyn.event.basic.Sensors;
-import brooklyn.internal.BrooklynInitialization;
import brooklyn.util.JavaGroovyEquivalents;
import brooklyn.util.collections.MutableSet;
import brooklyn.util.collections.QuorumCheck;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java b/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java
index 8fa38ad..e069aa9 100644
--- a/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java
+++ b/core/src/main/java/brooklyn/util/internal/ssh/sshj/SshjTool.java
@@ -49,11 +49,11 @@ import net.schmizz.sshj.sftp.SFTPClient;
import net.schmizz.sshj.transport.TransportException;
import net.schmizz.sshj.xfer.InMemorySourceFile;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.commons.io.input.ProxyInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeTimeoutException;
import brooklyn.util.internal.ssh.BackoffLimitedRetryHandler;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java b/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
index c472132..13d035b 100644
--- a/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
+++ b/core/src/main/java/brooklyn/util/task/BasicExecutionManager.java
@@ -49,10 +49,10 @@ import org.apache.brooklyn.api.management.ExecutionManager;
import org.apache.brooklyn.api.management.HasTaskChildren;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.util.collections.MutableList;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.text.Identifiers;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java
new file mode 100644
index 0000000..24d138b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablement.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.internal;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.internal.storage.BrooklynStorage;
+import brooklyn.util.internal.ssh.ShellTool;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Maps;
+
+/**
+ * For enabling/disabling experimental features.
+ * They can be enabled via java system properties, or by explicitly calling {@link #setEnablement(String, boolean)}.
+ * <p>
+ * For example, start brooklyn with {@code -Dbrooklyn.experimental.feature.policyPersistence=true}
+ *
+ * @author aled
+ */
+@Beta
+public class BrooklynFeatureEnablement {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BrooklynFeatureEnablement.class);
+
+ public static final String FEATURE_PROPERTY_PREFIX = "brooklyn.experimental.feature";
+
+ public static final String FEATURE_POLICY_PERSISTENCE_PROPERTY = FEATURE_PROPERTY_PREFIX+".policyPersistence";
+
+ public static final String FEATURE_ENRICHER_PERSISTENCE_PROPERTY = FEATURE_PROPERTY_PREFIX+".enricherPersistence";
+
+ public static final String FEATURE_FEED_PERSISTENCE_PROPERTY = FEATURE_PROPERTY_PREFIX+".feedPersistence";
+
+ /** whether feeds are automatically registered when set on entities, so that they are persisted */
+ public static final String FEATURE_FEED_REGISTRATION_PROPERTY = FEATURE_PROPERTY_PREFIX+".feedRegistration";
+
+ public static final String FEATURE_CATALOG_PERSISTENCE_PROPERTY = FEATURE_PROPERTY_PREFIX+".catalogPersistence";
+
+ /** whether the default standby mode is {@link HighAvailabilityMode#HOT_STANDBY} or falling back to the traditional
+ * {@link HighAvailabilityMode#STANDBY} */
+ public static final String FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY = FEATURE_PROPERTY_PREFIX+".defaultStandbyIsHot";
+
+ /** whether to attempt to use {@link BrooklynStorage} (datagrid) as a backing store for data;
+ * note this is <b>not</b> compatible with {@link #FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY}
+ * which uses a blob/file store and a larger-granularity rebind process than was intended with the datagrid */
+ /* not sure if we still even need this? now the rebind/read-only feature reloads on demand from the persistence store;
+ * the data-grid backing */
+ public static final String FEATURE_USE_BROOKLYN_LIVE_OBJECTS_DATAGRID_STORAGE = FEATURE_PROPERTY_PREFIX+".useBrooklynLiveObjectsDatagridStorage";
+
+ /**
+ * Renaming threads can really helps with debugging etc; however it's a massive performance hit (2x)
+ * <p>
+ * We get 55000 tasks per sec with this off, 28k/s with this on.
+ * <p>
+ * Defaults to false if system property is not set.
+ */
+ public static final String FEATURE_RENAME_THREADS = "brooklyn.executionManager.renameThreads";
+
+ /**
+ * When rebinding to state created from very old versions, the catalogItemId properties will be missing which
+ * results in errors when OSGi bundles are used. When enabled the code tries to infer the catalogItemId from
+ * <ul>
+ * <li> parent entities
+ * <li> catalog items matching the type that needs to be deserialized
+ * <li> iterating through all catalog items and checking if they can provide the needed type
+ * </ul>
+ */
+ public static final String FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND = "brooklyn.backwardCompatibility.feature.inferCatalogItemOnRebind";
+
+ /**
+ * When rebinding, an entity could reference a catalog item that no longer exists. This option
+ * will automatically update the catalog item reference to what is inferred as the most
+ * suitable catalog symbolicName:version.
+ */
+ public static final String FEATURE_AUTO_FIX_CATALOG_REF_ON_REBIND = "brooklyn.quickfix.fixDanglingCatalogItemOnRebind";
+
+ /**
+ * When executing over ssh, whether to support the "async exec" approach, or only the classic approach.
+ *
+ * If this feature is disabled, then even if the {@link ShellTool#PROP_EXEC_ASYNC} is configured it
+ * will still use the classic ssh approach.
+ */
+ public static final String FEATURE_SSH_ASYNC_EXEC = FEATURE_PROPERTY_PREFIX+".ssh.asyncExec";
+
+ public static final String FEATURE_VALIDATE_LOCATION_SSH_KEYS = "brooklyn.validate.locationSshKeys";
+
+ private static final Map<String, Boolean> FEATURE_ENABLEMENTS = Maps.newLinkedHashMap();
+
+ private static final Object MUTEX = new Object();
+
+ static void setDefaults() {
+ // Idea is here one can put experimental features that are *enabled* by default, but
+ // that can be turned off via system properties, or vice versa.
+ // Typically this is useful where a feature is deemed risky!
+
+ setDefault(FEATURE_POLICY_PERSISTENCE_PROPERTY, true);
+ setDefault(FEATURE_ENRICHER_PERSISTENCE_PROPERTY, true);
+ setDefault(FEATURE_FEED_PERSISTENCE_PROPERTY, true);
+ setDefault(FEATURE_FEED_REGISTRATION_PROPERTY, false);
+ setDefault(FEATURE_CATALOG_PERSISTENCE_PROPERTY, true);
+ setDefault(FEATURE_DEFAULT_STANDBY_IS_HOT_PROPERTY, false);
+ setDefault(FEATURE_USE_BROOKLYN_LIVE_OBJECTS_DATAGRID_STORAGE, false);
+ setDefault(FEATURE_RENAME_THREADS, false);
+ setDefault(FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND, true);
+ setDefault(FEATURE_AUTO_FIX_CATALOG_REF_ON_REBIND, false);
+ setDefault(FEATURE_SSH_ASYNC_EXEC, false);
+ setDefault(FEATURE_VALIDATE_LOCATION_SSH_KEYS, true);
+ }
+
+ static {
+ setDefaults();
+ }
+
+ /**
+ * Initialises the feature-enablement from brooklyn properties. For each
+ * property, prefer a system-property if present; otherwise use the value
+ * from brooklyn properties.
+ */
+ public static void init(BrooklynProperties props) {
+ boolean changed = false;
+ for (Map.Entry<String, Object> entry : props.asMapWithStringKeys().entrySet()) {
+ String property = entry.getKey();
+ if (property.startsWith(FEATURE_PROPERTY_PREFIX)) {
+ if (!FEATURE_ENABLEMENTS.containsKey(property)) {
+ Object rawVal = System.getProperty(property);
+ if (rawVal == null) {
+ rawVal = entry.getValue();
+ }
+ boolean val = Boolean.parseBoolean(""+rawVal);
+ FEATURE_ENABLEMENTS.put(property, val);
+
+ changed = true;
+ LOG.debug("Init feature enablement of "+property+" set to "+val);
+ }
+ }
+ }
+ if (!changed) {
+ LOG.debug("Init feature enablement did nothing, as no settings in brooklyn properties");
+ }
+ }
+
+ public static boolean isEnabled(String property) {
+ synchronized (MUTEX) {
+ if (!FEATURE_ENABLEMENTS.containsKey(property)) {
+ String rawVal = System.getProperty(property);
+ boolean val = Boolean.parseBoolean(rawVal);
+ FEATURE_ENABLEMENTS.put(property, val);
+ }
+ return FEATURE_ENABLEMENTS.get(property);
+ }
+ }
+
+ public static boolean enable(String property) {
+ return setEnablement(property, true);
+ }
+
+ public static boolean disable(String property) {
+ return setEnablement(property, false);
+ }
+
+ public static boolean setEnablement(String property, boolean val) {
+ synchronized (MUTEX) {
+ boolean oldVal = isEnabled(property);
+ FEATURE_ENABLEMENTS.put(property, val);
+ return oldVal;
+ }
+ }
+
+ static void setDefault(String property, boolean val) {
+ synchronized (MUTEX) {
+ if (!FEATURE_ENABLEMENTS.containsKey(property)) {
+ String rawVal = System.getProperty(property);
+ if (rawVal == null) {
+ FEATURE_ENABLEMENTS.put(property, val);
+ LOG.debug("Default enablement of "+property+" set to "+val);
+ } else {
+ LOG.debug("Not setting default enablement of "+property+" to "+val+", because system property is "+rawVal);
+ }
+ }
+ }
+ }
+
+ static void clearCache() {
+ synchronized (MUTEX) {
+ FEATURE_ENABLEMENTS.clear();
+ setDefaults();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java
new file mode 100644
index 0000000..1858306
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynInitialization.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.internal;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.location.basic.PortRanges;
+import brooklyn.util.crypto.SecureKeys;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.net.Networking;
+
+import com.google.common.annotations.Beta;
+
+/** Various static initialization tasks are routed through this class,
+ * to give us better traceability of their invocation. */
+@Beta
+public class BrooklynInitialization {
+
+ private static AtomicBoolean done = new AtomicBoolean(false);
+
+ public static void initTypeCoercionStandardAdapters() {
+ TypeCoercions.initStandardAdapters();
+ }
+
+ public static void initSecureKeysBouncyCastleProvider() {
+ SecureKeys.initBouncyCastleProvider();
+ }
+
+ public static void initNetworking() {
+ Networking.init();
+ }
+
+ public static void initPortRanges() {
+ PortRanges.init();
+ }
+
+ @SuppressWarnings("deprecation")
+ public static void initLegacyLanguageExtensions() {
+ brooklyn.util.BrooklynLanguageExtensions.init();
+ }
+
+ /* other things:
+ *
+ * RendererHints - done by the entity classes which need them, including Sensors
+ *
+ */
+
+ public synchronized static void initAll() {
+ if (done.get()) return;
+ initTypeCoercionStandardAdapters();
+ initSecureKeysBouncyCastleProvider();
+ initNetworking();
+ initPortRanges();
+ initLegacyLanguageExtensions();
+ done.set(true);
+ }
+
+ @SuppressWarnings("deprecation")
+ public synchronized static void reinitAll() {
+ done.set(false);
+ brooklyn.util.BrooklynLanguageExtensions.reinit();
+ initAll();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java b/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
index 8a02fcf..25d8281 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerImpl.java
@@ -42,6 +42,7 @@ import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
import org.apache.brooklyn.api.management.ha.MementoCopyMode;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister.Delta;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.ha.BasicMasterChooser.AlphabeticMasterChooser;
import org.apache.brooklyn.core.management.internal.BrooklynObjectManagementMode;
import org.apache.brooklyn.core.management.internal.LocalEntityManager;
@@ -66,7 +67,6 @@ import brooklyn.entity.rebind.persister.PersistenceActivityMetrics;
import brooklyn.entity.rebind.plane.dto.BasicManagementNodeSyncRecord;
import brooklyn.entity.rebind.plane.dto.ManagementPlaneSyncRecordImpl;
import brooklyn.entity.rebind.plane.dto.ManagementPlaneSyncRecordImpl.Builder;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.exceptions.Exceptions;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
index 306dcd8..3c353e2 100644
--- a/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/management/internal/LocalManagementContext.java
@@ -42,6 +42,7 @@ import org.apache.brooklyn.api.management.ManagementContext;
import org.apache.brooklyn.api.management.SubscriptionManager;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.TaskAdaptable;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.entitlement.Entitlements;
import org.apache.brooklyn.core.management.ha.OsgiManager;
import org.slf4j.Logger;
@@ -54,7 +55,6 @@ import brooklyn.entity.effector.Effectors;
import brooklyn.entity.proxying.InternalEntityFactory;
import brooklyn.entity.proxying.InternalLocationFactory;
import brooklyn.entity.proxying.InternalPolicyFactory;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.internal.storage.DataGridFactory;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.guava.Maybe;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java b/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
index c5a74a0..554a781 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/AbstractLocation.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.mementos.LocationMemento;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.LocalLocationManager;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.slf4j.Logger;
@@ -47,7 +48,6 @@ import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.rebind.BasicLocationRebindSupport;
import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.internal.storage.BrooklynStorage;
import brooklyn.internal.storage.Reference;
import brooklyn.internal.storage.impl.BasicReference;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java b/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java
index ce3c444..d34a199 100644
--- a/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/location/basic/LocationConfigUtils.java
@@ -31,13 +31,15 @@ import java.util.Map;
import java.util.Set;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.internal.BrooklynFeatureEnablement;
+
import org.apache.brooklyn.location.cloud.CloudLocationConfig;
+
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
index 5d95534..f46df75 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogItemTest.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestEntity;
@@ -47,7 +48,6 @@ import brooklyn.catalog.internal.BasicBrooklynCatalog;
import brooklyn.catalog.internal.CatalogDto;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
-import brooklyn.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
index 2c3890c..7654759 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindCatalogWhenCatalogPersistenceDisabledTest.java
@@ -30,12 +30,12 @@ import brooklyn.camp.lite.CampPlatformWithJustBrooklynMgmt;
import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.entity.proxying.EntitySpec;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.test.entity.TestEntity;
import brooklyn.config.BrooklynProperties;
import brooklyn.config.BrooklynServerConfig;
-import brooklyn.internal.BrooklynFeatureEnablement;
import com.google.common.collect.Iterables;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/test/java/brooklyn/internal/BrooklynFeatureEnablementTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/internal/BrooklynFeatureEnablementTest.java b/core/src/test/java/brooklyn/internal/BrooklynFeatureEnablementTest.java
deleted file mode 100644
index ea0fed6..0000000
--- a/core/src/test/java/brooklyn/internal/BrooklynFeatureEnablementTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.internal;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-
-public class BrooklynFeatureEnablementTest {
-
- @BeforeMethod(alwaysRun=true)
- public void setUp() throws Exception {
- BrooklynFeatureEnablement.clearCache();
- }
-
- @Test
- public void testDefaultIsNotEnabled() throws Exception {
- assertFalse(BrooklynFeatureEnablement.isEnabled("feature.not.referenced.anywhere"));
- }
-
- @Test
- public void testCanSetPropertyEnablement() throws Exception {
- String featureProperty = "brooklyn.experimental.feature.testCanSetPropertyEnablement";
- boolean preTestVal = BrooklynFeatureEnablement.isEnabled(featureProperty);
- try {
- boolean oldVal = BrooklynFeatureEnablement.enable(featureProperty);
- assertEquals(oldVal, preTestVal);
- assertTrue(BrooklynFeatureEnablement.isEnabled(featureProperty));
-
- boolean oldVal2 = BrooklynFeatureEnablement.disable(featureProperty);
- assertTrue(oldVal2);
- assertFalse(BrooklynFeatureEnablement.isEnabled(featureProperty));
- } finally {
- BrooklynFeatureEnablement.setEnablement(featureProperty, preTestVal);
- }
- }
-
- @Test
- public void testReadsEnablementFromProperties() throws Exception {
- String featureProperty = "brooklyn.experimental.feature.testReadsEnablementFromProperties";
- System.setProperty(featureProperty, "true");
- try {
- assertTrue(BrooklynFeatureEnablement.isEnabled(featureProperty));
- } finally {
- System.clearProperty(featureProperty);
- }
- }
-
- @Test
- public void testCanSetDefaultWhichTakesEffectIfNoSystemProperty() throws Exception {
- String featureProperty = "brooklyn.experimental.feature.testCanSetDefaultWhichTakesEffectIfNoSystemProperty";
- BrooklynFeatureEnablement.setDefault(featureProperty, true);
- assertTrue(BrooklynFeatureEnablement.isEnabled(featureProperty));
- System.setProperty(featureProperty, "true");
- try {
- } finally {
- System.clearProperty(featureProperty);
- }
- }
-
- @Test
- public void testCanSetDefaultWhichIsIgnoredIfSystemProperty() throws Exception {
- String featureProperty = "brooklyn.experimental.feature.testCanSetDefaultWhichIsIgnoredIfSystemProperty";
- System.setProperty(featureProperty, "false");
- try {
- BrooklynFeatureEnablement.setDefault(featureProperty, true);
- assertFalse(BrooklynFeatureEnablement.isEnabled(featureProperty));
- } finally {
- System.clearProperty(featureProperty);
- }
- }
-
- @Test
- public void testCanSetDefaultWhichIsIgnoredIfBrooklynProps() throws Exception {
- String featureProperty = "brooklyn.experimental.feature.testCanSetDefaultWhichIsIgnoredIfBrooklynProps";
- BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
- props.put(featureProperty, false);
- BrooklynFeatureEnablement.init(props);
- BrooklynFeatureEnablement.setDefault(featureProperty, true);
- assertFalse(BrooklynFeatureEnablement.isEnabled(featureProperty));
- }
-
- @Test
- public void testPrefersSysPropOverBrooklynProps() throws Exception {
- String featureProperty = "brooklyn.experimental.feature.testPrefersSysPropOverBrooklynProps";
- BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
- props.put(featureProperty, false);
- System.setProperty(featureProperty, "true");
- try {
- BrooklynFeatureEnablement.init(props);
- BrooklynFeatureEnablement.setDefault(featureProperty, true);
- assertTrue(BrooklynFeatureEnablement.isEnabled(featureProperty));
- } finally {
- System.clearProperty(featureProperty);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java b/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
index 9d468a6..df0330a 100644
--- a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
+++ b/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolAsyncStubIntegrationTest.java
@@ -25,11 +25,11 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.internal.ssh.SshAbstractTool.SshAction;
import brooklyn.util.internal.ssh.sshj.SshjTool.ShellAction;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java b/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java
index de3f58e..f1e354c 100644
--- a/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java
+++ b/core/src/test/java/brooklyn/util/internal/ssh/sshj/SshjToolIntegrationTest.java
@@ -36,9 +36,9 @@ import java.util.concurrent.atomic.AtomicReference;
import net.schmizz.sshj.connection.channel.direct.Session;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.testng.annotations.Test;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.test.Asserts;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.RuntimeTimeoutException;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/test/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablementTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablementTest.java b/core/src/test/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablementTest.java
new file mode 100644
index 0000000..93ed8db
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/internal/BrooklynFeatureEnablementTest.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.internal;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+
+public class BrooklynFeatureEnablementTest {
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ BrooklynFeatureEnablement.clearCache();
+ }
+
+ @Test
+ public void testDefaultIsNotEnabled() throws Exception {
+ assertFalse(BrooklynFeatureEnablement.isEnabled("feature.not.referenced.anywhere"));
+ }
+
+ @Test
+ public void testCanSetPropertyEnablement() throws Exception {
+ String featureProperty = "brooklyn.experimental.feature.testCanSetPropertyEnablement";
+ boolean preTestVal = BrooklynFeatureEnablement.isEnabled(featureProperty);
+ try {
+ boolean oldVal = BrooklynFeatureEnablement.enable(featureProperty);
+ assertEquals(oldVal, preTestVal);
+ assertTrue(BrooklynFeatureEnablement.isEnabled(featureProperty));
+
+ boolean oldVal2 = BrooklynFeatureEnablement.disable(featureProperty);
+ assertTrue(oldVal2);
+ assertFalse(BrooklynFeatureEnablement.isEnabled(featureProperty));
+ } finally {
+ BrooklynFeatureEnablement.setEnablement(featureProperty, preTestVal);
+ }
+ }
+
+ @Test
+ public void testReadsEnablementFromProperties() throws Exception {
+ String featureProperty = "brooklyn.experimental.feature.testReadsEnablementFromProperties";
+ System.setProperty(featureProperty, "true");
+ try {
+ assertTrue(BrooklynFeatureEnablement.isEnabled(featureProperty));
+ } finally {
+ System.clearProperty(featureProperty);
+ }
+ }
+
+ @Test
+ public void testCanSetDefaultWhichTakesEffectIfNoSystemProperty() throws Exception {
+ String featureProperty = "brooklyn.experimental.feature.testCanSetDefaultWhichTakesEffectIfNoSystemProperty";
+ BrooklynFeatureEnablement.setDefault(featureProperty, true);
+ assertTrue(BrooklynFeatureEnablement.isEnabled(featureProperty));
+ System.setProperty(featureProperty, "true");
+ try {
+ } finally {
+ System.clearProperty(featureProperty);
+ }
+ }
+
+ @Test
+ public void testCanSetDefaultWhichIsIgnoredIfSystemProperty() throws Exception {
+ String featureProperty = "brooklyn.experimental.feature.testCanSetDefaultWhichIsIgnoredIfSystemProperty";
+ System.setProperty(featureProperty, "false");
+ try {
+ BrooklynFeatureEnablement.setDefault(featureProperty, true);
+ assertFalse(BrooklynFeatureEnablement.isEnabled(featureProperty));
+ } finally {
+ System.clearProperty(featureProperty);
+ }
+ }
+
+ @Test
+ public void testCanSetDefaultWhichIsIgnoredIfBrooklynProps() throws Exception {
+ String featureProperty = "brooklyn.experimental.feature.testCanSetDefaultWhichIsIgnoredIfBrooklynProps";
+ BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
+ props.put(featureProperty, false);
+ BrooklynFeatureEnablement.init(props);
+ BrooklynFeatureEnablement.setDefault(featureProperty, true);
+ assertFalse(BrooklynFeatureEnablement.isEnabled(featureProperty));
+ }
+
+ @Test
+ public void testPrefersSysPropOverBrooklynProps() throws Exception {
+ String featureProperty = "brooklyn.experimental.feature.testPrefersSysPropOverBrooklynProps";
+ BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
+ props.put(featureProperty, false);
+ System.setProperty(featureProperty, "true");
+ try {
+ BrooklynFeatureEnablement.init(props);
+ BrooklynFeatureEnablement.setDefault(featureProperty, true);
+ assertTrue(BrooklynFeatureEnablement.isEnabled(featureProperty));
+ } finally {
+ System.clearProperty(featureProperty);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java
index 7e34071..15caa29 100644
--- a/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/management/ha/HighAvailabilityManagerSplitBrainTest.java
@@ -34,6 +34,7 @@ import org.apache.brooklyn.api.management.ha.ManagementNodeState;
import org.apache.brooklyn.api.management.ha.ManagementNodeSyncRecord;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecord;
import org.apache.brooklyn.api.management.ha.ManagementPlaneSyncRecordPersister;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.ha.HighAvailabilityManagerImpl;
import org.apache.brooklyn.core.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
import org.apache.brooklyn.core.management.ha.TestEntityFailingRebind.RebindException;
@@ -54,7 +55,6 @@ import brooklyn.entity.rebind.persister.InMemoryObjectStore;
import brooklyn.entity.rebind.persister.ListeningObjectStore;
import brooklyn.entity.rebind.persister.PersistMode;
import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.test.Asserts;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
index f18b414..57ea76d 100644
--- a/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
+++ b/software/webapp/src/test/java/org/apache/brooklyn/entity/proxy/nginx/NginxRebindWithHaIntegrationTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.entity.proxying.EntitySpec;
import org.apache.brooklyn.api.location.LocationSpec;
import org.apache.brooklyn.api.management.Task;
import org.apache.brooklyn.api.management.ha.HighAvailabilityMode;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.core.management.internal.LocalManagementContext;
import org.apache.brooklyn.entity.proxy.nginx.NginxController;
import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
@@ -51,7 +52,6 @@ import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.group.DynamicCluster;
import brooklyn.entity.rebind.RebindTestFixtureWithApp;
import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.internal.BrooklynFeatureEnablement;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.basic.SshMachineLocationReuseIntegrationTest.RecordingSshjTool;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
index 8d50dde..3081243 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
@@ -24,13 +24,13 @@ import static org.testng.Assert.assertFalse;
import org.apache.brooklyn.api.policy.Enricher;
import org.apache.brooklyn.api.policy.Policy;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlRebindTest;
+import org.apache.brooklyn.core.internal.BrooklynFeatureEnablement;
import org.testng.annotations.Test;
import brooklyn.catalog.internal.CatalogUtils;
import brooklyn.entity.basic.BasicEntity;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.StartableApplication;
-import brooklyn.internal.BrooklynFeatureEnablement;
import brooklyn.test.policy.TestEnricher;
import brooklyn.test.policy.TestPolicy;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9cf456dc/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
index c9bf366..13ee15a 100644
--- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
@@ -63,10 +63,10 @@ import brooklyn.BrooklynVersion;
import brooklyn.config.BrooklynServerPaths;
import brooklyn.config.BrooklynServiceAttributes;
import brooklyn.config.ConfigKey;
-import brooklyn.internal.BrooklynInitialization;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.management.ManagementContext;
+import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.apache.brooklyn.core.management.internal.ManagementContextInternal;
import org.apache.brooklyn.launcher.config.CustomResourceLocator;
import org.apache.brooklyn.location.basic.LocalhostMachineProvisioningLocation;