blob: bf8eaded0762dbcea49bdb8ee7838d4430c44a72 [file] [log] [blame]
Richard S. Hall7fa14152006-06-14 15:22:03 +00001/*
2 * Copyright 2006 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17package org.apache.felix.ipojo;
18
Richard S. Hall7c2e92a2006-07-20 10:26:08 +000019import java.io.IOException;
20import java.net.URL;
21import java.security.ProtectionDomain;
22import java.util.Enumeration;
Richard S. Hall7fa14152006-06-14 15:22:03 +000023import java.util.logging.Level;
24
25import org.apache.felix.ipojo.metadata.Element;
26import org.osgi.framework.BundleContext;
27
28/**
29 * The component manager factory class manages component manager object.
Richard S. Hall749e4592006-06-22 12:51:44 +000030 * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
Richard S. Hall7fa14152006-06-14 15:22:03 +000031 */
32public class ComponentManagerFactory {
33
34 // Fields :
35 /**
36 * List of the managed component manager.
37 */
38 private ComponentManager[] m_componentManagers = new ComponentManager[0];
39
40 /**
41 * The bundle context reference.
42 */
43 private BundleContext m_bundleContext = null;
44
Richard S. Hall7c2e92a2006-07-20 10:26:08 +000045 /**
46 * Component class.
47 */
48 private byte[] m_clazz = null;
49
50 /**
51 * Component Class Name.
52 */
53 private String m_componentClassName = null;
54
55 /**
56 * Classloader to delegate loading.
57 */
58 private FactoryClassloader m_classLoader = null;
59
Richard S. Hall7fa14152006-06-14 15:22:03 +000060 //End field
61
Richard S. Hall7c2e92a2006-07-20 10:26:08 +000062 /**
63 * FactoryClassloader.
64 */
65 private class FactoryClassloader extends ClassLoader {
66
67 /**
68 * load the class.
69 * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
70 * @param name : the name of the class
71 * @param resolve : should be the class resolve now ?
72 * @return : the loaded class
73 * @throws ClassNotFoundException : the class to load is not found
74 */
75 protected synchronized Class loadClass(final String name,
76 final boolean resolve) throws ClassNotFoundException {
77 return m_bundleContext.getBundle().loadClass(name);
78 }
79
80
81 /**
82 * Return the URL of the asked ressource.
83 * @param arg : the name of the resource to find.
84 * @return the URL of the resource.
85 * @see java.lang.ClassLoader#getResource(java.lang.String)
86 */
87 public URL getResource(String arg) {
88 return m_bundleContext.getBundle().getResource(arg);
89 }
90
91 /**
92 * .
93 * @param arg : resource to find
94 * @return : the enumeration found
95 * @throws IOException : if the lookup failed.
96 * @see java.lang.ClassLoader#getResources(java.lang.String)
97 */
98 public Enumeration getRessources(String arg) throws IOException {
99 return m_bundleContext.getBundle().getResources(arg);
100 }
101
102 /**
103 * The defineClass method.
104 * @param name : name of the class
105 * @param b : the byte array of the class
106 * @param domain : the protection domain
107 * @return : the defined class.
108 * @throws Exception : if a problem is detected during the loading
109 */
110 public Class defineClass(String name, byte[] b,
111 ProtectionDomain domain) throws Exception {
112 return super.defineClass(name, b, 0, b.length, domain);
113 }
114 }
115
Richard S. Hall7fa14152006-06-14 15:22:03 +0000116 // Field accessors
117
118 /**
119 * Add a component manager factory to the component manager list.
120 * @param cm : the new component metadata.
121 */
122 private void addComponent(ComponentManager cm) {
123
124 // If the component manager array is not empty add the new factory at the end
125 if (m_componentManagers.length != 0) {
126 ComponentManager[] newCM = new ComponentManager[m_componentManagers.length + 1];
127 System.arraycopy(m_componentManagers, 0, newCM, 0, m_componentManagers.length);
128 newCM[m_componentManagers.length] = cm;
129 m_componentManagers = newCM;
130 }
131 // Else create an array of size one with the new component manager
132 else {
133 m_componentManagers = new ComponentManager[] {cm};
134 }
135 }
136
137 /**
138 * Remove the component manager for m the list.
139 * @param cm : the component manager to remove
140 */
141 public void removeComponent(ComponentManager cm) {
142 cm.stop();
143 int idx = -1;
144
145 for (int i = 0; i < m_componentManagers.length; i++) {
146 if (m_componentManagers[i] == cm) { idx = i; }
147 }
148
149 if (idx >= 0) {
150 if ((m_componentManagers.length - 1) == 0) { m_componentManagers = new ComponentManager[0]; }
151 else {
152 ComponentManager[] newCMList = new ComponentManager[m_componentManagers.length - 1];
153 System.arraycopy(m_componentManagers, 0, newCMList, 0, idx);
154 if (idx < newCMList.length) {
155 System.arraycopy(m_componentManagers, idx + 1, newCMList, idx, newCMList.length - idx); }
156 m_componentManagers = newCMList;
157 }
158 }
159 }
160
161 /**
162 * @return the iPOJO activator reference
163 */
164 public BundleContext getBundleContext() { return m_bundleContext; }
165
166 // End field accessors
167
168 /**
Richard S. Hall7fa14152006-06-14 15:22:03 +0000169 * Create a component manager factory and create a component manager with the given medatada.
170 * @param bc : bundle context
171 * @param cm : metadata of the component to create
172 */
173 public ComponentManagerFactory(BundleContext bc, Element cm) {
174 m_bundleContext = bc;
175 createComponentManager(cm);
Richard S. Hall7c2e92a2006-07-20 10:26:08 +0000176 m_componentClassName = cm.getAttribute("className");
177 }
178
179 /**
180 * Create a component manager factory and create a component manager with the given medatada.
181 * @param bc : bundle context
182 * @param clazz : the component class
183 * @param cm : metadata of the component
184 */
185 public ComponentManagerFactory(BundleContext bc, byte[] clazz, Element cm) {
186 m_bundleContext = bc;
187 m_clazz = clazz;
188 m_componentClassName = cm.getAttribute("className");
189 createComponentManager(cm);
Richard S. Hall7fa14152006-06-14 15:22:03 +0000190 }
191
192 /**
193 * Create a component manager factory, no component manager are created.
194 * @param bc
195 */
196 public ComponentManagerFactory(BundleContext bc) {
197 m_bundleContext = bc;
198 }
199
200 /**
201 * Create a component manager form the component metadata.
202 * @param cm : Component Metadata
203 * @return a component manager configured with the metadata
204 */
205 public ComponentManager createComponentManager(Element cm) {
206 ComponentManager component = new ComponentManager(this);
207 component.configure(cm);
208 addComponent(component);
209 return component;
210 }
211
212 // Factory lifecycle management
213
214 /**
215 * Stop all the component managers.
216 */
217 public void stop() {
218 Activator.getLogger().log(Level.INFO, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] Stop the component factory");
219 for (int i = 0; i < m_componentManagers.length; i++) {
220 ComponentManager cm = m_componentManagers[i];
221 cm.stop();
222 }
223 }
224
225 /**
226 * Start all the component managers.
227 */
228 public void start() {
229 Activator.getLogger().log(Level.INFO, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] Start the component factory");
230 for (int i = 0; i < m_componentManagers.length; i++) {
231 ComponentManager cm = m_componentManagers[i];
232 cm.start();
233 }
234 }
235
Richard S. Hall7c2e92a2006-07-20 10:26:08 +0000236 /**
237 * Load a class.
238 * @param className : name of the class to load
239 * @return the resulting Class object
240 * @throws ClassNotFoundException : happen when the class is not found
241 */
242 public Class loadClass(String className) throws ClassNotFoundException {
243 Activator.getLogger().log(Level.INFO, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] In load for : " + className);
244 if (m_clazz != null && className.equals(m_componentClassName)) {
245 if (m_classLoader == null) {
246 Activator.getLogger().log(Level.INFO, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] Create the FactoryClassLoader for : " + className);
247 m_classLoader = new FactoryClassloader();
248 }
249 try {
250 Class c = m_classLoader.defineClass(m_componentClassName, m_clazz, null);
251 Activator.getLogger().log(Level.INFO, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] Return " + c + " for " + className);
252 return c;
253 } catch (Exception e) {
254 Activator.getLogger().log(Level.SEVERE, "[Bundle " + m_bundleContext.getBundle().getBundleId() + "] Cannot define the class : " + className);
255 return null;
256 }
257 }
258 return m_bundleContext.getBundle().loadClass(className);
259 }
260
261 /**
262 * Return the URL of a resource.
263 * @param resName : resource name
264 * @return the URL of the resource
265 */
266 public URL getResource(String resName) {
267 return m_bundleContext.getBundle().getResource(resName);
268 }
269
Richard S. Hall7fa14152006-06-14 15:22:03 +0000270}