1 /*
   2  * Copyright (c) 1997, 2015, 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      */
  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 
 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 
 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 
 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 
 200     static InputStream getFileAsStream(Class clazz, HandlerChain chain) {
 201         Package pkg = clazz.getPackage();
 202         String filename = chain.file();
 203         String fullpath = addPackagePath(filename, pkg);
 204         InputStream is;
 205 
 206         is = moduleResource(clazz, filename);
 207         if (is != null) return is;
 208 
 209         is = moduleResource(clazz, fullpath);
 210         if (is != null) return is;
 211 
 212         URL url = cpResource(clazz, filename);
 213         if (url == null) url = cpResource(clazz, fullpath);
 214 
 215         if (url == null) {
 216             throw new UtilException("util.failed.to.find.handlerchain.file",
 217                     clazz.getName(), filename);
 218         }
 219         try {
 220             return url.openStream();
 221         } catch (IOException e) {
 222             throw new UtilException("util.failed.to.parse.handlerchain.file",
 223                     clazz.getName(), filename);
 224         }
 225     }
 226 
 227     private static URL cpResource(Class clazz, String name) {
 228         URL url = clazz.getResource(name);
 229         if (url == null) {
 230             ClassLoader tccl = Thread.currentThread().getContextClassLoader();
 231             url = tccl.getResource(name);
 232         }
 233         return url;
 234     }
 235 
 236     private static InputStream moduleResource(Class resolvingClass, String name) {
 237         Module module = resolvingClass.getModule();
 238         try {
 239             InputStream stream = module.getResourceAsStream(name);
 240             if (stream != null) {
 241                 return stream;
 242             }
 243         } catch(IOException e) {
 244             throw new UtilException("util.failed.to.find.handlerchain.file",
 245                     resolvingClass.getName(), name);
 246         }
 247         return null;
 248     }
 249 
 250     private static String addPackagePath(String file, Package pkg) {
 251         String tmp = pkg.getName();
 252         tmp = tmp.replace('.', '/');
 253         tmp += "/" + file;
 254         return tmp;
 255     }
 256 }