blob: d7b50f2d42bddeee6d3ce12a2d5d8b8cf5147f8b [file] [log] [blame]
/**
* 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.cxf.dosgi.dsw.qos;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.cxf.binding.BindingConfiguration;
import org.apache.cxf.endpoint.AbstractEndpointFactory;
import org.apache.cxf.feature.Feature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class IntentManagerImpl implements IntentManager {
static final Logger LOG = LoggerFactory.getLogger(IntentManagerImpl.class);
private static final String PROVIDED_INTENT_VALUE = "PROVIDED";
private final IntentMap intentMap;
private final long maxIntentWaitTime;
public IntentManagerImpl(IntentMap intentMap) {
this(intentMap, 0);
}
public IntentManagerImpl(IntentMap intentMap, int maxIntentWaitTime) {
this.intentMap = intentMap;
this.maxIntentWaitTime = maxIntentWaitTime;
}
public String[] applyIntents(List<Feature> features, AbstractEndpointFactory factory,
Map<String, Object> props) throws IntentUnsatisfiedException {
Set<String> requestedIntents = IntentUtils.getRequestedIntents(props);
Set<String> appliedIntents = new HashSet<String>();
appliedIntents.addAll(reverseLookup(intentMap, PROVIDED_INTENT_VALUE));
boolean bindingApplied = false;
for (String intentName : requestedIntents) {
bindingApplied |= processIntent(features, factory, intentName, intentMap.get(intentName));
appliedIntents.add(intentName);
}
if (!bindingApplied) {
String defaultBindingName = "SOAP";
processIntent(features, factory, defaultBindingName, intentMap.get(defaultBindingName));
appliedIntents.add(defaultBindingName);
}
appliedIntents.addAll(addSynonymIntents(appliedIntents, intentMap));
return appliedIntents.toArray(new String[appliedIntents.size()]);
}
private boolean processIntent(List<Feature> features, AbstractEndpointFactory factory,
String intentName, Object intent) throws IntentUnsatisfiedException {
if (intent instanceof String) {
if (PROVIDED_INTENT_VALUE.equalsIgnoreCase((String) intent)) {
return false;
}
} else if (intent instanceof BindingConfiguration) {
BindingConfiguration bindingCfg = (BindingConfiguration)intent;
LOG.info("Applying intent: " + intentName + " via binding config: " + bindingCfg);
factory.setBindingConfig(bindingCfg);
return true;
} else if (intent instanceof Feature) {
Feature feature = (Feature) intent;
LOG.info("Applying intent: " + intentName + " via feature: " + feature);
features.add(feature);
return false;
} else {
LOG.info("No mapping for intent: " + intentName);
throw new IntentUnsatisfiedException(intentName);
}
return false;
}
private static Collection<String> addSynonymIntents(Collection<String> appliedIntents,
IntentMap map) {
// E.g. SOAP and SOAP.1_1 are synonyms
List<Object> values = new ArrayList<Object>();
for (String key : appliedIntents) {
values.add(map.get(key));
}
return reverseLookup(map, values);
}
private static Collection<String> reverseLookup(IntentMap im, Object obj) {
return reverseLookup(im, Collections.singleton(obj));
}
/**
* Retrieves all keys whose mapped values are found in the given collection.
*
* @param im an intent map
* @param values a collection of potential values
* @return all keys whose mapped values are found in the given collection
*/
private static Collection<String> reverseLookup(IntentMap im, Collection<?> values) {
Set<String> intentsFound = new HashSet<String>();
for (Map.Entry<String, Object> entry : im.entrySet()) {
if (values.contains(entry.getValue())) {
intentsFound.add(entry.getKey());
}
}
return intentsFound;
}
public void assertAllIntentsSupported(Map<String, Object> serviceProperties) {
long endTime = System.currentTimeMillis() + maxIntentWaitTime;
Set<String> requiredIntents = IntentUtils.getRequestedIntents(serviceProperties);
List<String> unsupportedIntents = new ArrayList<String>();
do {
unsupportedIntents.clear();
for (String ri : requiredIntents) {
if (!intentMap.containsKey(ri)) {
unsupportedIntents.add(ri);
}
}
long remainingSeconds = (endTime - System.currentTimeMillis()) / 1000;
if (!unsupportedIntents.isEmpty() && remainingSeconds > 0) {
LOG.debug("Waiting for custom intents " + unsupportedIntents + " timeout in " + remainingSeconds);
try {
synchronized (intentMap) {
intentMap.wait(1000);
}
} catch (InterruptedException e) {
LOG.warn(e.getMessage(), e);
}
}
} while (!unsupportedIntents.isEmpty() && System.currentTimeMillis() < endTime);
if (!unsupportedIntents.isEmpty()) {
throw new RuntimeException("service cannot be exported because the following "
+ "intents are not supported by this RSA: " + unsupportedIntents);
}
}
}