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