001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.impl;
018
019import org.apache.camel.CamelContext;
020import org.apache.camel.NoFactoryAvailableException;
021import org.apache.camel.NoSuchLanguageException;
022import org.apache.camel.spi.FactoryFinder;
023import org.apache.camel.spi.Language;
024import org.apache.camel.spi.LanguageResolver;
025import org.apache.camel.util.ResolverHelper;
026import org.slf4j.Logger;
027import org.slf4j.LoggerFactory;
028
029/**
030 * Default language resolver that looks for language factories in <b>META-INF/services/org/apache/camel/language/</b> and
031 * language resolvers in <b>META-INF/services/org/apache/camel/language/resolver/</b>.
032 *
033 * @version
034 */
035public class DefaultLanguageResolver implements LanguageResolver {
036    public static final String LANGUAGE_RESOURCE_PATH = "META-INF/services/org/apache/camel/language/";
037    public static final String LANGUAGE_RESOLVER_RESOURCE_PATH = LANGUAGE_RESOURCE_PATH + "resolver/";
038
039    private static final Logger LOG = LoggerFactory.getLogger(DefaultLanguageResolver.class);
040
041    protected FactoryFinder languageFactory;
042    protected FactoryFinder languageResolver;
043
044    public Language resolveLanguage(String name, CamelContext context) {
045        // lookup in registry first
046        Language languageReg = ResolverHelper.lookupLanguageInRegistryWithFallback(context, name);
047        if (languageReg != null) {
048            return languageReg;
049        }
050
051        Class<?> type = null;
052        try {
053            type = findLanguage(name, context);
054        } catch (NoFactoryAvailableException e) {
055            // ignore
056        } catch (Exception e) {
057            throw new IllegalArgumentException("Invalid URI, no Language registered for scheme: " + name, e);
058        }
059
060        if (type != null) {
061            if (Language.class.isAssignableFrom(type)) {
062                return (Language) context.getInjector().newInstance(type);
063            } else {
064                throw new IllegalArgumentException("Resolving language: " + name + " detected type conflict: Not a Language implementation. Found: " + type.getName());
065            }
066        } else {
067            // no specific language found then try fallback
068            return noSpecificLanguageFound(name, context);
069        }
070    }
071
072
073    protected Language noSpecificLanguageFound(String name, CamelContext context) {
074        Class<?> type = null;
075        try {
076            type = findLanguageResolver("default", context);
077        } catch (NoFactoryAvailableException e) {
078            // ignore
079        } catch (ClassNotFoundException e) {
080            // ignore
081        } catch (Exception e) {
082            throw new IllegalArgumentException("Invalid URI, no LanguageResolver registered for scheme: " + name, e);
083        }
084        if (type != null) {
085            if (LanguageResolver.class.isAssignableFrom(type)) {
086                LanguageResolver resolver = (LanguageResolver) context.getInjector().newInstance(type);
087                return resolver.resolveLanguage(name, context);
088            } else {
089                throw new IllegalArgumentException("Resolving language: " + name + " detected type conflict: Not a LanguageResolver implementation. Found: " + type.getName());
090            }
091        }
092        throw new NoSuchLanguageException(name);
093    }
094
095    protected Class<?> findLanguage(String name, CamelContext context) throws Exception {
096        if (languageFactory == null) {
097            languageFactory = context.getFactoryFinder(LANGUAGE_RESOURCE_PATH);
098        }
099        return languageFactory.findClass(name);
100    }
101
102    protected Class<?> findLanguageResolver(String name, CamelContext context) throws Exception {
103        if (languageResolver == null) {
104            languageResolver = context.getFactoryFinder(LANGUAGE_RESOLVER_RESOURCE_PATH);
105        }
106        return languageResolver.findClass(name);
107    }
108
109    protected Logger getLog() {
110        return LOG;
111    }
112}