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 }