http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java deleted file mode 100644 index 18bc5cc..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/ManagementPlaneSyncRecordPersisterToObjectStore.java +++ /dev/null @@ -1,364 +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 org.apache.brooklyn.core.mgmt.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 java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityMode; -import org.apache.brooklyn.api.mgmt.ha.ManagementNodeState; -import org.apache.brooklyn.api.mgmt.ha.ManagementNodeSyncRecord; -import org.apache.brooklyn.api.mgmt.ha.ManagementPlaneSyncRecord; -import org.apache.brooklyn.api.mgmt.ha.ManagementPlaneSyncRecordPersister; -import org.apache.brooklyn.core.mgmt.ha.dto.BasicManagementNodeSyncRecord; -import org.apache.brooklyn.core.mgmt.ha.dto.ManagementPlaneSyncRecordImpl; -import org.apache.brooklyn.core.mgmt.persist.MementoSerializer; -import org.apache.brooklyn.core.mgmt.persist.PersistenceObjectStore; -import org.apache.brooklyn.core.mgmt.persist.RetryingMementoSerializer; -import org.apache.brooklyn.core.mgmt.persist.StoreObjectAccessorLocking; -import org.apache.brooklyn.core.mgmt.persist.XmlMementoSerializer; -import org.apache.brooklyn.core.mgmt.persist.PersistenceObjectStore.StoreObjectAccessorWithLock; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.text.Strings; -import org.apache.brooklyn.util.time.Duration; -import org.apache.brooklyn.util.time.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -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; - - protected final AtomicLong checkpointLogCount = new AtomicLong(); - private static final int INITIAL_LOG_WRITES = 5; - - @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(org.apache.brooklyn.core.mgmt.persist.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() && shouldLogCheckpoint()) 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; - } - - protected boolean shouldLogCheckpoint() { - long logCount = checkpointLogCount.incrementAndGet(); - return (logCount < INITIAL_LOG_WRITES) || (logCount % 1000 == 0); - } - -}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/MasterChooser.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/MasterChooser.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/MasterChooser.java deleted file mode 100644 index 0209fa2..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/MasterChooser.java +++ /dev/null @@ -1,39 +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 org.apache.brooklyn.core.mgmt.ha; - -import org.apache.brooklyn.api.mgmt.ha.ManagementNodeSyncRecord; -import org.apache.brooklyn.api.mgmt.ha.ManagementPlaneSyncRecord; -import org.apache.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); - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java deleted file mode 100644 index ba56b98..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java +++ /dev/null @@ -1,300 +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 org.apache.brooklyn.core.mgmt.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.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle; -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.BrooklynVersion; -import org.apache.brooklyn.core.server.BrooklynServerConfig; -import org.apache.brooklyn.core.server.BrooklynServerPaths; -import org.apache.brooklyn.rt.felix.EmbeddedFelixFramework; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.collections.MutableSet; -import org.apache.brooklyn.util.core.osgi.Osgis; -import org.apache.brooklyn.util.core.osgi.Osgis.BundleFinder; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.guava.Maybe; -import org.apache.brooklyn.util.os.Os; -import org.apache.brooklyn.util.os.Os.DeletionResult; -import org.apache.brooklyn.util.repeat.Repeater; -import org.apache.brooklyn.util.text.Strings; -import org.apache.brooklyn.util.time.Duration; -import org.osgi.framework.Bundle; -import org.osgi.framework.launch.Framework; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; - -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.getFramework(osgiCacheDir.getAbsolutePath(), false); - } catch (Exception e) { - throw Exceptions.propagate(e); - } - } - - public void stop() { - Osgis.ungetFramework(framework); - 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>() { - @Override - 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.isNameResolved() || - (bundle.getSymbolicName().equals(b.getSymbolicName()) && - bundle.getVersion().equals(b.getVersion().toString())); - } - - public <T> Maybe<Class<T>> tryResolveClass(String type, OsgiBundleWithUrl... osgiBundles) { - return tryResolveClass(type, Arrays.asList(osgiBundles)); - } - public <T> Maybe<Class<T>> tryResolveClass(String type, Iterable<? extends OsgiBundleWithUrl> osgiBundles) { - Map<OsgiBundleWithUrl,Throwable> bundleProblems = MutableMap.of(); - Set<String> extraMessages = MutableSet.of(); - for (OsgiBundleWithUrl osgiBundle: osgiBundles) { - try { - Maybe<Bundle> bundle = findBundle(osgiBundle); - if (bundle.isPresent()) { - Bundle b = bundle.get(); - Class<T> clazz; - //Extension bundles don't support loadClass. - //Instead load from the app classpath. - if (EmbeddedFelixFramework.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(osgiBundle, ((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(osgiBundle, 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 "+osgiBundle+" 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(OsgiBundleWithUrl 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<? extends OsgiBundleWithUrl> osgiBundles) { - for (OsgiBundleWithUrl osgiBundle: osgiBundles) { - try { - Maybe<Bundle> bundle = findBundle(osgiBundle); - if (bundle.isPresent()) { - URL result = bundle.get().getResource(name); - if (result!=null) return result; - } - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - } - } - return null; - } - - /** - * @return URL's to all resources matching the given name (using {@link Bundle#getResources(String)} in the referenced osgi bundles. - */ - public Iterable<URL> getResources(String name, Iterable<? extends OsgiBundleWithUrl> osgiBundles) { - Set<URL> resources = Sets.newLinkedHashSet(); - for (OsgiBundleWithUrl catalogBundle : osgiBundles) { - 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/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/dto/BasicManagementNodeSyncRecord.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/dto/BasicManagementNodeSyncRecord.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/dto/BasicManagementNodeSyncRecord.java deleted file mode 100644 index d8f18b1..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/dto/BasicManagementNodeSyncRecord.java +++ /dev/null @@ -1,194 +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 org.apache.brooklyn.core.mgmt.ha.dto; - -import java.io.Serializable; -import java.net.URI; - -import org.apache.brooklyn.api.mgmt.ha.ManagementNodeState; -import org.apache.brooklyn.api.mgmt.ha.ManagementNodeSyncRecord; -import org.apache.brooklyn.core.BrooklynVersion; -import org.apache.brooklyn.util.time.Time; -import org.codehaus.jackson.annotate.JsonAutoDetect; -import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; - -import com.google.common.base.Objects; - -/** - * Represents the state of a management node within the Brooklyn management plane - * (DTO class). - * - * @author aled - */ -@JsonAutoDetect(fieldVisibility=Visibility.ANY, getterVisibility=Visibility.NONE) -public class BasicManagementNodeSyncRecord implements ManagementNodeSyncRecord, Serializable { - - private static final long serialVersionUID = 4918161834047884244L; - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String brooklynVersion = BrooklynVersion.get(); - protected String nodeId; - protected URI uri; - protected ManagementNodeState status; - protected Long priority; - protected long localTimestamp; - protected Long remoteTimestamp; - - protected Builder self() { - return (Builder) this; - } - public Builder brooklynVersion(String val) { - brooklynVersion = val; return self(); - } - public Builder nodeId(String val) { - nodeId = val; return self(); - } - public Builder uri(URI val) { - uri = val; return self(); - } - public Builder status(ManagementNodeState val) { - status = val; return self(); - } - public Builder priority(Long val) { - priority = val; return self(); - } - public Builder localTimestamp(long val) { - localTimestamp = val; return self(); - } - public Builder remoteTimestamp(Long val) { - remoteTimestamp = val; return self(); - } - public Builder from(ManagementNodeSyncRecord other) { - return from(other, false); - } - public Builder from(ManagementNodeSyncRecord other, boolean ignoreNulls) { - if (ignoreNulls && other==null) return this; - if (other.getBrooklynVersion()!=null) brooklynVersion = other.getBrooklynVersion(); - if (other.getNodeId()!=null) nodeId = other.getNodeId(); - if (other.getUri()!=null) uri = other.getUri(); - if (other.getStatus()!=null) status = other.getStatus(); - if (other.getPriority()!=null) priority = other.getPriority(); - if (other.getLocalTimestamp()>0) localTimestamp = other.getLocalTimestamp(); - if (other.getRemoteTimestamp()!=null) remoteTimestamp = other.getRemoteTimestamp(); - return this; - } - public ManagementNodeSyncRecord build() { - return new BasicManagementNodeSyncRecord(this); - } - } - - private String brooklynVersion; - private String nodeId; - private URI uri; - private ManagementNodeState status; - private Long priority; - private Long localTimestamp; - private Long remoteTimestamp; - - /** @deprecated since 0.7.0, use {@link #localTimestamp} or {@link #remoteTimestamp}, - * but kept (or rather added back in) to support deserializing previous instances */ - @Deprecated - private Long timestampUtc; - - - // for de-serialization - @SuppressWarnings("unused") - private BasicManagementNodeSyncRecord() { - } - - // Trusts the builder to not mess around with mutability concurrently with build(). - protected BasicManagementNodeSyncRecord(Builder builder) { - brooklynVersion = builder.brooklynVersion; - nodeId = builder.nodeId; - uri = builder.uri; - status = builder.status; - priority = builder.priority; - localTimestamp = builder.localTimestamp; - remoteTimestamp = builder.remoteTimestamp; - } - - @Override - public String getBrooklynVersion() { - return brooklynVersion; - } - - @Override - public String getNodeId() { - return nodeId; - } - - @Override - public URI getUri() { - return uri; - } - - @Override - public ManagementNodeState getStatus() { - return status; - } - - @Override - public Long getPriority() { - return priority; - } - - @Override - public long getLocalTimestamp() { - if (localTimestamp!=null) return localTimestamp; - if (timestampUtc!=null) return timestampUtc; - throw new NullPointerException("localTimestamp not known for "+getNodeId()); - } - - @Override - public Long getRemoteTimestamp() { - return remoteTimestamp; - } - - @Override - public String toString() { - return Objects.toStringHelper(this) - .add("nodeId", getNodeId()) - .add("status", getStatus()).toString(); - } - - @Override - public String toVerboseString() { - return Objects.toStringHelper(this) - .omitNullValues() - .add("brooklynVersion", getBrooklynVersion()) - .add("nodeId", getNodeId()) - .add("uri", getUri()) - .add("status", getStatus()) - .add("priority", getPriority()) - .add("localTimestamp", getLocalTimestamp()+"="+Time.makeDateString(getLocalTimestamp())) - .add("remoteTimestamp", getRemoteTimestamp()+(getRemoteTimestamp()==null ? "" : - "="+Time.makeDateString(getRemoteTimestamp()))) - .toString(); - } - - /** used here for store to inject remote timestamp */ - public void setRemoteTimestamp(Long remoteTimestamp) { - this.remoteTimestamp = remoteTimestamp; - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/dto/ManagementPlaneSyncRecordImpl.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/dto/ManagementPlaneSyncRecordImpl.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/dto/ManagementPlaneSyncRecordImpl.java deleted file mode 100644 index dd89320..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/dto/ManagementPlaneSyncRecordImpl.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 org.apache.brooklyn.core.mgmt.ha.dto; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import java.io.Serializable; -import java.util.Map; - -import org.apache.brooklyn.api.mgmt.ha.ManagementNodeSyncRecord; -import org.apache.brooklyn.api.mgmt.ha.ManagementPlaneSyncRecord; -import org.apache.brooklyn.util.collections.MutableMap; - -import com.google.common.base.Objects; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; - -public class ManagementPlaneSyncRecordImpl implements ManagementPlaneSyncRecord, Serializable { - - private static final long serialVersionUID = -4207907303446336973L; - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - protected String masterNodeId; - protected final Map<String,ManagementNodeSyncRecord> nodes = MutableMap.of(); - - public Builder masterNodeId(String val) { - masterNodeId = val; return this; - } - public Builder nodes(Iterable<ManagementNodeSyncRecord> vals) { - checkState(!Iterables.contains(checkNotNull(vals, "nodes must not be null"), null), "nodes must not contain null: %s", vals); - for (ManagementNodeSyncRecord val: vals) nodes.put(val.getNodeId(), val); - return this; - } - public Builder node(ManagementNodeSyncRecord val) { - checkNotNull(val, "node must not be null"); - nodes.put(val.getNodeId(), val); - return this; - } - public ManagementPlaneSyncRecord build() { - return new ManagementPlaneSyncRecordImpl(this); - } - } - - private String masterNodeId; - private Map<String, ManagementNodeSyncRecord> managementNodes; - - private ManagementPlaneSyncRecordImpl(Builder builder) { - masterNodeId = builder.masterNodeId; - managementNodes = Maps.newLinkedHashMap(); - for (ManagementNodeSyncRecord node : builder.nodes.values()) { - checkState(!managementNodes.containsKey(node.getNodeId()), "duplicate nodeId %s", node.getNodeId()); - managementNodes.put(node.getNodeId(), node); - } - } - - @Override - public String getMasterNodeId() { - return masterNodeId; - } - - @Override - public Map<String, ManagementNodeSyncRecord> getManagementNodes() { - return managementNodes; - } - - @Override - public String toString() { - return Objects.toStringHelper(this) - .add("masterNodeId", masterNodeId) - .add("nodes", managementNodes.keySet()) - .toString(); - } - - @Override - public String toVerboseString() { - return toString(); - } -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java deleted file mode 100644 index da9fcae..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java +++ /dev/null @@ -1,522 +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 org.apache.brooklyn.core.mgmt.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.apache.brooklyn.api.catalog.BrooklynCatalog; -import org.apache.brooklyn.api.effector.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.location.Location; -import org.apache.brooklyn.api.location.LocationRegistry; -import org.apache.brooklyn.api.mgmt.ExecutionContext; -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.api.mgmt.SubscriptionContext; -import org.apache.brooklyn.api.mgmt.Task; -import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; -import org.apache.brooklyn.api.mgmt.entitlement.EntitlementManager; -import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityManager; -import org.apache.brooklyn.api.mgmt.rebind.RebindManager; -import org.apache.brooklyn.api.objs.BrooklynObject; -import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry; -import org.apache.brooklyn.api.typereg.RegisteredType; -import org.apache.brooklyn.config.StringConfigMap; -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.entity.AbstractEntity; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.entity.drivers.BasicEntityDriverManager; -import org.apache.brooklyn.core.entity.drivers.downloads.BasicDownloadsManager; -import org.apache.brooklyn.core.internal.BrooklynProperties; -import org.apache.brooklyn.core.internal.storage.BrooklynStorage; -import org.apache.brooklyn.core.internal.storage.DataGrid; -import org.apache.brooklyn.core.internal.storage.DataGridFactory; -import org.apache.brooklyn.core.internal.storage.impl.BrooklynStorageImpl; -import org.apache.brooklyn.core.internal.storage.impl.inmemory.InMemoryDataGridFactory; -import org.apache.brooklyn.core.location.BasicLocationRegistry; -import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; -import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext; -import org.apache.brooklyn.core.mgmt.entitlement.Entitlements; -import org.apache.brooklyn.core.mgmt.ha.HighAvailabilityManagerImpl; -import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl; -import org.apache.brooklyn.core.typereg.BasicBrooklynTypeRegistry; -import org.apache.brooklyn.util.collections.MutableList; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.ResourceUtils; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.task.BasicExecutionContext; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.groovy.GroovyJavaMethods; -import org.apache.brooklyn.util.guava.Maybe; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Function; -import com.google.common.base.Objects; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSet; - -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) { - RegisteredType item = internal.getManagementContext().getTypeRegistry().get(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 DeferredBrooklynProperties configMap; - protected BasicLocationRegistry locationRegistry; - protected final BasicBrooklynCatalog catalog; - protected final BrooklynTypeRegistry typeRegistry; - 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; - - protected final ExternalConfigSupplierRegistry configSupplierRegistry; - - 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 = new DeferredBrooklynProperties(brooklynProperties, this); - 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.typeRegistry = new BasicBrooklynTypeRegistry(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); - this.configSupplierRegistry = new BasicExternalConfigSupplierRegistry(this); // TODO leaking "this" reference; yuck - } - - @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) { - ImmutableSet<Object> tags = ImmutableSet.<Object>of( - BrooklynTaskTags.tagForContextEntity(e), - this - ); - return new BasicExecutionContext(MutableMap.of("tags", tags), 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 - ImmutableSet<Object> tags = ImmutableSet.<Object>of( - this, - BrooklynTaskTags.BROOKLYN_SERVER_TASK_TAG - ); - return new BasicExecutionContext(MutableMap.of("tags", tags), 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 SubscriptionContext getSubscriptionContext(Location loc) { - // BSC is a thin wrapper around SM so fine to create a new one here - return new BasicSubscriptionContext(getSubscriptionManager(), loc); - } - - @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; - } - - private final Object locationRegistrySemaphore = new Object(); - - @Override - public LocationRegistry getLocationRegistry() { - // NB: can deadlock if synched on whole LMC - synchronized (locationRegistrySemaphore) { - 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().setManagementContext(this); - getCatalogInitialization().populateUnofficial(catalog); - } - return catalog; - } - - @Override - public BrooklynTypeRegistry getTypeRegistry() { - return typeRegistry; - } - - @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.setManagementContext(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; - } - - /** @since 0.8.0 */ - @Override - public ExternalConfigSupplierRegistry getExternalConfigProviderRegistry() { - return configSupplierRegistry; - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractSubscriptionManager.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractSubscriptionManager.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractSubscriptionManager.java deleted file mode 100644 index dc454e2..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/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 org.apache.brooklyn.core.mgmt.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.mgmt.SubscriptionHandle; -import org.apache.brooklyn.api.mgmt.SubscriptionManager; -import org.apache.brooklyn.api.sensor.Sensor; -import org.apache.brooklyn.api.sensor.SensorEvent; -import org.apache.brooklyn.api.sensor.SensorEventListener; -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/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AccessManager.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AccessManager.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AccessManager.java deleted file mode 100644 index c2130ed..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/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 org.apache.brooklyn.core.mgmt.internal; - -import org.apache.brooklyn.api.mgmt.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/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AsyncCollectionChangeAdapter.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AsyncCollectionChangeAdapter.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AsyncCollectionChangeAdapter.java deleted file mode 100644 index 3ffdf5f..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AsyncCollectionChangeAdapter.java +++ /dev/null @@ -1,82 +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 org.apache.brooklyn.core.mgmt.internal; - -import static com.google.common.base.Preconditions.checkNotNull; - -import org.apache.brooklyn.api.mgmt.ExecutionManager; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.task.BasicExecutionManager; -import org.apache.brooklyn.util.core.task.SingleThreadedScheduler; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -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/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java deleted file mode 100644 index 6b261db..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/BasicExternalConfigSupplierRegistry.java +++ /dev/null @@ -1,125 +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 org.apache.brooklyn.core.mgmt.internal; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.core.config.ConfigPredicates; -import org.apache.brooklyn.core.config.ConfigUtils; -import org.apache.brooklyn.core.config.external.ExternalConfigSupplier; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.javalang.Reflections; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Optional; -import com.google.common.collect.Maps; - -/** - * Simple registry implementation. - * - * Permits a number of {@link ExternalConfigSupplier} instances to be registered, each with a unique name, for future - * (deferred) lookup of configuration values. - */ -public class BasicExternalConfigSupplierRegistry implements ExternalConfigSupplierRegistry { - - private static final Logger LOG = LoggerFactory.getLogger(BasicExternalConfigSupplierRegistry.class); - - private final Map<String, ExternalConfigSupplier> providersByName = Maps.newLinkedHashMap(); - private final Object providersMapMutex = new Object(); - - public BasicExternalConfigSupplierRegistry(ManagementContext mgmt) { - updateFromBrooklynProperties(mgmt); - } - - @Override - public void addProvider(String name, ExternalConfigSupplier supplier) { - synchronized (providersMapMutex) { - if (providersByName.containsKey(name)) - throw new IllegalArgumentException("Provider already registered with name '" + name + "'"); - providersByName.put(name, supplier); - } - LOG.info("Added external config supplier named '" + name + "': " + supplier); - } - - @Override - public void removeProvider(String name) { - synchronized (providersMapMutex) { - ExternalConfigSupplier supplier = providersByName.remove(name); - LOG.info("Removed external config supplier named '" + name + "': " + supplier); - } - } - - @Override - public String getConfig(String providerName, String key) { - synchronized (providersMapMutex) { - ExternalConfigSupplier provider = providersByName.get(providerName); - if (provider == null) - throw new IllegalArgumentException("No provider found with name '" + providerName + "'"); - return provider.get(key); - } - } - - @SuppressWarnings("unchecked") - private void updateFromBrooklynProperties(ManagementContext mgmt) { - // form is: - // brooklyn.external.<name> : fully.qualified.ClassName - // brooklyn.external.<name>.<key> : <value> - // brooklyn.external.<name>.<key> : <value> - // brooklyn.external.<name>.<key> : <value> - - String EXTERNAL_PROVIDER_PREFIX = "brooklyn.external."; - Map<String, Object> externalProviderProperties = mgmt.getConfig().submap(ConfigPredicates.startingWith(EXTERNAL_PROVIDER_PREFIX)).asMapWithStringKeys(); - ClassLoader classloader = mgmt.getCatalogClassLoader(); - List<Exception> exceptions = new LinkedList<Exception>(); - - for (String key : externalProviderProperties.keySet()) { - String strippedKey = key.substring(EXTERNAL_PROVIDER_PREFIX.length()); - if (strippedKey.contains(".")) - continue; - - String name = strippedKey; - String providerClassname = (String) externalProviderProperties.get(key); - Map<String, Object> config = ConfigUtils.filterForPrefixAndStrip(externalProviderProperties, key + "."); - - try { - Optional<ExternalConfigSupplier> configSupplier = Reflections.invokeConstructorWithArgs(classloader, providerClassname, mgmt, name, config); - if (!configSupplier.isPresent()) { - configSupplier = Reflections.invokeConstructorWithArgs(classloader, providerClassname, mgmt, name); - } - if (!configSupplier.isPresent()) { - throw new IllegalStateException("No matching constructor found in "+providerClassname); - } - - addProvider(name, configSupplier.get()); - - } catch (Exception e) { - LOG.error("Failed to instantiate external config supplier named '" + name + "': " + e, e); - exceptions.add(e); - } - } - - if (!exceptions.isEmpty()) - Exceptions.propagate(exceptions); - } - -}
