/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES 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.camp.brooklyn.spi.creation; import java.util.List; import java.util.Set; import org.apache.brooklyn.api.entity.Application; import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; import org.apache.brooklyn.camp.CampPlatform; import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator; import org.apache.brooklyn.camp.spi.Assembly; import org.apache.brooklyn.camp.spi.AssemblyTemplate; import org.apache.brooklyn.camp.spi.PlatformComponentTemplate; import org.apache.brooklyn.camp.spi.collection.ResolvableLink; import org.apache.brooklyn.core.mgmt.EntityManagementUtils; import org.apache.brooklyn.core.mgmt.EntityManagementUtils.CreationResult; import org.apache.brooklyn.core.mgmt.HasBrooklynManagementContext; import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext; import org.apache.brooklyn.util.collections.MutableSet; import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.Lists; public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator { private static final Logger log = LoggerFactory.getLogger(BrooklynAssemblyTemplateInstantiator.class); public static final String NEVER_UNWRAP_APPS_PROPERTY = "wrappedApp"; @Override public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) { Application app = create(template, platform); CreationResult<Application, Void> start = EntityManagementUtils.start(app); log.debug("CAMP created "+app+"; starting in "+start.task()); return platform.assemblies().get(app.getApplicationId()); } private Application create(AssemblyTemplate template, CampPlatform platform) { ManagementContext mgmt = getManagementContext(platform); BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt); EntitySpec<? extends Application> spec = createApplicationSpec(template, platform, loader, MutableSet.<String>of()); Application instance = mgmt.getEntityManager().createEntity(spec); log.info("CAMP created '{}'", instance); return instance; } @Override public List<EntitySpec<?>> createServiceSpecs( AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext itemLoader, Set<String> encounteredRegisteredTypeIds) { return buildTemplateServicesAsSpecs(itemLoader, template, platform, encounteredRegisteredTypeIds); } @Override public EntitySpec<? extends Application> createApplicationSpec( AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader, Set<String> encounteredTypeSymbolicNames) { log.debug("CAMP creating application instance for {} ({})", template.getId(), template); // AssemblyTemplates created via PDP, _specifying_ then entities to put in EntitySpec<? extends Application> app = CampInternalUtils.createWrapperApp(template, loader); app.configure(EntityManagementUtils.WRAPPER_APP_MARKER, Boolean.TRUE); // first build the children into an empty shell app List<EntitySpec<?>> childSpecs = createServiceSpecs(template, platform, loader, encounteredTypeSymbolicNames); for (EntitySpec<?> childSpec : childSpecs) { // children get parsed and unwrapped irrespective of the NEVER_UNWRAP_APPS setting; // we could support a NEVER_UNWRAP_NESTED_ENTITIES item but i don't know if there's a use case app.child(EntityManagementUtils.unwrapEntity(childSpec)); } if (allowedToUnwrap(template, app)) { app = EntityManagementUtils.unwrapApplication(app); } return app; } private boolean allowedToUnwrap(AssemblyTemplate template, EntitySpec<? extends Application> app) { return !(Boolean.TRUE.equals(TypeCoercions.coerce(template.getCustomAttributes().get(NEVER_UNWRAP_APPS_PROPERTY), Boolean.class))); } private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform, Set<String> encounteredRegisteredTypeIds) { List<EntitySpec<?>> result = Lists.newArrayList(); for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) { PlatformComponentTemplate appChildComponentTemplate = ctl.resolve(); BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, appChildComponentTemplate); EntitySpec<?> spec = entityResolver.resolveSpec(encounteredRegisteredTypeIds); result.add(spec); } return result; } private static ManagementContext getManagementContext(CampPlatform platform) { return ((HasBrooklynManagementContext)platform).getBrooklynManagementContext(); } }