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