1 /*
   2  * Copyright (c) 1997, 2017, 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.lang.reflect.Method;
  49 import java.net.URL;
  50 import java.util.logging.Logger;
  51 
  52 /**
  53  * <p>Used by client and server side to create handler information
  54  * from annotated class. The public methods all return a
  55  * HandlerChainInfo that contains the handlers and role information
  56  * needed at runtime.
  57  *
  58  * <p>All of the handler chain descriptors follow the same schema,
  59  * whether they are wsdl customizations, handler files specified
  60  * by an annotation, or are included in the sun-jaxws.xml file.
  61  * So this class is used for all handler xml information. The
  62  * two public entry points are
  63  * {@link HandlerAnnotationProcessor#buildHandlerInfo}, called
  64  * when you have an annotated class that points to a file.
  65  *
  66  * <p>The methods in the class are static so that it may called
  67  * from the runtime statically.
  68  *
  69  * @see com.sun.xml.internal.ws.util.HandlerAnnotationInfo
  70  *
  71  * @author JAX-WS Development Team
  72  */
  73 public class HandlerAnnotationProcessor {
  74 
  75     private static final Logger logger = Logger.getLogger(
  76         com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".util");
  77 
  78     /**
  79      * <p>This method is called by
  80      * {@link EndpointFactory} when
  81      * they have an annotated class.
  82      *
  83      * <p>If there is no handler chain annotation on the class,
  84      * this method will return null. Otherwise it will load the
  85      * class and call the parseHandlerFile method to read the
  86      * information.
  87      *
  88      * @return A HandlerAnnotationInfo object that stores the
  89      * handlers and roles. Will return null if the class passed
  90      * in has no handler chain annotation.
  91      */
  92     public static HandlerAnnotationInfo buildHandlerInfo(@NotNull
  93         Class<?> clazz, QName serviceName, QName portName, WSBinding binding) {
  94 
  95         MetadataReader metadataReader = EndpointFactory.getExternalMetadatReader(clazz, binding);
  96         if (metadataReader == null) {
  97             metadataReader = new ReflectAnnotationReader();
  98         }
  99 
 100 //        clazz = checkClass(clazz);
 101         HandlerChain handlerChain = metadataReader.getAnnotation(HandlerChain.class, clazz);
 102         if (handlerChain == null) {
 103             clazz = getSEI(clazz, metadataReader);
 104             if (clazz != null)
 105             handlerChain = metadataReader.getAnnotation(HandlerChain.class, clazz);
 106             if (handlerChain == null)
 107                 return null;
 108         }
 109 
 110         if (clazz.getAnnotation(SOAPMessageHandlers.class) != null) {
 111             throw new UtilException(
 112                 "util.handler.cannot.combine.soapmessagehandlers");
 113         }
 114         InputStream iStream = getFileAsStream(clazz, handlerChain);
 115         XMLStreamReader reader =
 116             XMLStreamReaderFactory.create(null,iStream, true);
 117         XMLStreamReaderUtil.nextElementContent(reader);
 118         HandlerAnnotationInfo handlerAnnInfo = HandlerChainsModel.parseHandlerFile(reader, clazz.getClassLoader(),
 119             serviceName, portName, binding);
 120         try {
 121             reader.close();
 122             iStream.close();
 123         } catch (XMLStreamException e) {
 124             e.printStackTrace();
 125             throw new UtilException(e.getMessage());
 126         } catch (IOException e) {
 127             e.printStackTrace();
 128             throw new UtilException(e.getMessage());
 129         }
 130         return handlerAnnInfo;
 131     }
 132 
 133     public static HandlerChainsModel buildHandlerChainsModel(final Class<?> clazz) {
 134         if(clazz == null) {
 135             return null;
 136         }
 137         HandlerChain handlerChain =
 138             clazz.getAnnotation(HandlerChain.class);
 139         if(handlerChain == null)
 140             return null;
 141         InputStream iStream = getFileAsStream(clazz, handlerChain);
 142         XMLStreamReader reader =
 143             XMLStreamReaderFactory.create(null,iStream, true);
 144         XMLStreamReaderUtil.nextElementContent(reader);
 145         HandlerChainsModel handlerChainsModel = HandlerChainsModel.parseHandlerConfigFile(clazz, reader);
 146         try {
 147             reader.close();
 148             iStream.close();
 149         } catch (XMLStreamException e) {
 150             e.printStackTrace();
 151             throw new UtilException(e.getMessage());
 152         } catch (IOException e) {
 153             e.printStackTrace();
 154             throw new UtilException(e.getMessage());
 155         }
 156         return handlerChainsModel;
 157     }
 158 
 159     static Class getClass(String className) {
 160         try {
 161             return Thread.currentThread().getContextClassLoader().loadClass(
 162                 className);
 163         } catch (ClassNotFoundException e) {
 164             throw new UtilException("util.handler.class.not.found",
 165                 className);
 166         }
 167     }
 168 
 169     static Class getSEI(Class<?> clazz, MetadataReader metadataReader) {
 170         if (metadataReader == null) {
 171             metadataReader = new ReflectAnnotationReader();
 172         }
 173 
 174         if (Provider.class.isAssignableFrom(clazz) || AsyncProvider.class.isAssignableFrom(clazz)) {
 175             //No SEI for Provider Implementation
 176             return null;
 177         }
 178         if (Service.class.isAssignableFrom(clazz)) {
 179             //No SEI for Service class
 180             return null;
 181         }
 182 
 183         WebService webService = metadataReader.getAnnotation(WebService.class, clazz);
 184         if (webService == null) {
 185             throw new UtilException("util.handler.no.webservice.annotation", clazz.getCanonicalName());
 186         }
 187 
 188         String ei = webService.endpointInterface();
 189         if (ei.length() > 0) {
 190             clazz = getClass(webService.endpointInterface());
 191             WebService ws = metadataReader.getAnnotation(WebService.class, clazz);
 192             if (ws == null) {
 193                 throw new UtilException("util.handler.endpoint.interface.no.webservice",
 194                     webService.endpointInterface());
 195             }
 196             return clazz;
 197         }
 198         return null;
 199     }
 200 
 201     static InputStream getFileAsStream(Class clazz, HandlerChain chain) {
 202         Package pkg = clazz.getPackage();
 203         String filename = chain.file();
 204         String fullpath = addPackagePath(filename, pkg);
 205         InputStream is;
 206 
 207         is = moduleResource(clazz, filename);
 208         if (is != null) return is;
 209 
 210         is = moduleResource(clazz, fullpath);
 211         if (is != null) return is;
 212 
 213         URL url = cpResource(clazz, filename);
 214         if (url == null) url = cpResource(clazz, fullpath);
 215 
 216         if (url == null) {
 217             throw new UtilException("util.failed.to.find.handlerchain.file",
 218                     clazz.getName(), filename);
 219         }
 220         try {
 221             return url.openStream();
 222         } catch (IOException e) {
 223             throw new UtilException("util.failed.to.parse.handlerchain.file",
 224                     clazz.getName(), filename);
 225         }
 226     }
 227 
 228     private static URL cpResource(Class clazz, String name) {
 229         URL url = clazz.getResource(name);
 230         if (url == null) {
 231             ClassLoader tccl = Thread.currentThread().getContextClassLoader();
 232             url = tccl.getResource(name);
 233         }
 234         return url;
 235     }
 236 
 237     private static InputStream moduleResource(Class resolvingClass, String name) {
 238         Module module = resolvingClass.getModule();
 239         try {
 240             InputStream stream = module.getResourceAsStream(name);
 241             if (stream != null) {
 242                 return stream;
 243             }
 244         } catch(IOException e) {
 245             throw new UtilException("util.failed.to.find.handlerchain.file",
 246                     resolvingClass.getName(), name);
 247         }
 248         return null;
 249     }
 250 
 251     private static String addPackagePath(String file, Package pkg) {
 252         String tmp = pkg.getName();
 253         tmp = tmp.replace('.', '/');
 254         tmp += "/" + file;
 255         return tmp;
 256     }
 257 }