1 /*
2  * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.xml.internal.ws.util;
27 
28 import com.sun.xml.internal.ws.api.WSBinding;
29 import com.sun.xml.internal.ws.api.databinding.MetadataReader;
30 import com.sun.xml.internal.ws.api.server.AsyncProvider;
31 import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
32 import com.sun.xml.internal.ws.handler.HandlerChainsModel;
33 import com.sun.xml.internal.ws.model.ReflectAnnotationReader;
34 import com.sun.xml.internal.ws.server.EndpointFactory;
35 import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
36 import com.sun.istack.internal.NotNull;
37 
38 import javax.jws.HandlerChain;
39 import javax.jws.WebService;
40 import javax.jws.soap.SOAPMessageHandlers;
41 import javax.xml.namespace.QName;
42 import javax.xml.stream.XMLStreamException;
43 import javax.xml.stream.XMLStreamReader;
44 import javax.xml.ws.Provider;
45 import javax.xml.ws.Service;
46 import java.io.IOException;
47 import java.io.InputStream;
48 import java.net.URL;
49 import java.util.logging.Logger;
50 
51 /**
52  * <p>Used by client and server side to create handler information
53  * from annotated class. The public methods all return a
54  * HandlerChainInfo that contains the handlers and role information
55  * needed at runtime.
56  *
57  * <p>All of the handler chain descriptors follow the same schema,
58  * whether they are wsdl customizations, handler files specified
59  * by an annotation, or are included in the sun-jaxws.xml file.
60  * So this class is used for all handler xml information. The
61  * two public entry points are
62  * {@link HandlerAnnotationProcessor#buildHandlerInfo}, called
63  * when you have an annotated class that points to a file.
64  *
65  * <p>The methods in the class are static so that it may called
66  * from the runtime statically.
67  *
68  * @see com.sun.xml.internal.ws.util.HandlerAnnotationInfo
69  *
70  * @author JAX-WS Development Team
71  */
72 public class HandlerAnnotationProcessor {
73 
74     private static final Logger logger = Logger.getLogger(
75         com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".util");
76 
77     /**
78      * <p>This method is called by
79      * {@link EndpointFactory} when
80      * they have an annotated class.
81      *
82      * <p>If there is no handler chain annotation on the class,
83      * this method will return null. Otherwise it will load the
84      * class and call the parseHandlerFile method to read the
85      * information.
86      *
87      * @return A HandlerAnnotationInfo object that stores the
88      * handlers and roles. Will return null if the class passed
89      * in has no handler chain annotation.
90      */
buildHandlerInfo(@otNull Class<?> clazz, QName serviceName, QName portName, WSBinding binding)91     public static HandlerAnnotationInfo buildHandlerInfo(@NotNull
92         Class<?> clazz, QName serviceName, QName portName, WSBinding binding) {
93 
94         MetadataReader metadataReader = EndpointFactory.getExternalMetadatReader(clazz, binding);
95         if (metadataReader == null) {
96             metadataReader = new ReflectAnnotationReader();
97         }
98 
99 //        clazz = checkClass(clazz);
100         HandlerChain handlerChain = metadataReader.getAnnotation(HandlerChain.class, clazz);
101         if (handlerChain == null) {
102             clazz = getSEI(clazz, metadataReader);
103             if (clazz != null)
104             handlerChain = metadataReader.getAnnotation(HandlerChain.class, clazz);
105             if (handlerChain == null)
106                 return null;
107         }
108 
109         if (clazz.getAnnotation(SOAPMessageHandlers.class) != null) {
110             throw new UtilException(
111                 "util.handler.cannot.combine.soapmessagehandlers");
112         }
113         InputStream iStream = getFileAsStream(clazz, handlerChain);
114         XMLStreamReader reader =
115             XMLStreamReaderFactory.create(null,iStream, true);
116         XMLStreamReaderUtil.nextElementContent(reader);
117         HandlerAnnotationInfo handlerAnnInfo = HandlerChainsModel.parseHandlerFile(reader, clazz.getClassLoader(),
118             serviceName, portName, binding);
119         try {
120             reader.close();
121             iStream.close();
122         } catch (XMLStreamException e) {
123             e.printStackTrace();
124             throw new UtilException(e.getMessage());
125         } catch (IOException e) {
126             e.printStackTrace();
127             throw new UtilException(e.getMessage());
128         }
129         return handlerAnnInfo;
130     }
131 
buildHandlerChainsModel(final Class<?> clazz)132     public static HandlerChainsModel buildHandlerChainsModel(final Class<?> clazz) {
133         if(clazz == null) {
134             return null;
135         }
136         HandlerChain handlerChain =
137             clazz.getAnnotation(HandlerChain.class);
138         if(handlerChain == null)
139             return null;
140         InputStream iStream = getFileAsStream(clazz, handlerChain);
141         XMLStreamReader reader =
142             XMLStreamReaderFactory.create(null,iStream, true);
143         XMLStreamReaderUtil.nextElementContent(reader);
144         HandlerChainsModel handlerChainsModel = HandlerChainsModel.parseHandlerConfigFile(clazz, reader);
145         try {
146             reader.close();
147             iStream.close();
148         } catch (XMLStreamException e) {
149             e.printStackTrace();
150             throw new UtilException(e.getMessage());
151         } catch (IOException e) {
152             e.printStackTrace();
153             throw new UtilException(e.getMessage());
154         }
155         return handlerChainsModel;
156     }
157 
getClass(String className)158     static Class getClass(String className) {
159         try {
160             return Thread.currentThread().getContextClassLoader().loadClass(
161                 className);
162         } catch (ClassNotFoundException e) {
163             throw new UtilException("util.handler.class.not.found",
164                 className);
165         }
166     }
167 
getSEI(Class<?> clazz, MetadataReader metadataReader)168     static Class getSEI(Class<?> clazz, MetadataReader metadataReader) {
169         if (metadataReader == null) {
170             metadataReader = new ReflectAnnotationReader();
171         }
172 
173         if (Provider.class.isAssignableFrom(clazz) || AsyncProvider.class.isAssignableFrom(clazz)) {
174             //No SEI for Provider Implementation
175             return null;
176         }
177         if (Service.class.isAssignableFrom(clazz)) {
178             //No SEI for Service class
179             return null;
180         }
181 
182         WebService webService = metadataReader.getAnnotation(WebService.class, clazz);
183         if (webService == null) {
184             throw new UtilException("util.handler.no.webservice.annotation", clazz.getCanonicalName());
185         }
186 
187         String ei = webService.endpointInterface();
188         if (ei.length() > 0) {
189             clazz = getClass(webService.endpointInterface());
190             WebService ws = metadataReader.getAnnotation(WebService.class, clazz);
191             if (ws == null) {
192                 throw new UtilException("util.handler.endpoint.interface.no.webservice",
193                     webService.endpointInterface());
194             }
195             return clazz;
196         }
197         return null;
198     }
199 
getFileAsStream(Class clazz, HandlerChain chain)200    static InputStream getFileAsStream(Class clazz, HandlerChain chain) {
201         URL url = clazz.getResource(chain.file());
202         if (url == null) {
203             url = Thread.currentThread().getContextClassLoader().
204                 getResource(chain.file());
205         }
206         if (url == null) {
207             String tmp = clazz.getPackage().getName();
208             tmp = tmp.replace('.', '/');
209             tmp += "/" + chain.file();
210             url =
211                 Thread.currentThread().getContextClassLoader().getResource(tmp);
212         }
213         if (url == null) {
214             throw new UtilException("util.failed.to.find.handlerchain.file",
215                 clazz.getName(), chain.file());
216         }
217         try {
218             return url.openStream();
219         } catch (IOException e) {
220             throw new UtilException("util.failed.to.parse.handlerchain.file",
221                 clazz.getName(), chain.file());
222         }
223     }
224 }
225