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; + } + +}
