1
2
3
4
5
6
7
8
9
10
11 package org.mule.construct;
12
13 import org.mule.MessageExchangePattern;
14 import org.mule.api.MuleContext;
15 import org.mule.api.MuleException;
16 import org.mule.api.MuleRuntimeException;
17 import org.mule.api.component.Component;
18 import org.mule.api.component.JavaComponent;
19 import org.mule.api.construct.FlowConstructInvalidException;
20 import org.mule.api.context.MuleContextAware;
21 import org.mule.api.endpoint.InboundEndpoint;
22 import org.mule.api.processor.MessageProcessor;
23 import org.mule.api.processor.MessageProcessorBuilder;
24 import org.mule.api.source.MessageSource;
25 import org.mule.config.i18n.MessageFactory;
26 import org.mule.construct.processor.FlowConstructStatisticsMessageObserver;
27 import org.mule.interceptor.LoggingInterceptor;
28 import org.mule.processor.builder.InterceptingChainMessageProcessorBuilder;
29 import org.mule.util.ClassUtils;
30
31 import java.lang.reflect.Method;
32 import java.util.List;
33
34 import edu.emory.mathcs.backport.java.util.Collections;
35
36
37
38
39
40 public class SimpleService extends AbstractFlowConstruct
41 {
42 public enum Type
43 {
44
45
46
47
48 JAX_WS
49 {
50 @Override
51 public void validate(Component component) throws FlowConstructInvalidException
52 {
53 if (!(component instanceof JavaComponent))
54 {
55 throw new FlowConstructInvalidException(
56 MessageFactory.createStaticMessage("SimpleService can only expose instances of JAX-WS annotated JavaComponent instances. You provided a: "
57 + component.getClass().getName()));
58 }
59 }
60
61 @Override
62 public void configureComponentMessageProcessor(MuleContext muleContext,
63 InterceptingChainMessageProcessorBuilder builder,
64 Component component)
65 {
66 builder.chain(newJaxWsComponentMessageProcessor(muleContext, getComponentClass(component)));
67 builder.chain(component);
68 }
69 },
70
71
72
73
74
75 JAX_RS
76 {
77 @Override
78 public void validate(Component component) throws FlowConstructInvalidException
79 {
80 if (!(component instanceof JavaComponent))
81 {
82 throw new FlowConstructInvalidException(
83 MessageFactory.createStaticMessage("SimpleService can only expose instances of JAX-RS annotated JavaComponent instances. You provided a: "
84 + component.getClass().getName()));
85 }
86 }
87
88 @Override
89 public void configureComponentMessageProcessor(MuleContext muleContext,
90 InterceptingChainMessageProcessorBuilder builder,
91 Component component)
92 {
93 builder.chain(newJaxRsComponentWrapper(muleContext, component));
94 }
95 },
96
97
98
99
100 DIRECT
101 {
102 @Override
103 public void validate(Component component) throws FlowConstructInvalidException
104 {
105
106 }
107
108 @Override
109 public void configureComponentMessageProcessor(MuleContext muleContext,
110 InterceptingChainMessageProcessorBuilder builder,
111 Component component)
112 {
113 builder.chain(component);
114 }
115 };
116
117 public abstract void validate(Component component) throws FlowConstructInvalidException;
118
119 public abstract void configureComponentMessageProcessor(MuleContext muleContext,
120 InterceptingChainMessageProcessorBuilder builder,
121 Component component);
122
123 public static Type fromString(String string)
124 {
125 String mepString = string.toUpperCase().replace('-', '_');
126 return Type.valueOf(mepString);
127 }
128 }
129
130 private final Component component;
131 private final Type type;
132
133 public SimpleService(String name,
134 MuleContext muleContext,
135 MessageSource messageSource,
136 Component component,
137 Type type) throws MuleException
138 {
139 super(name, muleContext);
140
141 if (messageSource == null)
142 {
143 throw new FlowConstructInvalidException(
144 MessageFactory.createStaticMessage("messageSource can't be null on: " + this.toString()));
145 }
146
147 if (component == null)
148 {
149 throw new FlowConstructInvalidException(
150 MessageFactory.createStaticMessage("component can't be null on: " + this.toString()));
151 }
152
153 if (type == null)
154 {
155 throw new FlowConstructInvalidException(
156 MessageFactory.createStaticMessage("type can't be null on: " + this.toString()));
157 }
158
159 this.messageSource = messageSource;
160 this.component = component;
161 this.type = type;
162 }
163
164 public Component getComponent()
165 {
166 return component;
167 }
168
169 @Override
170 protected void configureMessageProcessors(InterceptingChainMessageProcessorBuilder builder)
171 {
172 builder.chain(new LoggingInterceptor());
173 builder.chain(new FlowConstructStatisticsMessageObserver());
174 type.configureComponentMessageProcessor(muleContext, builder, component);
175 }
176
177 @Override
178 protected void validateConstruct() throws FlowConstructInvalidException
179 {
180 super.validateConstruct();
181
182 if ((messageSource instanceof InboundEndpoint)
183 && (!((InboundEndpoint) messageSource).getExchangePattern().equals(
184 MessageExchangePattern.REQUEST_RESPONSE)))
185 {
186 throw new FlowConstructInvalidException(
187 MessageFactory.createStaticMessage("SimpleService only works with a request-response inbound endpoint."),
188 this);
189 }
190
191 type.validate(component);
192 }
193
194 private static Class<?> getComponentClass(Component component)
195 {
196 if (component instanceof JavaComponent)
197 {
198 return ((JavaComponent) component).getObjectFactory().getObjectClass();
199 }
200
201 return component.getClass();
202 }
203
204 private static MessageProcessor newJaxWsComponentMessageProcessor(MuleContext muleContext,
205 Class<?> componentClass)
206 {
207 try
208 {
209 MessageProcessorBuilder wsmpb = (MessageProcessorBuilder) ClassUtils.instanciateClass("org.mule.module.cxf.builder.WebServiceMessageProcessorBuilder");
210
211 Method setServiceClassMethod = ClassUtils.getMethod(wsmpb.getClass(), "setServiceClass",
212 new Class<?>[]{Class.class});
213
214 setServiceClassMethod.invoke(wsmpb, new Object[]{componentClass});
215
216 Method setFrontendMethod = ClassUtils.getMethod(wsmpb.getClass(), "setFrontend",
217 new Class<?>[]{String.class});
218
219 setFrontendMethod.invoke(wsmpb, new Object[]{"jaxws"});
220
221 ((MuleContextAware) wsmpb).setMuleContext(muleContext);
222
223 return wsmpb.build();
224 }
225 catch (Exception e)
226 {
227 throw new MuleRuntimeException(
228 MessageFactory.createStaticMessage("Failed to configure the required web service infrastructure: are you missing the Mule CXF Module?"),
229 e);
230 }
231 }
232
233 private static Component newJaxRsComponentWrapper(MuleContext muleContext, Component component)
234 {
235 try
236 {
237 Component jrc = (Component) ClassUtils.instanciateClass("org.mule.module.jersey.JerseyResourcesComponent");
238
239 Method setComponentsMethod = ClassUtils.getMethod(jrc.getClass(), "setComponents",
240 new Class<?>[]{List.class});
241
242 setComponentsMethod.invoke(jrc, new Object[]{Collections.singletonList(component)});
243
244 ((MuleContextAware) jrc).setMuleContext(muleContext);
245
246 return jrc;
247 }
248 catch (Exception e)
249 {
250 throw new MuleRuntimeException(
251 MessageFactory.createStaticMessage("Failed to configure the required web service infrastructure: are you missing the Mule Jersey Module?"),
252 e);
253 }
254 }
255 }