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 018 package org.apache.geronimo.axis2; 019 020 import java.net.URL; 021 import java.util.ArrayList; 022 import java.util.List; 023 024 import javax.jws.HandlerChain; 025 import javax.jws.WebService; 026 import javax.xml.ws.WebServiceException; 027 import javax.xml.ws.handler.Handler; 028 import javax.xml.ws.handler.LogicalHandler; 029 030 import org.apache.commons.logging.Log; 031 import org.apache.commons.logging.LogFactory; 032 import org.apache.geronimo.xbeans.javaee.HandlerChainType; 033 import org.apache.geronimo.xbeans.javaee.HandlerChainsDocument; 034 import org.apache.geronimo.xbeans.javaee.HandlerChainsType; 035 import org.apache.geronimo.xbeans.javaee.PortComponentHandlerType; 036 037 /** 038 * @version $Rev$ $Date$ 039 */ 040 public class AnnotationHandlerChainBuilder { 041 042 private static final Log log = LogFactory.getLog(AnnotationHandlerChainBuilder.class); 043 044 public AnnotationHandlerChainBuilder() { 045 } 046 047 /** 048 * @param clz 049 * @param existingHandlers 050 * @return 051 */ 052 public List<Handler> buildHandlerChainFromClass(Class<?> clz, List<Handler> existingHandlers) { 053 log.debug("building handler chain"); 054 HandlerChainAnnotation hcAnn = findHandlerChainAnnotation(clz, true); 055 List<Handler> chain = null; 056 if (hcAnn == null) { 057 log.debug("no HandlerChain annotation on " + clz); 058 chain = new ArrayList<Handler>(); 059 } else { 060 hcAnn.validate(); 061 062 try { 063 URL handlerFileURL = clz.getResource(hcAnn.getFileName()); 064 HandlerChainsType handlerChainsType = HandlerChainsDocument.Factory.parse(handlerFileURL).getHandlerChains(); 065 066 if (null == handlerChainsType || handlerChainsType.getHandlerChainArray() == null) { 067 throw new WebServiceException("Chain not specified"); 068 } 069 070 chain = new ArrayList<Handler>(); 071 for (HandlerChainType hc : handlerChainsType.getHandlerChainArray()) { 072 chain.addAll(buildHandlerChain(hc, clz.getClassLoader())); 073 } 074 075 } catch (Exception e) { 076 throw new WebServiceException("Chain not specified", e); 077 } 078 } 079 080 assert chain != null; 081 if (existingHandlers != null) { 082 chain.addAll(existingHandlers); 083 } 084 return sortHandlers(chain); 085 } 086 087 public List<Handler> buildHandlerChainFromClass(Class<?> clz) { 088 return buildHandlerChainFromClass(clz, null); 089 } 090 091 private HandlerChainAnnotation findHandlerChainAnnotation(Class<?> clz, boolean searchSEI) { 092 if (log.isDebugEnabled()) { 093 log.debug("Checking for HandlerChain annotation on " + clz.getName()); 094 } 095 HandlerChainAnnotation hcAnn = null; 096 HandlerChain ann = clz.getAnnotation(HandlerChain.class); 097 if (ann == null) { 098 if (searchSEI) { 099 /* HandlerChain annotation can be specified on the SEI 100 * but the implementation bean might not implement the SEI. 101 */ 102 WebService ws = clz.getAnnotation(WebService.class); 103 if (ws != null 104 && ws.endpointInterface() != null 105 && ws.endpointInterface().trim().length() > 0) { 106 String seiClassName = ws.endpointInterface().trim(); 107 Class seiClass = null; 108 try { 109 seiClass = clz.getClassLoader().loadClass(seiClassName); 110 } catch (ClassNotFoundException e) { 111 throw new WebServiceException("Failed to load SEI class: " + seiClassName, e); 112 } 113 114 // check SEI class and its interfaces for HandlerChain annotation 115 hcAnn = findHandlerChainAnnotation(seiClass, false); 116 } 117 } 118 if (hcAnn == null) { 119 // check interfaces for HandlerChain annotation 120 for (Class<?> iface : clz.getInterfaces()) { 121 if (log.isDebugEnabled()) { 122 log.debug("Checking for HandlerChain annotation on " + iface.getName()); 123 } 124 ann = iface.getAnnotation(HandlerChain.class); 125 if (ann != null) { 126 hcAnn = new HandlerChainAnnotation(ann, iface); 127 break; 128 } 129 } 130 } 131 } else { 132 hcAnn = new HandlerChainAnnotation(ann, clz); 133 } 134 135 return hcAnn; 136 } 137 138 protected List<Handler> buildHandlerChain(HandlerChainType hc, ClassLoader classLoader) { 139 List<Handler> handlerChain = new ArrayList<Handler>(); 140 for (PortComponentHandlerType ht : hc.getHandlerArray()) { 141 try { 142 log.debug("loading handler :" + trimString(ht.getHandlerName().getStringValue())); 143 144 Class<? extends Handler> handlerClass = Class.forName( 145 trimString(ht.getHandlerClass() 146 .getStringValue()), true, classLoader) 147 .asSubclass(Handler.class); 148 149 Handler handler = handlerClass.newInstance(); 150 log.debug("adding handler to chain: " + handler); 151 handlerChain.add(handler); 152 } catch (Exception e) { 153 throw new WebServiceException("Failed to instantiate handler", e); 154 } 155 } 156 return handlerChain; 157 } 158 159 private String trimString(String str) { 160 return str != null ? str.trim() : null; 161 } 162 163 /** 164 * sorts the handlers into correct order. All of the logical handlers first 165 * followed by the protocol handlers 166 * 167 * @param handlers 168 * @return sorted list of handlers 169 */ 170 public List<Handler> sortHandlers(List<Handler> handlers) { 171 172 List<LogicalHandler> logicalHandlers = new ArrayList<LogicalHandler>(); 173 List<Handler> protocolHandlers = new ArrayList<Handler>(); 174 175 for (Handler handler : handlers) { 176 if (handler instanceof LogicalHandler) { 177 logicalHandlers.add((LogicalHandler) handler); 178 } else { 179 protocolHandlers.add(handler); 180 } 181 } 182 183 List<Handler> sortedHandlers = new ArrayList<Handler>(); 184 sortedHandlers.addAll(logicalHandlers); 185 sortedHandlers.addAll(protocolHandlers); 186 return sortedHandlers; 187 } 188 189 private static class HandlerChainAnnotation { 190 private final Class<?> declaringClass; 191 private final HandlerChain ann; 192 193 HandlerChainAnnotation(HandlerChain hc, Class<?> clz) { 194 ann = hc; 195 declaringClass = clz; 196 } 197 198 public Class<?> getDeclaringClass() { 199 return declaringClass; 200 } 201 202 public String getFileName() { 203 return ann.file(); 204 } 205 206 public void validate() { 207 if (null == ann.file() || "".equals(ann.file())) { 208 throw new WebServiceException("@HandlerChain annotation does not contain a file name or url."); 209 } 210 } 211 212 public String toString() { 213 return "[" + declaringClass + "," + ann + "]"; 214 } 215 } 216 }