1 /***
2 *
3 * Copyright 2004 Protique Ltd
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18 package org.activeio;
19
20 import java.io.BufferedInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URI;
24 import java.util.HashMap;
25 import java.util.Properties;
26
27 import org.activeio.adapter.AsynchToSynchChannelFactoryAdaptor;
28 import org.activeio.adapter.SynchToAsynchChannelFactoryAdaptor;
29
30 import EDU.oswego.cs.dl.util.concurrent.Executor;
31 import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
32 import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;
33
34 /***
35 * A {@see ChannelFactory}uses the requested URI's scheme to determine the
36 * actual {@see org.activeio.SynchChannelFactory}or
37 * {@see org.activeio.AsynchChannelFactory}implementation to use to create it's
38 * {@see org.activeio.Channel}s and {@see org.activeio.ChannelServer}s.
39 *
40 * Each URI scheme that {@see ChannelFactory}object handles will have a
41 * properties file located at: "META-INF/org.activeio.ChannelFactory/{scheme}".
42 *
43 */
44 public class ChannelFactory implements SynchChannelFactory, AsynchChannelFactory {
45
46 private final HashMap synchChannelFactoryMap = new HashMap();
47 private final HashMap asynchChannelFactoryMap = new HashMap();
48
49
50 static public final Executor DEFAULT_EXECUTOR = new PooledExecutor();
51 static {
52 ((PooledExecutor) DEFAULT_EXECUTOR).setThreadFactory(new ThreadFactory() {
53 public Thread newThread(Runnable run) {
54 Thread thread = new Thread(run);
55 thread.setDaemon(true);
56 return thread;
57 }
58 });
59 }
60
61 static private class FactoryFinder {
62 private String path;
63
64 public FactoryFinder(String path) {
65 this.path = path;
66 }
67
68 /***
69 * Creates a new instance of the given key
70 *
71 * @param key
72 * is the key to add to the path to find a text file
73 * containing the factory name
74 * @return a newly created instance
75 */
76 public Object newInstance(String key) throws IllegalAccessException, InstantiationException, IOException,
77 ClassNotFoundException {
78 return newInstance(key, null);
79 }
80
81 public Object newInstance(String key, String propertyPrefix) throws IllegalAccessException,
82 InstantiationException, IOException, ClassNotFoundException {
83 return newInstance(doFindFactoryProperies(key), propertyPrefix);
84 }
85
86 private Object newInstance(Properties properties, String propertyPrefix) throws ClassNotFoundException,
87 InstantiationException, IllegalAccessException, IOException {
88
89 if (propertyPrefix == null)
90 propertyPrefix = "";
91
92 String className = properties.getProperty(propertyPrefix + "class");
93 if (className == null) {
94 throw new IOException("Expected property is missing: " + propertyPrefix + "class");
95 }
96 Class clazz;
97 try {
98 clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
99 } catch (ClassNotFoundException e) {
100 clazz = getClass().getClassLoader().loadClass(className);
101 }
102
103
104
105 return clazz.newInstance();
106 }
107
108 private Properties doFindFactoryProperies(String key) throws IOException, ClassNotFoundException {
109 String uri = path + key;
110
111
112 InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(uri);
113 if (in == null) {
114 in = getClass().getClassLoader().getResourceAsStream(uri);
115 if (in == null) {
116 throw new IOException("Could not find factory class for resource: " + uri);
117 }
118 }
119
120
121 BufferedInputStream reader = null;
122 try {
123 reader = new BufferedInputStream(in);
124 Properties properties = new Properties();
125 properties.load(reader);
126 return properties;
127 } finally {
128 try {
129 reader.close();
130 } catch (Exception e) {
131 }
132 }
133 }
134 }
135
136 private static FactoryFinder finder = new FactoryFinder("META-INF/org.activeio.ChannelFactory/");
137
138 public SynchChannel openSynchChannel(URI location) throws IOException {
139 SynchChannelFactory factory = getSynchChannelFactory(location.getScheme());
140 return factory.openSynchChannel(location);
141 }
142
143 public SynchChannelServer bindSynchChannel(URI location) throws IOException {
144 SynchChannelFactory factory = getSynchChannelFactory(location.getScheme());
145 return factory.bindSynchChannel(location);
146 }
147
148 public AsynchChannel openAsynchChannel(URI location) throws IOException {
149 AsynchChannelFactory factory = getAsynchChannelFactory(location.getScheme());
150 return factory.openAsynchChannel(location);
151 }
152
153 public AsynchChannelServer bindAsynchChannel(URI location) throws IOException {
154 AsynchChannelFactory factory = getAsynchChannelFactory(location.getScheme());
155 return factory.bindAsynchChannel(location);
156 }
157
158 private SynchChannelFactory getSynchChannelFactory(String protocol) throws IOException {
159 try {
160 SynchChannelFactory rc = (SynchChannelFactory) synchChannelFactoryMap.get(protocol);
161 if (rc == null) {
162 try {
163 rc = (SynchChannelFactory) finder.newInstance(protocol, "SynchChannelFactory.");
164 } catch (Throwable original) {
165
166
167 try {
168 AsynchChannelFactory f = (AsynchChannelFactory) finder.newInstance(protocol,
169 "AsynchChannelFactory.");
170 rc = AsynchToSynchChannelFactoryAdaptor.adapt(f);
171 } catch (Throwable e) {
172
173 throw original;
174 }
175 }
176 synchChannelFactoryMap.put(protocol, rc);
177 }
178 return rc;
179 } catch (Throwable e) {
180 throw (IOException) new IOException("Could not load a SynchChannelFactory for protcol: " + protocol
181 + ", reason: " + e).initCause(e);
182 }
183 }
184
185 private AsynchChannelFactory getAsynchChannelFactory(String protocol) throws IOException {
186 try {
187 AsynchChannelFactory rc = (AsynchChannelFactory) asynchChannelFactoryMap.get(protocol);
188 if (rc == null) {
189
190 try {
191 rc = (AsynchChannelFactory) finder.newInstance(protocol, "AsynchChannelFactory.");
192 } catch (Throwable original) {
193
194
195 try {
196 SynchChannelFactory f = (SynchChannelFactory) finder.newInstance(protocol,
197 "SynchChannelFactory.");
198 rc = SynchToAsynchChannelFactoryAdaptor.adapt(f);
199 } catch (Throwable e) {
200
201 throw original;
202 }
203 }
204
205 asynchChannelFactoryMap.put(protocol, rc);
206 }
207 return rc;
208 } catch (Throwable e) {
209 throw (IOException) new IOException("Could not load a AsynchChannelFactory for protcol: " + protocol
210 + ", reason: " + e).initCause(e);
211 }
212 }
213
214 }