1 package org.codehaus.xfire.loom;
2
3 import java.util.Collections;
4 import java.util.HashMap;
5 import java.util.Map;
6
7 import org.apache.avalon.framework.configuration.Configurable;
8 import org.apache.avalon.framework.configuration.Configuration;
9 import org.apache.avalon.framework.configuration.ConfigurationException;
10 import org.apache.avalon.framework.logger.AbstractLogEnabled;
11 import org.apache.avalon.framework.service.ServiceException;
12 import org.apache.avalon.framework.service.ServiceManager;
13 import org.apache.avalon.framework.service.Serviceable;
14 import org.codehaus.xfire.aegis.AegisBindingProvider;
15 import org.codehaus.xfire.service.Service;
16 import org.codehaus.xfire.service.ServiceFactory;
17 import org.codehaus.xfire.service.ServiceRegistry;
18 import org.codehaus.xfire.service.binding.ObjectBinding;
19 import org.codehaus.xfire.service.binding.ObjectServiceFactory;
20 import org.codehaus.xfire.soap.Soap11;
21 import org.codehaus.xfire.soap.Soap12;
22 import org.codehaus.xfire.soap.SoapVersion;
23 import org.codehaus.xfire.util.ClassLoaderUtils;
24
25 /***
26 * Default implementation of ServiceDeployer
27 *
28 * @author <a href="mailto:peter.royal@pobox.com">peter royal</a>
29 */
30 public class DefaultServiceDeployer
31 extends AbstractLogEnabled
32 implements ServiceDeployer, Serviceable, Configurable
33 {
34 private final Map m_services = Collections.synchronizedMap(new HashMap());
35
36 private ServiceRegistry m_serviceRegistry;
37 private Map m_serviceFactories;
38
39 private ServiceFactory m_defaultServiceFactory;
40
41 private Map m_configurations;
42
43 public void configure(final Configuration configuration)
44 throws ConfigurationException
45 {
46 final Configuration[] kids = configuration.getChildren("service");
47
48 m_configurations = new HashMap(kids.length);
49
50 for (int i = 0; i < kids.length; i++)
51 {
52 m_configurations.put(kids[i].getAttribute("key"), kids[i]);
53 }
54
55 final Configuration child = configuration.getChild("defaultFactory");
56
57 m_defaultServiceFactory = (ServiceFactory) m_serviceFactories.get(child.getValue());
58
59 if (null == m_defaultServiceFactory)
60 {
61 final String msg = "Missing default factory '" + child.getValue() + "' at " + child.getLocation();
62 throw new ConfigurationException(msg);
63 }
64 }
65
66 public void service(final ServiceManager manager)
67 throws ServiceException
68 {
69 m_serviceRegistry = (ServiceRegistry) manager.lookup(ServiceRegistry.ROLE);
70 m_serviceFactories = (Map) manager.lookup(ServiceFactory.class.getName() + "{}");
71 }
72
73 public void deploy(final String key, final Object object)
74 throws Exception
75 {
76 if (m_services.containsKey(key))
77 {
78 throw new IllegalStateException("Service with key '" + key + "' already deployed");
79 }
80
81 final Configuration configuration = (Configuration) m_configurations.get(key);
82 final Service endpoint;
83
84 if (null == configuration)
85 {
86 if (getLogger().isInfoEnabled())
87 getLogger().info("No configuration found for '" + key + "', using defaults");
88
89 endpoint = m_defaultServiceFactory.create(object.getClass());
90 }
91 else
92 {
93 endpoint = createServiceFromConfiguration(configuration);
94
95 if (getLogger().isDebugEnabled())
96 getLogger().debug("Created '" + endpoint.getServiceInfo().getName() + "' from key '" + key + "'");
97 }
98
99 endpoint.getBinding().setInvoker(new ServiceInvoker(object));
100
101 registerService(key, endpoint);
102 }
103
104 private Service createServiceFromConfiguration(final Configuration configuration)
105 throws ConfigurationException
106 {
107 final ServiceFactory factory = getServiceFactory(configuration.getChild("factory").getValue(null));
108 String encodingUri = configuration.getChild("encodingStyleURI").getValue(null);
109 final Map propertiesMap = new HashMap();
110
111 if (encodingUri != null)
112 {
113 propertiesMap.put(AegisBindingProvider.TYPE_MAPPING_KEY, encodingUri);
114 }
115
116 if (factory instanceof ObjectServiceFactory)
117 {
118 ObjectServiceFactory osf = (ObjectServiceFactory) factory;
119 osf.setStyle(configuration.getChild("style").getValue("wrapped"));
120 osf.setUse(configuration.getChild("use").getValue("wrapped"));
121 osf.setSoapVersion(getSoapVersion(configuration.getChild("soapVersion")));
122 }
123
124 final Configuration[] properties = configuration.getChildren("property");
125
126 for (int i = 0; i < properties.length; i++)
127 {
128 propertiesMap.put(properties[i].getAttribute("name"), properties[i].getAttribute("value"));
129 }
130
131 final Service service =
132 factory.create(loadClass(configuration.getChild("serviceClass")),
133 configuration.getChild("name").getValue(),
134 configuration.getChild("namespace").getValue(""),
135 propertiesMap);
136
137 return service;
138 }
139
140 private ServiceFactory getServiceFactory(final String key)
141 {
142 if (m_serviceFactories.containsKey(key))
143 {
144 return (ServiceFactory) m_serviceFactories.get(key);
145 }
146 else
147 {
148 return m_defaultServiceFactory;
149 }
150 }
151
152 private SoapVersion getSoapVersion(final Configuration configuration)
153 throws ConfigurationException
154 {
155 final String value = configuration.getValue("1.1");
156
157 if (value.equals("1.1"))
158 {
159 return Soap11.getInstance();
160 }
161 else if (value.equals("1.2"))
162 {
163 return Soap12.getInstance();
164 }
165 else
166 {
167 final String msg = "Invalid soap version at " + configuration.getLocation() + ". Must be 1.1 or 1.2.";
168 throw new ConfigurationException(msg);
169 }
170 }
171
172 private Class loadClass(final Configuration configuration)
173 throws ConfigurationException
174 {
175 try
176 {
177 return ClassLoaderUtils.loadClass(configuration.getValue(), getClass());
178 }
179 catch (ClassNotFoundException e)
180 {
181 final String msg = "Unable to load " + configuration.getValue() + " at " + configuration.getLocation();
182 throw new ConfigurationException(msg, e);
183 }
184 }
185
186 private void registerService(final String key, final Service endpoint)
187 {
188 m_serviceRegistry.register(endpoint);
189
190 m_services.put(key, endpoint.getName());
191 }
192
193 public void undeploy(final String key)
194 {
195 if (m_services.containsKey(key))
196 {
197 m_serviceRegistry.unregister((String) m_services.remove(key));
198 }
199 else if (getLogger().isWarnEnabled())
200 {
201 getLogger().warn("Attempted to undeploy unknown key: " + key);
202 }
203 }
204 }