All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cf.service.ServiceBroker Maven / Gradle / Ivy

The newest version!
/*
 *   Copyright (c) 2013 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.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Implements a Cloud Foundry service broker. This broker does not implement the actual REST endpoint. This must be
 * done using Spring MVC or some other HTTP server technology. This class is intended to act as an intermediary between
 * a set of HTTP endpoints and a user provide implementation of {@link cf.service.Provisioner}.
 *
 * @author Mike Heath 
 * @deprecated Use the V2 services.
 */
@Deprecated
public class ServiceBroker {

	private static final Logger LOGGER = LoggerFactory.getLogger(ServiceBroker.class);

	/**
	 * The name of the HTTP header holding the service auth token.
	 */
	public static final String VCAP_SERVICE_TOKEN_HEADER = "X-VCAP-Service-Token";

	public static final String SERVICE_INSTANCE_ID = "service_id";
	public static final String SERVICE_BINDING_ID = "binding_id";

	public static final Pattern BINDING_PATTERN = Pattern.compile("/+gateway/v1/configurations/(.*?)/handles(/(.*))?");
	public static final Pattern INSTANCE_PATTERN = Pattern.compile("/+gateway/v1/configurations(/(.*))?");

	final private ObjectMapper mapper = new ObjectMapper();

	private final String authToken;
	private final Provisioner provisioner;

	public ServiceBroker(Provisioner provisioner, String authToken) {
		if (authToken == null) {
			throw new IllegalArgumentException("authToken can not be null");
		}
		this.provisioner = provisioner;
		this.authToken = authToken;

		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
	}

	public String createService(String authToken, byte[] body)
			throws ServiceBrokerException {
		LOGGER.debug("Creating service");

		validateAuthToken(authToken);
		final CreateRequest createRequest = decode(CreateRequest.class, body);
		final ServiceInstance serviceInstance = provisioner.create(createRequest);
		final ObjectNode gatewayData = mapper.createObjectNode();
		putAll(gatewayData, serviceInstance.getGatewayData());
		gatewayData.put(SERVICE_INSTANCE_ID, serviceInstance.getInstanceId());

		final ObjectNode credentials = mapper.createObjectNode();
		putAll(credentials, serviceInstance.getCredentials());

		final CreateResponse response = new CreateResponse(serviceInstance.getInstanceId(), gatewayData, credentials);

		return encode(response);
	}

	public String deleteService(String authToken, String uri)
			throws ServiceBrokerException {
		LOGGER.debug("Deleting service");
		validateAuthToken(authToken);
		final Matcher matcher = INSTANCE_PATTERN.matcher(uri);
		if (!matcher.matches() && matcher.groupCount() != 2) {
			throw new ResourceNotFoundException();
		}
		final String serviceInstanceId = matcher.group(2);
		provisioner.delete(serviceInstanceId);
		return "{}";
	}

	public String bindService(String authToken, byte[] body)
			throws ServiceBrokerException {
		LOGGER.debug("Binding service");
		validateAuthToken(authToken);
		final BindRequest bindRequest = decode(BindRequest.class, body);
		final ServiceBinding serviceBinding = provisioner.bind(bindRequest);

		final Map gatewayData = new HashMap<>(serviceBinding.getGatewayData());
		gatewayData.put(SERVICE_INSTANCE_ID, serviceBinding.getInstanceId());
		gatewayData.put(SERVICE_BINDING_ID, serviceBinding.getBindingId());

		final BindResponse bindResponse = new BindResponse(serviceBinding.getBindingId(), gatewayData, serviceBinding.getCredentials());

		return encode(bindResponse);
	}

	public String unbindService(String authToken, String uri) throws ServiceBrokerException {
		LOGGER.debug("Unbinding service");
		validateAuthToken(authToken);
		final Matcher matcher = BINDING_PATTERN.matcher(uri);
		if (!matcher.matches() && matcher.groupCount() != 3) {
			throw new ResourceNotFoundException();
		}
		final String instanceId = matcher.group(1);
		final String bindingId = matcher.group(2);
		provisioner.unbind(instanceId, bindingId);
		return "{}";
	}

	private void validateAuthToken(String authToken) throws AuthenticationException {
		if (!this.authToken.equals(authToken)) {
			LOGGER.warn("Received invalid service-auth-token from Cloud Controller.");
			throw new AuthenticationException();
		}
	}

	private  T decode(Class type, byte[] body) throws BadRequestException {
		try {
			return mapper.readValue(body, type);
		} catch (IOException e) {
			throw new BadRequestException();
		}
	}

	private String encode(Object object) {
		try {
			return mapper.writeValueAsString(object);
		} catch (JsonProcessingException e) {
			throw new RuntimeException(e);
		}
	}

	private void putAll(ObjectNode object, Map map) {
		for (Map.Entry entry : map.entrySet()) {
			final JsonNode value;
			if (entry.getValue() instanceof JsonNode) {
				value = (JsonNode) entry.getValue();
			} else {
				value = mapper.valueToTree(entry.getValue());
			}
			object.put(entry.getKey(), value);
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy