1/* 2 * Copyright (c) 1997, 2013, 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 26package com.sun.xml.internal.ws.assembler; 27 28import com.sun.istack.internal.NotNull; 29import com.sun.istack.internal.logging.Logger; 30import com.sun.xml.internal.ws.api.BindingID; 31import com.sun.xml.internal.ws.api.pipe.ClientTubeAssemblerContext; 32import com.sun.xml.internal.ws.api.pipe.ServerTubeAssemblerContext; 33import com.sun.xml.internal.ws.api.pipe.Tube; 34import com.sun.xml.internal.ws.api.pipe.TubelineAssembler; 35import com.sun.xml.internal.ws.assembler.dev.TubelineAssemblyDecorator; 36import com.sun.xml.internal.ws.dump.LoggingDumpTube; 37import com.sun.xml.internal.ws.resources.TubelineassemblyMessages; 38import com.sun.xml.internal.ws.util.ServiceFinder; 39 40import java.util.Collection; 41import java.util.logging.Level; 42 43/** 44* TODO: Write some description here ... 45* 46* @author Miroslav Kos (miroslav.kos at oracle.com) 47*/ 48public class MetroTubelineAssembler implements TubelineAssembler { 49 50 private static final String COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE = "com.sun.metro.soap.dump"; 51 public static final MetroConfigNameImpl JAXWS_TUBES_CONFIG_NAMES = new MetroConfigNameImpl("jaxws-tubes-default.xml", "jaxws-tubes.xml"); 52 53 private static enum Side { 54 55 Client("client"), 56 Endpoint("endpoint"); 57 private final String name; 58 59 private Side(String name) { 60 this.name = name; 61 } 62 63 @Override 64 public String toString() { 65 return name; 66 } 67 } 68 69 private static class MessageDumpingInfo { 70 71 final boolean dumpBefore; 72 final boolean dumpAfter; 73 final Level logLevel; 74 75 MessageDumpingInfo(boolean dumpBefore, boolean dumpAfter, Level logLevel) { 76 this.dumpBefore = dumpBefore; 77 this.dumpAfter = dumpAfter; 78 this.logLevel = logLevel; 79 } 80 } 81 82 private static final Logger LOGGER = Logger.getLogger(MetroTubelineAssembler.class); 83 private final BindingID bindingId; 84 private final TubelineAssemblyController tubelineAssemblyController; 85 86 public MetroTubelineAssembler(final BindingID bindingId, MetroConfigName metroConfigName) { 87 this.bindingId = bindingId; 88 this.tubelineAssemblyController = new TubelineAssemblyController(metroConfigName); 89 } 90 91 TubelineAssemblyController getTubelineAssemblyController() { 92 return tubelineAssemblyController; 93 } 94 95 @NotNull 96 public Tube createClient(@NotNull ClientTubeAssemblerContext jaxwsContext) { 97 if (LOGGER.isLoggable(Level.FINER)) { 98 LOGGER.finer("Assembling client-side tubeline for WS endpoint: " + jaxwsContext.getAddress().getURI().toString()); 99 } 100 101 DefaultClientTubelineAssemblyContext context = createClientContext(jaxwsContext); 102 103 Collection<TubeCreator> tubeCreators = tubelineAssemblyController.getTubeCreators(context); 104 105 for (TubeCreator tubeCreator : tubeCreators) { 106 tubeCreator.updateContext(context); 107 } 108 109 TubelineAssemblyDecorator decorator = TubelineAssemblyDecorator.composite( 110 ServiceFinder.find(TubelineAssemblyDecorator.class, context.getContainer())); 111 112 boolean first = true; 113 for (TubeCreator tubeCreator : tubeCreators) { 114 final MessageDumpingInfo msgDumpInfo = setupMessageDumping(tubeCreator.getMessageDumpPropertyBase(), Side.Client); 115 116 final Tube oldTubelineHead = context.getTubelineHead(); 117 LoggingDumpTube afterDumpTube = null; 118 if (msgDumpInfo.dumpAfter) { 119 afterDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.After, context.getTubelineHead()); 120 context.setTubelineHead(afterDumpTube); 121 } 122 123 if (!context.setTubelineHead(decorator.decorateClient(tubeCreator.createTube(context), context))) { // no new tube has been created 124 if (afterDumpTube != null) { 125 context.setTubelineHead(oldTubelineHead); // removing possible "after" message dumping tube 126 } 127 } else { 128 final String loggedTubeName = context.getTubelineHead().getClass().getName(); 129 if (afterDumpTube != null) { 130 afterDumpTube.setLoggedTubeName(loggedTubeName); 131 } 132 133 if (msgDumpInfo.dumpBefore) { 134 final LoggingDumpTube beforeDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.Before, context.getTubelineHead()); 135 beforeDumpTube.setLoggedTubeName(loggedTubeName); 136 context.setTubelineHead(beforeDumpTube); 137 } 138 } 139 140 if (first) { 141 context.setTubelineHead(decorator.decorateClientTail(context.getTubelineHead(), context)); 142 first = false; 143 } 144 } 145 146 return decorator.decorateClientHead(context.getTubelineHead(), context); 147 } 148 149 @NotNull 150 public Tube createServer(@NotNull ServerTubeAssemblerContext jaxwsContext) { 151 if (LOGGER.isLoggable(Level.FINER)) { 152 LOGGER.finer("Assembling endpoint tubeline for WS endpoint: " + jaxwsContext.getEndpoint().getServiceName() + "::" + jaxwsContext.getEndpoint().getPortName()); 153 } 154 155 DefaultServerTubelineAssemblyContext context = createServerContext(jaxwsContext); 156 157 // FIXME endpoint URI for provider case 158 Collection<TubeCreator> tubeCreators = tubelineAssemblyController.getTubeCreators(context); 159 for (TubeCreator tubeCreator : tubeCreators) { 160 tubeCreator.updateContext(context); 161 } 162 163 TubelineAssemblyDecorator decorator = TubelineAssemblyDecorator.composite( 164 ServiceFinder.find(TubelineAssemblyDecorator.class, context.getEndpoint().getContainer())); 165 166 boolean first = true; 167 for (TubeCreator tubeCreator : tubeCreators) { 168 final MessageDumpingInfo msgDumpInfo = setupMessageDumping(tubeCreator.getMessageDumpPropertyBase(), Side.Endpoint); 169 170 final Tube oldTubelineHead = context.getTubelineHead(); 171 LoggingDumpTube afterDumpTube = null; 172 if (msgDumpInfo.dumpAfter) { 173 afterDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.After, context.getTubelineHead()); 174 context.setTubelineHead(afterDumpTube); 175 } 176 177 if (!context.setTubelineHead(decorator.decorateServer(tubeCreator.createTube(context), context))) { // no new tube has been created 178 if (afterDumpTube != null) { 179 context.setTubelineHead(oldTubelineHead); // removing possible "after" message dumping tube 180 } 181 } else { 182 final String loggedTubeName = context.getTubelineHead().getClass().getName(); 183 if (afterDumpTube != null) { 184 afterDumpTube.setLoggedTubeName(loggedTubeName); 185 } 186 187 if (msgDumpInfo.dumpBefore) { 188 final LoggingDumpTube beforeDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.Before, context.getTubelineHead()); 189 beforeDumpTube.setLoggedTubeName(loggedTubeName); 190 context.setTubelineHead(beforeDumpTube); 191 } 192 } 193 194 if (first) { 195 context.setTubelineHead(decorator.decorateServerTail(context.getTubelineHead(), context)); 196 first = false; 197 } 198 } 199 200 return decorator.decorateServerHead(context.getTubelineHead(), context); 201 } 202 203 private MessageDumpingInfo setupMessageDumping(String msgDumpSystemPropertyBase, Side side) { 204 boolean dumpBefore = false; 205 boolean dumpAfter = false; 206 Level logLevel = Level.INFO; 207 208 // checking common properties 209 Boolean value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE); 210 if (value != null) { 211 dumpBefore = value.booleanValue(); 212 dumpAfter = value.booleanValue(); 213 } 214 215 value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".before"); 216 dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; 217 218 value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".after"); 219 dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; 220 221 Level levelValue = getLevelValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".level"); 222 if (levelValue != null) { 223 logLevel = levelValue; 224 } 225 226 // narrowing to proper communication side on common properties 227 value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString()); 228 if (value != null) { 229 dumpBefore = value.booleanValue(); 230 dumpAfter = value.booleanValue(); 231 } 232 233 value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".before"); 234 dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; 235 236 value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".after"); 237 dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; 238 239 levelValue = getLevelValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".level"); 240 if (levelValue != null) { 241 logLevel = levelValue; 242 } 243 244 245 // checking general tube-specific properties 246 value = getBooleanValue(msgDumpSystemPropertyBase); 247 if (value != null) { 248 dumpBefore = value.booleanValue(); 249 dumpAfter = value.booleanValue(); 250 } 251 252 value = getBooleanValue(msgDumpSystemPropertyBase + ".before"); 253 dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; 254 255 value = getBooleanValue(msgDumpSystemPropertyBase + ".after"); 256 dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; 257 258 levelValue = getLevelValue(msgDumpSystemPropertyBase + ".level"); 259 if (levelValue != null) { 260 logLevel = levelValue; 261 } 262 263 // narrowing to proper communication side on tube-specific properties 264 msgDumpSystemPropertyBase += "." + side.toString(); 265 266 value = getBooleanValue(msgDumpSystemPropertyBase); 267 if (value != null) { 268 dumpBefore = value.booleanValue(); 269 dumpAfter = value.booleanValue(); 270 } 271 272 value = getBooleanValue(msgDumpSystemPropertyBase + ".before"); 273 dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; 274 275 value = getBooleanValue(msgDumpSystemPropertyBase + ".after"); 276 dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; 277 278 levelValue = getLevelValue(msgDumpSystemPropertyBase + ".level"); 279 if (levelValue != null) { 280 logLevel = levelValue; 281 } 282 283 return new MessageDumpingInfo(dumpBefore, dumpAfter, logLevel); 284 } 285 286 private Boolean getBooleanValue(String propertyName) { 287 Boolean retVal = null; 288 289 String stringValue = System.getProperty(propertyName); 290 if (stringValue != null) { 291 retVal = Boolean.valueOf(stringValue); 292 LOGGER.fine(TubelineassemblyMessages.MASM_0018_MSG_LOGGING_SYSTEM_PROPERTY_SET_TO_VALUE(propertyName, retVal)); 293 } 294 295 return retVal; 296 } 297 298 private Level getLevelValue(String propertyName) { 299 Level retVal = null; 300 301 String stringValue = System.getProperty(propertyName); 302 if (stringValue != null) { 303 // if value is not null => property is set, we will try to override the default logging level 304 LOGGER.fine(TubelineassemblyMessages.MASM_0018_MSG_LOGGING_SYSTEM_PROPERTY_SET_TO_VALUE(propertyName, stringValue)); 305 try { 306 retVal = Level.parse(stringValue); 307 } catch (IllegalArgumentException ex) { 308 LOGGER.warning(TubelineassemblyMessages.MASM_0019_MSG_LOGGING_SYSTEM_PROPERTY_ILLEGAL_VALUE(propertyName, stringValue), ex); 309 } 310 } 311 312 return retVal; 313 } 314 315 // Extension point to change Tubeline Assembly behaviour: override if necessary ... 316 protected DefaultServerTubelineAssemblyContext createServerContext(ServerTubeAssemblerContext jaxwsContext) { 317 return new DefaultServerTubelineAssemblyContext(jaxwsContext); 318 } 319 320 // Extension point to change Tubeline Assembly behaviour: override if necessary ... 321 protected DefaultClientTubelineAssemblyContext createClientContext(ClientTubeAssemblerContext jaxwsContext) { 322 return new DefaultClientTubelineAssemblyContext(jaxwsContext); 323 } 324 325} 326