BROOKLYN-474: rebind to policy with private constructor (cherry picked from commit 8e314a986465923365ea640efd86f936acab3bfc)
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/4547cef4 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/4547cef4 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/4547cef4 Branch: refs/heads/0.11.x Commit: 4547cef47429771eb7240b5ac5f46def8f145108 Parents: eef08cf Author: Aled Sage <[email protected]> Authored: Thu Apr 13 17:46:33 2017 +0100 Committer: Richard Downer <[email protected]> Committed: Tue Apr 18 13:35:45 2017 +0100 ---------------------------------------------------------------------- .../core/objs/proxy/InternalFactory.java | 20 ++++- .../core/entity/proxying/EntityManagerTest.java | 14 +++ .../RebindPolicyPrivateConstructorTest.java | 93 ++++++++++++++++++++ ...policy-private-no-arg-constructor-lplpmv3goo | 37 ++++++++ 4 files changed, 162 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4547cef4/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java index 0f7e79e..4af0900 100644 --- a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java +++ b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/InternalFactory.java @@ -20,7 +20,9 @@ package org.apache.brooklyn.core.objs.proxy; import static com.google.common.base.Preconditions.checkNotNull; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import java.util.Map; import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; @@ -30,11 +32,15 @@ import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.javalang.Reflections; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** */ public class InternalFactory { + private static final Logger LOG = LoggerFactory.getLogger(InternalFactory.class); + protected final ManagementContextInternal managementContext; /** @@ -68,7 +74,7 @@ public class InternalFactory { */ public static boolean isNewStyle(Class<?> clazz) { try { - clazz.getConstructor(new Class[0]); + clazz.getDeclaredConstructor(new Class[0]); return true; } catch (NoSuchMethodException e) { return false; @@ -130,7 +136,17 @@ public class InternalFactory { try { FactoryConstructionTracker.setConstructing(); try { - return clazz.newInstance(); + Constructor<T> constructor = clazz.getDeclaredConstructor(new Class[0]); + if (!(Modifier.isPublic(clazz.getModifiers()) && Modifier.isPublic(constructor.getModifiers())) + && !constructor.isAccessible()) { + try { + constructor.setAccessible(true); + LOG.warn("Set no-arg constructor accessible for "+clazz+" (deprecated; should have public no-arg constructor)"); + } catch (SecurityException e) { + LOG.warn("Unable to set no-arg constructor accessible for "+clazz+" (continuing, but may subsequently fail): " + e); + } + } + return constructor.newInstance(new Object[0]); } finally { FactoryConstructionTracker.reset(); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4547cef4/core/src/test/java/org/apache/brooklyn/core/entity/proxying/EntityManagerTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/proxying/EntityManagerTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/proxying/EntityManagerTest.java index 3b0b239..903a15a 100644 --- a/core/src/test/java/org/apache/brooklyn/core/entity/proxying/EntityManagerTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/entity/proxying/EntityManagerTest.java @@ -90,6 +90,20 @@ public class EntityManagerTest extends BrooklynAppUnitTestSupport { } @Test + public void testCreateEntityUsingPrivateConstructorFails() { + try { + TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class).impl(TestEntityPrivateConstructorImpl.class)); + Asserts.shouldHaveFailedPreviously("entity="+entity); + } catch (Exception e) { + Asserts.expectedFailureContains(e, "must have a no-argument constructor"); + } + } + private static class TestEntityPrivateConstructorImpl extends TestEntityImpl { + private TestEntityPrivateConstructorImpl() { + } + } + + @Test public void testGetEntities() { TestApplication app2 = ApplicationBuilder.newManagedApp(TestApplication.class, mgmt); TestEntity entity = app.createAndManageChild(EntitySpec.create(TestEntity.class)); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4547cef4/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyPrivateConstructorTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyPrivateConstructorTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyPrivateConstructorTest.java new file mode 100644 index 0000000..122c784 --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindPolicyPrivateConstructorTest.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.mgmt.rebind; + +import java.io.File; + +import org.apache.brooklyn.api.mgmt.rebind.RebindExceptionHandler; +import org.apache.brooklyn.api.mgmt.rebind.RebindManager.RebindFailureMode; +import org.apache.brooklyn.api.objs.BrooklynObjectType; +import org.apache.brooklyn.core.policy.AbstractPolicy; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.util.os.Os; +import org.apache.brooklyn.util.stream.Streams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.io.Files; + +public class RebindPolicyPrivateConstructorTest extends RebindTestFixtureWithApp { + + @SuppressWarnings("unused") + private static final Logger log = LoggerFactory.getLogger(RebindPolicyPrivateConstructorTest.class); + + @SuppressWarnings("unused") + private static class PrivatePolicy extends AbstractPolicy { + private PrivatePolicy() { + } + } + + @Override + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + super.setUp(); + } + + // See https://issues.apache.org/jira/browse/BROOKLYN-474 + // + // However, instead of using ZooKeeperEnsembleImpl$MemberTrackingPolicy (which would require + // being in `brooklyn-library` repo), we use a test policy written in a similar way - i.e. it + // has a private no-arg construtor. + @Test + public void testPolicyWithPrivateConstructor() throws Exception { + addMemento(BrooklynObjectType.POLICY, "policy-private-no-arg-constructor", "lplpmv3goo"); + rebind(); + } + + @Override + protected TestApplication rebind() throws Exception { + RebindExceptionHandler exceptionHandler = RebindExceptionHandlerImpl.builder() + .danglingRefFailureMode(RebindFailureMode.FAIL_AT_END) + .rebindFailureMode(RebindFailureMode.FAIL_AT_END) + .addConfigFailureMode(RebindFailureMode.FAIL_AT_END) + .addPolicyFailureMode(RebindFailureMode.FAIL_AT_END) + .loadPolicyFailureMode(RebindFailureMode.FAIL_AT_END) + .build(); + return super.rebind(RebindOptions.create().exceptionHandler(exceptionHandler)); + } + + protected void addMemento(BrooklynObjectType type, String label, String id) throws Exception { + String mementoFilename = label+"-"+id; + String memento = Streams.readFullyString(getClass().getResourceAsStream(mementoFilename)); + + File persistedFile = getPersistanceFile(type, id); + Files.write(memento.getBytes(), persistedFile); + } + + protected File getPersistanceFile(BrooklynObjectType type, String id) { + String dir; + switch (type) { + case POLICY: dir = "policies"; break; + default: throw new UnsupportedOperationException("type="+type); + } + return new File(mementoDir, Os.mergePaths(dir, id)); + } +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4547cef4/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/policy-private-no-arg-constructor-lplpmv3goo ---------------------------------------------------------------------- diff --git a/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/policy-private-no-arg-constructor-lplpmv3goo b/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/policy-private-no-arg-constructor-lplpmv3goo new file mode 100644 index 0000000..f6f0974 --- /dev/null +++ b/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/policy-private-no-arg-constructor-lplpmv3goo @@ -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. +--> + +<policy> + <brooklynVersion>0.11.0-SNAPSHOT</brooklynVersion> + <type>org.apache.brooklyn.core.mgmt.rebind.RebindPolicyPrivateConstructorTest$PrivatePolicy</type> + <id>lplpmv3goo</id> + <displayName>Members tracker</displayName> + <tags> + <string>MemberTrackingPolicy:ZooKeeperEnsembleImpl{id=stkwkmp76w}</string> + </tags> + <uniqueTag>MemberTrackingPolicy:ZooKeeperEnsembleImpl{id=stkwkmp76w}</uniqueTag> + <config> + <uniqueTag>MemberTrackingPolicy:ZooKeeperEnsembleImpl{id=stkwkmp76w}</uniqueTag> + <tags> + <set> + <string>MemberTrackingPolicy:ZooKeeperEnsembleImpl{id=stkwkmp76w}</string> + </set> + </tags> + </config> +</policy>
