View Javadoc
1   package org.apache.fulcrum.yaafi.framework.crypto;
2   
3   import java.io.InputStream;
4   
5   /*
6    * Licensed to the Apache Software Foundation (ASF) under one
7    * or more contributor license agreements.  See the NOTICE file
8    * distributed with this work for additional information
9    * regarding copyright ownership.  The ASF licenses this file
10   * to you under the Apache License, Version 2.0 (the
11   * "License"); you may not use this file except in compliance
12   * with the License.  You may obtain a copy of the License at
13   *
14   *   http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing,
17   * software distributed under the License is distributed on an
18   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19   * KIND, either express or implied.  See the License for the
20   * specific language governing permissions and limitations
21   * under the License.
22   */
23  
24  import org.apache.fulcrum.yaafi.framework.reflection.Clazz;
25  
26  /**
27   * Factory class to get a decrypting input stream for reading configuration
28   * files. The implementation uses dynamic class loading to make decryption an
29   * optional feature which is highly desirable when avoiding the ECCN export code
30   * problems.
31   *
32   * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl </a>
33   */
34  
35  public class CryptoStreamFactory {
36  	/** is the instance already initialized */
37  	private static boolean isInitialized;
38  
39  	/** the factory to create encrypting input streams */
40  	private static Object cryptoStreamFactory;
41  
42  	/** the name of the class to be loaded */
43  	private static String className = "org.apache.fulcrum.jce.crypto.CryptoStreamFactoryImpl";
44  
45  	/**
46  	 * Create a (potentially) decrypting input stream using the default password.
47  	 *
48  	 * @param is          the input stream to be decrypted
49  	 * @param isEncrypted the encryption mode (true|false|auto)
50  	 * @return a decrypting input stream
51  	 * @throws Exception reading the input stream failed
52  	 */
53  	public static InputStream getDecryptingInputStream(InputStream is, String isEncrypted) throws Exception {
54  		InputStream result;
55  
56  		if (isEncrypted.equalsIgnoreCase("true")) {
57  			// a decrypting input stream was requested
58  			result = createDecryptingInputStream(is, "getInputStream");
59  		} else if (isEncrypted.equalsIgnoreCase("auto") && hasCryptoStreamFactory()) {
60  			// no user-supplied preferences but crypto stream is available
61  			result = createDecryptingInputStream(is, "getSmartInputStream");
62  		} else if (isEncrypted.equalsIgnoreCase("auto") && !hasCryptoStreamFactory()) {
63  			// no user-supplied perferences so we fall back to normal input stream
64  			result = is;
65  		} else if (isEncrypted.equalsIgnoreCase("false")) {
66  			// just use normal input stream
67  			result = is;
68  		} else {
69  			throw new IllegalArgumentException("Unknown decryption mode : " + isEncrypted);
70  		}
71  
72  		return result;
73  	}
74  
75  	/**
76  	 * Factory method to create a decrypting input stream.
77  	 *
78  	 * @param is                the input stream to be decrypted
79  	 * @param factoryMethodName the name of the factory method
80  	 * @return a decrypting input stream
81  	 * @throws Exception creating the decrypting input stream failed
82  	 */
83  	private static InputStream createDecryptingInputStream(InputStream is, String factoryMethodName) throws Exception {
84  		Class[] signature = { InputStream.class };
85  		Object[] args = { is };
86  		Object cryptoStreamFactory = getCryptoStreamFactory();
87  
88  		if (cryptoStreamFactory == null) {
89  			throw new IllegalStateException(
90  					"No CryptoStreamFactory available - unable to create a decrypting input stream");
91  		} else {
92  			return (InputStream) Clazz.invoke(cryptoStreamFactory, factoryMethodName, signature, args);
93  		}
94  	}
95  
96  	/**
97  	 * Factory method to create a CryptoStreamFactory.
98  	 * 
99  	 * @return a CryptoStreamFactory
100 	 * @throws Exception generic exception
101 	 */
102 	private synchronized static Object getCryptoStreamFactory() throws Exception {
103 		if (!isInitialized) {
104 			isInitialized = true;
105 			ClassLoader clazzLoader = CryptoStreamFactory.class.getClassLoader();
106 
107 			if (Clazz.hasClazz(clazzLoader, className)) {
108 				Class[] signature = {};
109 				Object[] args = {};
110 				Class<?> clazz = Clazz.getClazz(clazzLoader, className);
111 				cryptoStreamFactory = Clazz.newInstance(clazz, signature, args);
112 			}
113 		}
114 
115 		return cryptoStreamFactory;
116 	}
117 
118 	/**
119 	 * @return true if a CryptoStreamFactory is available
120 	 * @throws Exception generic exception
121 	 */
122 	private static boolean hasCryptoStreamFactory() throws Exception {
123 		return getCryptoStreamFactory() != null;
124 	}
125 }