001: /*
002: * JFox - The most lightweight Java EE Application Server!
003: * more details please visit http://www.huihoo.org/jfox or http://www.jfox.org.cn.
004: *
005: * JFox is licenced and re-distributable under GNU LGPL.
006: */
007: package org.jfox.webservice.xfire;
008:
009: import java.io.IOException;
010: import java.lang.reflect.Method;
011: import java.net.URL;
012: import java.util.HashMap;
013: import java.util.Map;
014: import javax.jws.WebService;
015: import javax.xml.namespace.QName;
016:
017: import org.apache.log4j.Logger;
018: import org.codehaus.xfire.MessageContext;
019: import org.codehaus.xfire.XFire;
020: import org.codehaus.xfire.XFireFactory;
021: import org.codehaus.xfire.annotations.AnnotationException;
022: import org.codehaus.xfire.annotations.AnnotationServiceFactory;
023: import org.codehaus.xfire.fault.XFireFault;
024: import org.codehaus.xfire.service.binding.ObjectServiceFactory;
025: import org.codehaus.xfire.service.invoker.Invoker;
026: import org.codehaus.xfire.transport.TransportManager;
027: import org.codehaus.xfire.util.NamespaceHelper;
028: import org.codehaus.xfire.wsdl.ResourceWSDL;
029: import org.jfox.ejb3.EJBBucket;
030: import org.jfox.ejb3.EJBContainer;
031: import org.jfox.ejb3.EJBObjectId;
032: import org.jfox.ejb3.StatelessBucket;
033: import org.jfox.ejb3.event.EJBLoadedComponentEvent;
034: import org.jfox.ejb3.event.EJBUnloadedComponentEvent;
035: import org.jfox.ejb3.security.SecurityContext;
036: import org.jfox.framework.annotation.Inject;
037: import org.jfox.framework.annotation.Service;
038: import org.jfox.framework.component.ActiveComponent;
039: import org.jfox.framework.component.ComponentContext;
040: import org.jfox.framework.component.ComponentInitialization;
041: import org.jfox.framework.component.ComponentUnregistration;
042: import org.jfox.framework.event.ComponentEvent;
043: import org.jfox.framework.event.ComponentListener;
044: import org.jfox.mvc.SessionContext;
045: import org.jfox.webservice.WSContainer;
046:
047: /**
048: * 使用 XFire 实现 Web Service
049: *
050: * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
051: */
052: @Service(priority=Integer.MIN_VALUE)
053: public class JFoxXFireDelegate implements WSContainer, Invoker,
054: ComponentInitialization, ActiveComponent,
055: ComponentUnregistration, ComponentListener {
056:
057: private static final Logger logger = Logger
058: .getLogger(JFoxXFireDelegate.class);
059:
060: @Inject
061: EJBContainer ejbContainer;
062:
063: /**
064: * XFire instance
065: */
066: private XFire xfire;
067:
068: /**
069: * EJB XFire Service Factory
070: */
071: private EJBServiceFactory factory;
072:
073: public static JFoxXFireDelegate xFireDelegate = null;
074:
075: /**
076: * EJB Endpoint interface => ejb name
077: * 以便 webservice 调用 ejb çš„æ—¶å€™ï¼Œèƒ½å¤Ÿæ ¹æ?® interface 找到 ejb
078: */
079: private Map<String, String> endpointInterface2EJBNameMap = new HashMap<String, String>();
080:
081: public static XFire getXFireInstance() {
082: if (xFireDelegate == null) {
083: throw new NullPointerException("XFire is not initialized!");
084: }
085: return xFireDelegate.xfire;
086: }
087:
088: public void postContruct(ComponentContext componentContext) {
089: xfire = XFireFactory.newInstance().getXFire();
090: //是��以考虑直接使用 XFire 的 JAXAWSServiceFactory
091: factory = new EJBServiceFactory(xfire.getTransportManager());
092: xFireDelegate = this ;
093: }
094:
095: public void postInject() {
096: // need do nothing
097: }
098:
099: public boolean preUnregister(ComponentContext context) {
100: return true;
101: }
102:
103: public void postUnregister() {
104:
105: }
106:
107: public void componentChanged(ComponentEvent componentEvent) {
108: if (componentEvent instanceof EJBLoadedComponentEvent) {
109: EJBBucket ejbBucket = ((EJBLoadedComponentEvent) componentEvent)
110: .getEJBBucket();
111: if (ejbBucket instanceof StatelessBucket) {
112: Class wsEndpointInterface = ((StatelessBucket) ejbBucket)
113: .getWebServiceEndpointInterface();
114: if (wsEndpointInterface != null) {
115: // 把 EJB �布� WebService
116: endpointInterface2EJBNameMap.put(
117: wsEndpointInterface.getName(), ejbBucket
118: .getEJBName());
119: // create xfire service by stateless bucket
120: org.codehaus.xfire.service.Service service = factory
121: .create((StatelessBucket) ejbBucket);
122: service.setInvoker(this );
123: if (xfire.getServiceRegistry().hasService(
124: service.getSimpleName())
125: || xfire.getServiceRegistry().hasService(
126: service.getName())) {
127: logger.warn("Web Service with QName "
128: + service.getName()
129: + " has already beean registered!");
130: return;
131: }
132: xfire.getServiceRegistry().register(service);
133: logger.info("Web Service with QName "
134: + service.getName()
135: + " registered successfully!");
136: }
137: }
138: } else if (componentEvent instanceof EJBUnloadedComponentEvent) {
139: EJBBucket ejbBucket = ((EJBUnloadedComponentEvent) componentEvent)
140: .getEJBBucket();
141: if (ejbBucket instanceof StatelessBucket) {
142: Class wsEndpointInterface = ((StatelessBucket) ejbBucket)
143: .getWebServiceEndpointInterface();
144: if (wsEndpointInterface != null) {
145: // xfire.getServiceRegistry().unregister();
146: endpointInterface2EJBNameMap
147: .remove(wsEndpointInterface.getName());
148: logger.info("Web Service with endpoint interface "
149: + wsEndpointInterface.getName()
150: + " unregistered!");
151: }
152: }
153: }
154:
155: }
156:
157: /**
158: * 通过 EJBContainer 完�对 EJB 的调用
159: *
160: * @param method �调用的方法
161: * @param params å?‚æ•°
162: * @param messageContext soap message context
163: * @return method invocation result
164: * @throws XFireFault
165: */
166: public Object invoke(Method method, Object[] params,
167: MessageContext messageContext) throws XFireFault {
168: SecurityContext securityContext = new SecurityContext();
169: SessionContext sessionContext = SessionContext
170: .getCurrentThreadSessionContext();
171:
172: String ejbName = getEJBNameByWebServiceEndpointInterface(messageContext
173: .getService().getServiceInfo().getServiceClass());
174: try {
175: // stateless, 直接用 ejb name � ejb id
176: return ejbContainer.invokeEJB(new EJBObjectId(ejbName),
177: method, params, sessionContext);
178: } catch (Exception e) {
179: return new XFireFault(e);
180: }
181: }
182:
183: private String getEJBNameByWebServiceEndpointInterface(
184: Class endpointInterface) {
185: return endpointInterface2EJBNameMap.get(endpointInterface
186: .getName());
187: }
188:
189: /**
190: * EJB Service Factory
191: */
192: class EJBServiceFactory extends ObjectServiceFactory {
193:
194: public EJBServiceFactory(TransportManager transportManager) {
195: super (transportManager);
196: }
197:
198: org.codehaus.xfire.service.Service create(
199: StatelessBucket ejbBucket) {
200: Map<String, Object> properties = new HashMap<String, Object>();
201: WebService wsAnnotation = ejbBucket
202: .getWebServiceAnnotation();
203: Class endpointInterface = ejbBucket
204: .getWebServiceEndpointInterface();
205:
206: String serviceName = wsAnnotation.serviceName();
207: if (serviceName == null || serviceName.trim().length() == 0) {
208: serviceName = ejbBucket.getBeanClass().getSimpleName();
209: }
210:
211: String serviceNameSpace = wsAnnotation.targetNamespace();
212: if (serviceNameSpace == null
213: || serviceNameSpace.trim().length() == 0) {
214: serviceNameSpace = NamespaceHelper
215: .makeNamespaceFromClassName(ejbBucket
216: .getBeanClass().getName(), "http");
217: }
218:
219: String portType = wsAnnotation.name();
220: if (portType == null || portType.trim().length() == 0) {
221: portType = serviceName + "PortType";
222: }
223:
224: properties.put(PORT_TYPE, new QName(serviceNameSpace,
225: portType));
226: String pname = wsAnnotation.portName();
227: if (pname != null && pname.length() > 0) {
228: properties.put(PORT_NAME, new QName(serviceNameSpace,
229: pname));
230: }
231:
232: org.codehaus.xfire.service.Service service = create(
233: endpointInterface, serviceName, serviceNameSpace,
234: properties);
235: String wsdl = wsAnnotation.wsdlLocation();
236: if (wsdl != null && wsdl.length() > 0) {
237: try {
238: service.setWSDLWriter(new ResourceWSDL(wsdl));
239: } catch (IOException e) {
240: throw new AnnotationException(
241: "Couldn't load wsdl from " + wsdl, e);
242: }
243: }
244: return service;
245: }
246:
247: @SuppressWarnings("unchecked")
248: public org.codehaus.xfire.service.Service create(Class clazz,
249: QName name, URL wsdlUrl, Map properties) {
250: if (properties == null) {
251: properties = new HashMap();
252: }
253: properties.put(AnnotationServiceFactory.ALLOW_INTERFACE,
254: Boolean.TRUE);
255: return super.create(clazz, name, wsdlUrl, properties);
256: }
257:
258: }
259: }
|