001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.cxfse;
018    
019    import java.io.IOException;
020    import java.lang.reflect.Field;
021    import java.lang.reflect.Method;
022    import java.util.HashMap;
023    import java.util.List;
024    import java.util.Map;
025    import java.util.concurrent.CopyOnWriteArrayList;
026    
027    import javax.annotation.PostConstruct;
028    import javax.annotation.PreDestroy;
029    import javax.jbi.component.ComponentContext;
030    import javax.jbi.management.DeploymentException;
031    import javax.jbi.messaging.DeliveryChannel;
032    import javax.jbi.messaging.ExchangeStatus;
033    import javax.jbi.messaging.InOnly;
034    import javax.jbi.messaging.MessageExchange;
035    import javax.jbi.messaging.NormalizedMessage;
036    import javax.jbi.messaging.RobustInOnly;
037    import javax.wsdl.WSDLException;
038    import javax.wsdl.factory.WSDLFactory;
039    import javax.xml.namespace.QName;
040    import javax.xml.parsers.ParserConfigurationException;
041    import javax.xml.transform.TransformerException;
042    import javax.xml.ws.WebServiceRef;
043    import org.w3c.dom.Element;
044    import org.xml.sax.SAXException;
045    import org.apache.cxf.Bus;
046    import org.apache.cxf.aegis.databinding.AegisDatabinding;
047    import org.apache.cxf.binding.soap.SoapMessage;
048    import org.apache.cxf.binding.soap.SoapVersion;
049    import org.apache.cxf.binding.soap.model.SoapBindingInfo;
050    import org.apache.cxf.endpoint.Server;
051    import org.apache.cxf.frontend.ServerFactoryBean;
052    import org.apache.cxf.interceptor.Fault;
053    import org.apache.cxf.interceptor.Interceptor;
054    import org.apache.cxf.interceptor.InterceptorProvider;
055    import org.apache.cxf.jaxws.EndpointImpl;
056    import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
057    import org.apache.cxf.jaxws.ServiceImpl;
058    import org.apache.cxf.jaxws.support.JaxWsImplementorInfo;
059    import org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean;
060    import org.apache.cxf.message.Message;
061    import org.apache.cxf.service.model.BindingOperationInfo;
062    import org.apache.cxf.service.model.EndpointInfo;
063    import org.apache.cxf.transport.ConduitInitiatorManager;
064    import org.apache.cxf.transport.jbi.JBIDestination;
065    import org.apache.cxf.transport.jbi.JBIDispatcherUtil;
066    import org.apache.cxf.transport.jbi.JBITransportFactory;
067    import org.apache.cxf.wsdl11.ServiceWSDLBuilder;
068    import org.apache.servicemix.common.endpoints.ProviderEndpoint;
069    import org.apache.servicemix.cxfse.interceptors.AttachmentInInterceptor;
070    import org.apache.servicemix.cxfse.interceptors.AttachmentOutInterceptor;
071    import org.apache.servicemix.cxfse.support.ReflectionUtils;
072    import org.apache.servicemix.id.IdGenerator;
073    import org.apache.servicemix.jbi.jaxp.SourceTransformer;
074    import org.apache.servicemix.soap.util.DomUtil;
075    import org.springframework.util.ReflectionUtils.FieldCallback;
076    
077    
078    /**
079     * 
080     * @author gnodet
081     * @org.apache.xbean.XBean element="endpoint" description="an endpoint using
082     *                         CXF's JAX-WS frontend"
083     */
084    public class CxfSeEndpoint extends ProviderEndpoint implements
085            InterceptorProvider {
086    
087        private static final IdGenerator ID_GENERATOR = new IdGenerator();
088    
089        private Object pojo;
090    
091        private EndpointImpl endpoint;
092    
093        private String address;
094        
095        private ServerFactoryBean sf;
096    
097        private List<Interceptor> in = new CopyOnWriteArrayList<Interceptor>();
098    
099        private List<Interceptor> out = new CopyOnWriteArrayList<Interceptor>();
100    
101        private List<Interceptor> outFault = new CopyOnWriteArrayList<Interceptor>();
102    
103        private List<Interceptor> inFault = new CopyOnWriteArrayList<Interceptor>();
104    
105        private Map properties;
106        
107        private Server server;
108    
109        private boolean mtomEnabled;
110    
111        private boolean schemaValidationEnabled;
112    
113        private boolean useJBIWrapper = true;
114    
115        private boolean useSOAPEnvelope = true;
116    
117        private boolean useAegis;
118        
119        private QName pojoService;
120        private String pojoEndpoint;
121        private QName pojoInterfaceName;
122        
123        private Server soapBindingServer;
124        /**
125         * Returns the object implementing the endpoint's functionality. It is
126         * returned as a generic Java <code>Object</code> that can be cast to the
127         * proper type.
128         * 
129         * @return the pojo
130         */
131        public Object getPojo() {
132            return pojo;
133        }
134    
135        /**
136         * Specifies the object implementing the endpoint's functionality. This
137         * object should use the JAX-WS annotations.
138         * 
139         * @param pojo
140         *            a JAX-WS annotated object
141         * 
142         * @org.apache.xbean.Property description="a bean configuring the JAX-WS
143         *                            annotated implementation for the endpoint"
144         */
145        public void setPojo(Object pojo) {
146            this.pojo = pojo;
147        }
148    
149        /**
150         * Returns the list of interceptors used to process fault messages being
151         * sent back to the consumer.
152         * 
153         * @return a list of <code>Interceptor</code> objects
154         */
155        public List<Interceptor> getOutFaultInterceptors() {
156            return outFault;
157        }
158    
159        /**
160         * Returns the list of interceptors used to process fault messages being
161         * recieved by the endpoint.
162         * 
163         * @return a list of <code>Interceptor</code> objects
164         */
165        public List<Interceptor> getInFaultInterceptors() {
166            return inFault;
167        }
168    
169        /**
170         * Returns the list of interceptors used to process messages being recieved
171         * by the endpoint.
172         * 
173         * @return a list of <code>Interceptor</code> objects
174         */
175        public List<Interceptor> getInInterceptors() {
176            return in;
177        }
178    
179        /**
180         * Returns the list of interceptors used to process responses being sent
181         * back to the consumer.
182         * 
183         * @return a list of <code>Interceptor</code> objects
184         */
185        public List<Interceptor> getOutInterceptors() {
186            return out;
187        }
188    
189        /**
190         * Specifies a list of interceptors used to process requests recieved by the
191         * endpoint.
192         * 
193         * @param interceptors
194         *            a list of <code>Interceptor</code> objects
195         * @org.apache.xbean.Property description="a list of beans configuring
196         *                            interceptors that process incoming requests"
197         */
198        public void setInInterceptors(List<Interceptor> interceptors) {
199            in.addAll(interceptors);
200        }
201    
202        /**
203         * Specifies a list of interceptors used to process faults recieved by the
204         * endpoint.
205         * 
206         * @param interceptors
207         *            a list of <code>Interceptor</code> objects
208         * @org.apache.xbean.Property description="a list of beans configuring
209         *                            interceptors that process incoming faults"
210         */
211        public void setInFaultInterceptors(List<Interceptor> interceptors) {
212            inFault.addAll(interceptors);
213        }
214    
215        /**
216         * Specifies a list of interceptors used to process responses sent by the
217         * endpoint.
218         * 
219         * @param interceptors
220         *            a list of <code>Interceptor</code> objects
221         * @org.apache.xbean.Property description="a list of beans configuring
222         *                            interceptors that process response messages"
223         */
224        public void setOutInterceptors(List<Interceptor> interceptors) {
225            out.addAll(interceptors);
226        }
227    
228        /**
229         * Specifies a list of interceptors used to process faults sent by the
230         * endpoint.
231         * 
232         * @param interceptors
233         *            a list of <code>Interceptor</code> objects
234         * @org.apache.xbean.Property description="a list of beans configuring
235         *                            interceptors that process fault messages being
236         *                            returned to the consumer"
237         */
238        public void setOutFaultInterceptors(List<Interceptor> interceptors) {
239            outFault.addAll(interceptors);
240        }
241    
242        public Map getProperties() {
243            return properties;
244        }
245    
246        public void setProperties(Map properties) {
247            this.properties = properties;
248        }
249    
250        /*
251         * (non-Javadoc)
252         * 
253         * @see org.apache.servicemix.common.Endpoint#validate()
254         */
255        @Override
256        public void validate() throws DeploymentException {
257            if (getPojo() == null) {
258                throw new DeploymentException("pojo must be set");
259            }
260            if (isUseAegis()) {
261                sf = new ServerFactoryBean();
262                sf.setServiceBean(getPojo());
263                sf.setAddress("jbi://" + ID_GENERATOR.generateSanitizedId());
264                sf.getServiceFactory().setDataBinding(new AegisDatabinding());
265                sf.getServiceFactory().setPopulateFromClass(true);
266                sf.setStart(false);
267                if (isUseJBIWrapper()) {
268                    sf.setBindingId(org.apache.cxf.binding.jbi.JBIConstants.NS_JBI_BINDING);
269                }
270                server = sf.create();
271                server.getEndpoint().getInInterceptors().addAll(getInInterceptors());
272                server.getEndpoint().getInFaultInterceptors().addAll(getInFaultInterceptors());
273                server.getEndpoint().getOutInterceptors().addAll(getOutInterceptors());
274                server.getEndpoint().getOutFaultInterceptors().addAll(getOutFaultInterceptors());
275                if (isMtomEnabled()) {
276                    server.getEndpoint().getInInterceptors().add(new AttachmentInInterceptor());
277                    server.getEndpoint().getOutInterceptors().add(new AttachmentOutInterceptor());
278                }
279    
280                if (sf.getServiceFactory().getServiceQName() != null) {
281                    setPojoService(sf.getServiceFactory().getServiceQName());
282                    if (getService() == null) {
283                        setService(sf.getServiceFactory().getServiceQName());
284                    }
285                }
286                if (sf.getServiceFactory().getEndpointInfo().getName() != null) {
287                    setPojoEndpoint(sf.getServiceFactory().getEndpointInfo().getName().getLocalPart());
288                    if (getEndpoint() == null) {
289                        setEndpoint(sf.getServiceFactory().getEndpointInfo().getName().getLocalPart());
290                    }
291                }
292                if (sf.getServiceFactory().getInterfaceName() != null) {
293                    setPojoInterfaceName(sf.getServiceFactory().getInterfaceName());
294                    if (getInterfaceName() == null) {
295                        setInterfaceName(sf.getServiceFactory().getInterfaceName());
296                    }
297                }
298            } else {
299                JaxWsServiceFactoryBean serviceFactory = new JaxWsServiceFactoryBean();
300                serviceFactory.setPopulateFromClass(true);
301                endpoint = new EndpointImpl(getBus(), getPojo(),
302                    new JaxWsServerFactoryBean(serviceFactory));
303                if (isUseJBIWrapper()) {
304                    endpoint
305                        .setBindingUri(org.apache.cxf.binding.jbi.JBIConstants.NS_JBI_BINDING);
306                }   
307                endpoint.setInInterceptors(getInInterceptors());
308                endpoint.setInFaultInterceptors(getInFaultInterceptors());
309                endpoint.setOutInterceptors(getOutInterceptors());
310                endpoint.setOutFaultInterceptors(getOutFaultInterceptors());
311                if (isMtomEnabled()) {
312                    endpoint.getInInterceptors().add(new AttachmentInInterceptor());
313                    endpoint.getOutInterceptors().add(new AttachmentOutInterceptor());
314                }
315                if (isSchemaValidationEnabled()) {
316                    if (endpoint.getProperties() == null) {
317                        endpoint.setProperties(new HashMap<String, Object>());
318                    }
319                    endpoint.getProperties().put(org.apache.cxf.message.Message.SCHEMA_VALIDATION_ENABLED, true);
320                }
321    
322                JaxWsImplementorInfo implInfo = new JaxWsImplementorInfo(getPojo()
323                    .getClass());
324                setPojoService(implInfo.getServiceName());
325                setPojoInterfaceName(implInfo.getInterfaceName());
326                setPojoEndpoint(implInfo.getEndpointName().getLocalPart());
327                if (getService() == null) {
328                    setService(implInfo.getServiceName());
329                }
330                if (getInterfaceName() == null) {
331                    setInterfaceName(implInfo.getInterfaceName());
332                }
333                if (getEndpoint() == null) {
334                    setEndpoint(implInfo.getEndpointName().getLocalPart());
335                }
336                
337            }
338            super.validate();
339        }
340    
341        private void removeInterceptor(List<Interceptor> interceptors,
342                String whichInterceptor) {
343            for (Interceptor interceptor : interceptors) {
344                if (interceptor.getClass().getName().endsWith(whichInterceptor)) {
345                    interceptors.remove(interceptor);
346                }
347            }
348        }
349    
350        /*
351         * (non-Javadoc)
352         * 
353         * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#process(javax.jbi.messaging.MessageExchange)
354         */
355        @Override
356        public void process(MessageExchange exchange) throws Exception {
357    
358            if (exchange.getStatus() != ExchangeStatus.ACTIVE) {
359                return;
360            }
361            QName opeName = exchange.getOperation();
362            EndpointInfo ei = server.getEndpoint().getEndpointInfo();
363                   
364            if (opeName == null) {
365                // if interface only have one operation, may not specify the opeName
366                // in MessageExchange
367                if (ei.getBinding().getOperations().size() == 1) {
368                    opeName = ei.getBinding().getOperations().iterator().next()
369                            .getName();
370                    exchange.setOperation(opeName);
371                } else {
372                    NormalizedMessage nm = exchange.getMessage("in");
373                    if (soapBindingServer == null) {
374                        ServerFactoryBean sfForSoapBinding = new ServerFactoryBean();
375                        sfForSoapBinding.setServiceBean(getPojo());
376                        sfForSoapBinding.getServiceFactory().setPopulateFromClass(true);
377                        sfForSoapBinding.setStart(false);
378                        sfForSoapBinding.setAddress("local://dummy");
379                        soapBindingServer = sfForSoapBinding.create();
380                    }
381                    Message message = soapBindingServer.getEndpoint().getBinding().createMessage();
382                    opeName = findOperation(nm, message, exchange);
383                    exchange.setOperation(opeName);
384                }
385            }
386            JBITransportFactory jbiTransportFactory = (JBITransportFactory) getBus()
387                    .getExtension(ConduitInitiatorManager.class)
388                    .getConduitInitiator(CxfSeComponent.JBI_TRANSPORT_ID);
389    
390            exchange.setService(getPojoService());
391            exchange.setInterfaceName(getPojoInterfaceName());
392            JBIDestination jbiDestination = jbiTransportFactory
393                    .getDestination(getPojoService().toString()
394                            + getPojoInterfaceName().toString());
395            DeliveryChannel dc = getContext().getDeliveryChannel();
396            jbiTransportFactory.setDeliveryChannel(dc);
397    
398            jbiDestination.setDeliveryChannel(dc);
399            if (exchange.getStatus() == ExchangeStatus.ACTIVE) {
400                jbiDestination.getJBIDispatcherUtil().dispatch(exchange);
401            }
402            if (exchange instanceof InOnly || exchange instanceof RobustInOnly) {
403                exchange.setStatus(ExchangeStatus.DONE);
404                dc.send(exchange);
405            }
406        }
407    
408        private QName findOperation(NormalizedMessage nm,
409                Message message, MessageExchange exchange)
410            throws TransformerException, ParserConfigurationException,
411                IOException, SAXException {
412            // try to figure out the operationName based on the incoming message
413            // payload and wsdl if use doc/literal/wrapped
414            Element element = new SourceTransformer().toDOMElement(nm.getContent());
415    
416            if (!useJBIWrapper) {
417                SoapVersion soapVersion = ((SoapMessage) message).getVersion();
418                if (element != null) {
419                    Element bodyElement = (Element) element.getElementsByTagNameNS(
420                            element.getNamespaceURI(),
421                            soapVersion.getBody().getLocalPart()).item(0);
422                    if (bodyElement != null) {
423                        element = (Element) bodyElement.getFirstChild();
424                    }
425                }
426            } else {
427                element = DomUtil.getFirstChildElement(DomUtil
428                        .getFirstChildElement(element));
429            }
430    
431            QName opeName = new QName(element.getNamespaceURI(), element
432                    .getLocalName());
433            SoapBindingInfo binding = (SoapBindingInfo) soapBindingServer.getEndpoint().getEndpointInfo().getBinding();
434            for (BindingOperationInfo op : binding.getOperations()) {
435                String style = binding.getStyle(op.getOperationInfo());
436                if (style == null) {
437                    style = binding.getStyle();
438                }
439                if ("document".equals(style)) {
440                    if (op.getName().getLocalPart().equals(opeName.getLocalPart())) {
441                        return new QName(getPojoService().getNamespaceURI(),
442                                opeName.getLocalPart());
443                    }
444                } else {
445                    throw new Fault(
446                            new Exception(
447                                    "Operation must bound on this MessageExchange if use rpc mode"));
448                }
449            }
450            throw new Fault(new Exception("Operation not bound on this MessageExchange"));
451            
452        }
453        
454        /*
455         * (non-Javadoc)
456         * 
457         * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#start()
458         */
459        @Override
460        public void start() throws Exception {
461            super.start();
462            address = "jbi://" + ID_GENERATOR.generateSanitizedId();
463            try {
464                if (isUseAegis()) {
465                    server.start();
466                } else {
467                    endpoint.publish(address);
468                    server = endpoint.getServer();
469                }
470            } catch (Exception e) {
471                e.printStackTrace();
472            }
473            if (getService() == null) {
474                setService(server.getEndpoint().getService().getName());
475            }
476            if (getEndpoint() == null) {
477                setEndpoint(server.getEndpoint().getEndpointInfo()
478                    .getName().getLocalPart());
479            }
480            setPojoService(server.getEndpoint().getService().getName());
481            setPojoEndpoint(server.getEndpoint().getEndpointInfo()
482                    .getName().getLocalPart());
483            if (!isUseJBIWrapper() && !isUseSOAPEnvelope()) {
484                removeInterceptor(server.getEndpoint().getBinding()
485                        .getInInterceptors(), "ReadHeadersInterceptor");
486                removeInterceptor(server.getEndpoint().getBinding()
487                        .getInFaultInterceptors(), "ReadHeadersInterceptor");
488                removeInterceptor(server.getEndpoint().getBinding()
489                        .getOutInterceptors(), "SoapOutInterceptor");
490                removeInterceptor(server.getEndpoint().getBinding()
491                        .getOutFaultInterceptors(), "SoapOutInterceptor");
492                removeInterceptor(server.getEndpoint().getBinding()
493                        .getOutInterceptors(), "StaxOutInterceptor");
494            }
495    
496            try {
497                definition = new ServiceWSDLBuilder(getBus(), server
498                        .getEndpoint().getService().getServiceInfos().iterator()
499                        .next()).build();
500                description = WSDLFactory.newInstance().newWSDLWriter()
501                        .getDocument(definition);
502            } catch (WSDLException e) {
503                throw new DeploymentException(e);
504            }
505            ReflectionUtils.doWithFields(getPojo().getClass(), new FieldCallback() {
506                public void doWith(Field field) throws IllegalArgumentException,
507                        IllegalAccessException {
508                    if (field.getAnnotation(WebServiceRef.class) != null) {
509                        ServiceImpl s = new ServiceImpl(getBus(), null, null, field
510                                .getType());
511                        s.addPort(new QName("port"),
512                                JBITransportFactory.TRANSPORT_ID, "jbi://"
513                                        + ID_GENERATOR.generateSanitizedId());
514                        Object o = s.getPort(new QName("port"), field.getType());
515                        field.setAccessible(true);
516                        field.set(getPojo(), o);
517                    }
518                }
519            });
520            ReflectionUtils.callLifecycleMethod(getPojo(), PostConstruct.class);
521            injectPojo();
522        }
523    
524        /*
525         * (non-Javadoc)
526         * 
527         * @see org.apache.servicemix.common.endpoints.ProviderEndpoint#stop()
528         */
529        @Override
530        public void stop() throws Exception {
531            if (isUseAegis()) {
532                server.stop();
533            } else {
534                endpoint.stop();
535            }
536            ReflectionUtils.callLifecycleMethod(getPojo(), PreDestroy.class);
537            JBIDispatcherUtil.clean();
538            JBITransportFactory jbiTransportFactory = (JBITransportFactory) getBus()
539                    .getExtension(ConduitInitiatorManager.class)
540                    .getConduitInitiator(CxfSeComponent.JBI_TRANSPORT_ID);
541            jbiTransportFactory.setDeliveryChannel(null);
542            jbiTransportFactory.removeDestination(getPojoService().toString()
543                    + getPojoInterfaceName().toString());
544            super.stop();
545        }
546    
547        protected Bus getBus() {
548            return ((CxfSeComponent) getServiceUnit().getComponent()).getBus();
549        }
550    
551        @PostConstruct
552        protected void injectPojo() {
553            try {
554                ComponentContext context = getContext();
555                Method mth = pojo.getClass().getMethod("setContext",
556                        new Class[] {ComponentContext.class});
557                if (mth != null) {
558                    mth.invoke(pojo, new Object[] {context});
559                }
560            } catch (Exception e) {
561                //setContext is optional for the pojo
562            }
563    
564        }
565    
566        /**
567         * Specifies if the endpoint can process messages with binary data.
568         * 
569         * @param mtomEnabled
570         *            a <code>boolean</code>
571         * @org.apache.xbean.Property description="Specifies if the service can
572         *                            consume MTOM formatted binary data. The
573         *                            default is <code>false</code>."
574         */
575        public void setMtomEnabled(boolean mtomEnabled) {
576            this.mtomEnabled = mtomEnabled;
577        }
578    
579        public boolean isMtomEnabled() {
580            return mtomEnabled;
581        }
582    
583        public boolean isSchemaValidationEnabled() {
584            return schemaValidationEnabled;
585        }
586    
587        public void setSchemaValidationEnabled(boolean schemaValidationEnabled) {
588            this.schemaValidationEnabled = schemaValidationEnabled;
589        }
590    
591        /**
592         * Specifies if the endpoint expects messages that are encased in the JBI
593         * wrapper used for SOAP messages.
594         * 
595         * @param mtomEnabled
596         *            a <code>boolean</code>
597         * @org.apache.xbean.Property description="Specifies if the endpoint expects
598         *                            to receive the JBI wrapper in the message
599         *                            received from the NMR. The default is
600         *                            <code>true</code>."
601         */
602        public void setUseJBIWrapper(boolean useJBIWrapper) {
603            this.useJBIWrapper = useJBIWrapper;
604        }
605    
606        public boolean isUseJBIWrapper() {
607            return useJBIWrapper;
608        }
609    
610        /**
611         * Specifies if the endpoint expects soap messages when useJBIWrapper is
612         * false, if useJBIWrapper is true then ignore useSOAPEnvelope
613         * 
614         * @org.apache.xbean.Property description="Specifies if the endpoint expects
615         *                            soap messages when useJBIWrapper is false, if
616         *                            useJBIWrapper is true then ignore
617         *                            useSOAPEnvelope. The default is
618         *                            <code>true</code>.
619         */
620        public void setUseSOAPEnvelope(boolean useSOAPEnvelope) {
621            this.useSOAPEnvelope = useSOAPEnvelope;
622        }
623    
624        public boolean isUseSOAPEnvelope() {
625            return useSOAPEnvelope;
626        }
627    
628        /**
629         * Specifies if the endpoint use aegis databinding to marshell/unmarshell message
630         * 
631         * @org.apache.xbean.Property description="Specifies if the endpoint use aegis databinding to marshell/unmarshell message. 
632         * The default is <code>false</code>.
633         */
634        public void setUseAegis(boolean useAegis) {
635            this.useAegis = useAegis;
636        }
637    
638        
639        public boolean isUseAegis() {
640            return useAegis;
641        }
642    
643        protected void setPojoService(QName pojoService) {
644            this.pojoService = pojoService;
645        }
646    
647        protected QName getPojoService() {
648            return pojoService;
649        }
650    
651        protected void setPojoEndpoint(String pojoEndpoint) {
652            this.pojoEndpoint = pojoEndpoint;
653        }
654    
655        protected String getPojoEndpoint() {
656            return pojoEndpoint;
657        }
658    
659        protected void setPojoInterfaceName(QName pojoInterfaceName) {
660            this.pojoInterfaceName = pojoInterfaceName;
661        }
662    
663        protected QName getPojoInterfaceName() {
664            return pojoInterfaceName;
665        }
666    
667    }