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     */
017    package org.apache.camel.util.jsse;
018    
019    import java.io.FileInputStream;
020    import java.io.FileNotFoundException;
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.net.URL;
024    import java.util.ArrayList;
025    import java.util.List;
026    
027    import org.apache.camel.CamelContext;
028    import org.apache.camel.CamelContextAware;
029    import org.apache.camel.RuntimeCamelException;
030    import org.apache.camel.spi.ClassResolver;
031    import org.slf4j.Logger;
032    import org.slf4j.LoggerFactory;
033    
034    /**
035     * Base class that provides optional integration with core Camel capabilities.
036     */
037    public 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    }