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.util.jsse;
018
019import java.io.FileInputStream;
020import java.io.FileNotFoundException;
021import java.io.IOException;
022import java.io.InputStream;
023import java.net.URL;
024import java.util.ArrayList;
025import java.util.List;
026
027import org.apache.camel.CamelContext;
028import org.apache.camel.CamelContextAware;
029import org.apache.camel.RuntimeCamelException;
030import org.apache.camel.spi.ClassResolver;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033
034/**
035 * Base class that provides optional integration with core Camel capabilities.
036 */
037public class JsseParameters implements CamelContextAware {
038    
039    private static final Logger LOG = LoggerFactory.getLogger(JsseParameters.class);
040    
041    private CamelContext context;
042
043    /**
044     * @see #setCamelContext(CamelContext)
045     */
046    public CamelContext getCamelContext() {
047        return context;
048    }
049
050    /**
051     * Sets the optional {@link CamelContext} used for integration with core capabilities
052     * such as Camel Property Placeholders and {@link ClassResolver}.
053     *
054     * @param context the context to use
055     */
056    public void setCamelContext(CamelContext context) {
057        this.context = context;
058    }
059    
060    /**
061     * Parses the value using the Camel Property Placeholder capabilities if
062     * a context is provided.  Otherwise returns {@code value} as is.
063     *
064     * @param value the string to replace property tokens in
065     * @return the value
066     * 
067     * @throws RuntimeCamelException if property placeholders were used and there was an error resolving them
068     *
069     * @see #setCamelContext(CamelContext)
070     */
071    protected String parsePropertyValue(String value) throws RuntimeCamelException {
072        if (this.getCamelContext() != null) {
073            try {
074                return this.getCamelContext().resolvePropertyPlaceholders(value);
075            } catch (Exception e) {
076                throw new RuntimeCamelException("Error parsing property value: " + value, e);
077            }
078        } else {
079            return value;
080        }
081    }
082    
083    /**
084     * Parses the values using the Camel Property Placeholder capabilities if
085     * a context is provided.  Otherwise returns {@code values} as is.
086     *
087     * @param values the list of strings to replace property tokens in
088     * @return the list of strings
089     * 
090     * @throws RuntimeCamelException if property placeholders were used and there was an error resolving them
091     *
092     * @see #parsePropertyValue(String)
093     */
094    protected List<String> parsePropertyValues(List<String> values) throws RuntimeCamelException {
095        if (this.getCamelContext() == null) {
096            return values;
097        } else {
098            List<String> parsedValues = new ArrayList<String>(values.size());
099            for (String value : values) {
100                parsedValues.add(this.parsePropertyValue(value));
101            }
102            return parsedValues;
103        }
104    }
105    
106    /**
107     * Attempts to loads a resource using a number of different approaches.
108     * The loading of the resource, is attempted by treating the resource as a file path,
109     * a class path resource, a URL, and using the Camel Context's {@link ClassResolver} 
110     * if a context is available in that order. An exception is thrown if the resource
111     * cannot be resolved to readable input stream using any of the above methods.
112     * 
113     * @param resource the resource location
114     * @return the input stream for the resource
115     *
116     * @throws IOException if the resource cannot be resolved using any of the above methods
117     * 
118     * @see #setCamelContext(CamelContext)
119     */
120    protected InputStream resolveResource(String resource) throws IOException {
121        InputStream is = null;
122
123        try {
124            LOG.trace("Trying to open resource [{}] as a file.", resource);
125            is = new FileInputStream(resource);
126            LOG.debug("Opened resource [{}] as a file.", resource);
127        } catch (FileNotFoundException e) {
128            LOG.trace("Could not open resource [" + resource + "] as a file.", e);
129        }
130        
131        if (is == null && Thread.currentThread().getContextClassLoader() != null) {
132            LOG.trace("Trying to open resource [{}] as a class path resource with the TCCL [{}].",
133                      resource, Thread.currentThread().getContextClassLoader());
134            is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
135            
136            if (is == null) {
137                LOG.trace("Could not open resource [{}] as a class path resource using the TCCL [{}].",
138                          resource, Thread.currentThread().getContextClassLoader());
139            } else {
140                LOG.debug("Opened resource [{}] as a class path resource with the TCCL [{}].",
141                          resource, Thread.currentThread().getContextClassLoader());
142            }
143        }
144
145        if (is == null) {
146            LOG.trace("Trying to open resource [{}] as a class path resource using the classloader [{}].",
147                      this.getClass().getClassLoader());
148            is = this.getClass().getResourceAsStream(resource);
149            
150            if (is == null) {
151                LOG.trace("Could not open resource [{}] as a class path resource using the classloader [{}].",
152                          resource, this.getClass().getClassLoader());
153            } else {
154                LOG.debug("Opened resource [{}] as a class path resource with the classloader [{}].",
155                          resource, this.getClass().getClassLoader());
156            }
157        }
158
159        if (is == null) {
160            try {
161                LOG.trace("Trying to open resource [{}] as a URL.", resource);
162                is = new URL(resource).openStream();
163                LOG.debug("Opened resource [{}] as a URL.", resource);
164            } catch (IOException e) {
165                LOG.trace("Could not open resource [" + resource + "] as a URL.", e);
166            }
167        }
168        
169        if (is == null && this.context != null) {
170            LOG.trace("Trying to open resource using the CamelContext ClassResolver [{}].", context.getClassResolver());
171            is = context.getClassResolver().loadResourceAsStream(resource);
172            if (is == null) {
173                LOG.trace("Could not to open resource [{}] using the CamelContext ClassResolver [{}].", 
174                          resource, context.getClassResolver());
175            } else {
176                LOG.debug("Opened resource [{}] using the CamelContext ClassResolver [{}].",
177                          resource, this.getClass().getClassLoader());
178            }
179        }
180
181        if (is == null) {
182            throw new IOException("Could not open " + resource + " as a file, class path resource, or URL.");
183        }
184        
185        return is;
186    }
187
188}