/* * Copyright (c) 2014 Intellectual Reserve, Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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 cf.spring.servicebroker; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.BeanExpressionResolver; import cf.spring.servicebroker.Catalog.CatalogService; import cf.spring.servicebroker.Catalog.ServiceDashboardClient; /** * Extension of {@link AbstractAnnotationCatalogAccessorProvider} building * the catalog from beans annotated with {@link ServiceBroker}. Services * are completely defined by this annotation (static catalog). * * @author Sebastien Gerard * @see cf.spring.servicebroker.ServiceBroker * @see Service * @see ServicePlan */ public class AnnotationCatalogAccessorProvider extends AbstractAnnotationCatalogAccessorProvider implements InitializingBean { private final BeanExpressionResolver expressionResolver; private final BeanExpressionContext expressionContext; private CatalogAccessor catalogAccessor; public AnnotationCatalogAccessorProvider(BeanExpressionResolver expressionResolver, BeanExpressionContext expressionContext) { this.expressionResolver = expressionResolver; this.expressionContext = expressionContext; } @Override public CatalogAccessor getCatalogAccessor() { return catalogAccessor; } protected CatalogAccessor initializeAccessor() { final List<BrokerServiceAccessor> serviceAccessors = new ArrayList<>(); final String[] serviceBrokers = context.getBeanNamesForAnnotation(ServiceBroker.class); for (String serviceBrokerName : serviceBrokers) { final Class<?> clazz = getBeanClass(serviceBrokerName); final ServiceBroker serviceBroker = clazz.getAnnotation(ServiceBroker.class); for (Service service : serviceBroker.value()) { final CatalogService catalogService = buildCatalogService(service); serviceAccessors.add(getMethodAccessor(serviceBrokerName, catalogService)); } } return new CatalogAccessor(serviceAccessors); } protected CatalogService buildCatalogService(Service service) { final String id = evaluate(service.id()); final String name = evaluate(service.name()); final String description = evaluate(service.description()); final boolean bindable = Boolean.valueOf(evaluate(service.bindable())); final boolean planUpdatable = Boolean.valueOf(evaluate(service.planUpdatable())); final List<String> tags = new ArrayList<>(); for (String tag : service.tags()) { tags.add(evaluate(tag)); } final Catalog.ServiceDashboardClient dashboardClient = buildDashboardClient(service.dashboardClient()); final Map<String, Object> metadata = buildMetadata(service.metadata()); final List<String> requires = new ArrayList<>(); for (Permission permission : service.requires()) { requires.add(permission.toString()); } final List<Catalog.Plan> plans = new ArrayList<>(); for (ServicePlan servicePlan : service.plans()) { final String planId = evaluate(servicePlan.id()); final String planName = evaluate(servicePlan.name()); final String planDescription = evaluate(servicePlan.description()); final boolean free = Boolean.valueOf(evaluate(servicePlan.free())); final Map<String, Object> planMetadata = buildMetadata(servicePlan.metadata()); plans.add(new Catalog.Plan(planId, planName, planDescription, free, planMetadata)); } return new CatalogService(id, name, description, bindable, tags, metadata, requires, plans, dashboardClient, planUpdatable); } private ServiceDashboardClient buildDashboardClient(DashboardClient dashboardClient) { return isFilled(dashboardClient) ? new ServiceDashboardClient(dashboardClient.id(), dashboardClient.secret(), dashboardClient.redirectUri()) : null; } private Map<String, Object> buildMetadata(Metadata[] metadata) { final Map<String, Object> metadataObject = new HashMap<>(); for (Metadata metadatum : metadata) { final List<Object> values = new ArrayList<>(); for (String value : metadatum.value()) { values.add(expressionResolver.evaluate(value, expressionContext)); } final String key = evaluate(metadatum.field()); if (values.size() == 1) { metadataObject.put(key, values.get(0)); } else { metadataObject.put(key, values); } } return metadataObject; } private String evaluate(String expression) { return expressionResolver.evaluate(expression, expressionContext).toString(); } private boolean isFilled(DashboardClient dashboardClient) { final String id = dashboardClient.id(); final String secret = dashboardClient.secret(); final String redirectUri = dashboardClient.redirectUri(); if (id.isEmpty() && secret.isEmpty() && redirectUri.isEmpty()) { return false; } else if (!id.isEmpty() && !secret.isEmpty() && !redirectUri.isEmpty()) { return true; } else { throw new IllegalArgumentException("If an argument of the " + DashboardClient.class.getSimpleName() + " is not null, all arguments must be specified."); } } @Override public void afterPropertiesSet() { this.catalogAccessor = initializeAccessor(); } }