-
-
Notifications
You must be signed in to change notification settings - Fork 195
/
ImplFactory.java
172 lines (151 loc) · 5.29 KB
/
ImplFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/**
* MicroEmulator
* Copyright (C) 2006-2007 Bartek Teodorczyk <barteo@barteo.net>
* Copyright (C) 2006-2007 Vlad Skarzhevskyy
* <p>
* It is licensed under the following two licenses as alternatives:
* 1. GNU Lesser General Public License (the "LGPL") version 2.1 or any newer version
* 2. Apache License (the "AL") Version 2.0
* <p>
* You may not use this file except in compliance with at least one of
* the above two licenses.
* <p>
* You may obtain a copy of the LGPL at
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
* <p>
* You may obtain a copy of the AL at
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the LGPL or the AL for the specific language governing permissions and
* limitations.
*
* @version $Id$
*/
package org.microemu.microedition;
import org.microemu.microedition.io.ConnectorDelegate;
import java.util.HashMap;
import java.util.Map;
/**
* This class allows to unbind implemenation with CLDC or MIDP declarations.
*
* @author vlads
*/
public class ImplFactory {
public static final String DEFAULT = "org.microemu.default";
private static final String INTERFACE_NAME_SUFIX = "Delegate";
private static final String IMPLEMENTATION_NAME_SUFIX = "Impl";
private Map implementations = new HashMap();
private Map implementationsGCF = new HashMap();
/**
* Allow default initialization. In Secure environment instance() should be
* called initialy from secure contex.
*/
private static class SingletonHolder {
private static ImplFactory instance = new ImplFactory();
}
public static ImplFactory instance() {
return SingletonHolder.instance;
}
public static void register(Class delegate, Class implementationClass) {
instance().implementations.put(delegate, implementationClass);
}
public static void register(Class delegate, Object implementationInstance) {
instance().implementations.put(delegate, implementationInstance);
}
public static void unregister(Class delegate, Class implementation) {
// TODO implement
}
/**
* Register Generic Connection Framework scheme implementation.
*
* @param implementation instance of ConnectorDelegate
* @param scheme
*/
public static void registerGCF(String scheme, Object implementation) {
if (!ConnectorDelegate.class.isAssignableFrom(implementation.getClass())) {
throw new IllegalArgumentException();
}
if (scheme == null) {
scheme = DEFAULT;
}
Object impl = instance().implementationsGCF.get(scheme);
instance().implementationsGCF.put(scheme, implementation);
}
public static void unregistedGCF(String scheme, Object implementation) {
if (!ConnectorDelegate.class.isAssignableFrom(implementation.getClass())) {
throw new IllegalArgumentException();
}
if (scheme == null) {
scheme = DEFAULT;
}
Object impl = instance().implementationsGCF.get(scheme);
if (impl == implementation) {
instance().implementationsGCF.remove(scheme);
}
}
private Object getDefaultImplementation(Class delegateInterface) {
try {
String name = delegateInterface.getName();
if (name.endsWith(INTERFACE_NAME_SUFIX)) {
name = name.substring(0, name.length() - INTERFACE_NAME_SUFIX.length());
}
final String implClassName = name + IMPLEMENTATION_NAME_SUFIX;
Class implClass = ImplFactory.class.getClassLoader().loadClass(implClassName);
try {
implClass.getConstructor();
} catch (NoSuchMethodException e) {
throw new InstantiationException("No default constructor in class " + implClassName);
}
return implClass.newInstance();
} catch (Throwable e) {
throw new RuntimeException("Unable create " + delegateInterface.getName() + " implementation", e);
}
}
private Object implementationNewInstance(final Class implClass) {
try {
return implClass.newInstance();
} catch (Throwable e) {
throw new RuntimeException("Unable create " + implClass.getName() + " implementation", e);
}
}
/**
* @param name The URL for the connection.
* @return UTL scheme
*/
public static String getCGFScheme(String name) {
return name.substring(0, name.indexOf(':'));
}
/**
* @param name The URL for the connection.
* @return
*/
public static ConnectorDelegate getCGFImplementation(String name) {
String scheme = getCGFScheme(name);
ConnectorDelegate impl = (ConnectorDelegate) instance().implementationsGCF.get(scheme);
if (impl != null) {
return impl;
}
impl = (ConnectorDelegate) instance().implementationsGCF.get(DEFAULT);
if (impl != null) {
return impl;
}
return (ConnectorDelegate) instance().getDefaultImplementation(ConnectorDelegate.class);
}
public static Implementation getImplementation(Class origClass, Class delegateInterface) {
// if called from implementation constructor return null to avoid
// recurive calls!
// TODO can be done using thread stack analyse or ThreadLocal
Object impl = instance().implementations.get(delegateInterface);
if (impl != null) {
if (impl instanceof Class) {
return (Implementation) instance().implementationNewInstance((Class) impl);
} else {
return (Implementation) impl;
}
}
return (Implementation) instance().getDefaultImplementation(delegateInterface);
}
}