aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.ws.assembler; aoqi@0: aoqi@0: import com.sun.istack.internal.NotNull; aoqi@0: import com.sun.istack.internal.logging.Logger; aoqi@0: import com.sun.xml.internal.ws.api.BindingID; aoqi@0: import com.sun.xml.internal.ws.api.pipe.ClientTubeAssemblerContext; aoqi@0: import com.sun.xml.internal.ws.api.pipe.ServerTubeAssemblerContext; aoqi@0: import com.sun.xml.internal.ws.api.pipe.Tube; aoqi@0: import com.sun.xml.internal.ws.api.pipe.TubelineAssembler; aoqi@0: import com.sun.xml.internal.ws.assembler.dev.TubelineAssemblyDecorator; aoqi@0: import com.sun.xml.internal.ws.dump.LoggingDumpTube; aoqi@0: import com.sun.xml.internal.ws.resources.TubelineassemblyMessages; aoqi@0: import com.sun.xml.internal.ws.util.ServiceFinder; aoqi@0: aoqi@0: import java.util.Collection; aoqi@0: import java.util.logging.Level; aoqi@0: aoqi@0: /** aoqi@0: * TODO: Write some description here ... aoqi@0: * aoqi@0: * @author Miroslav Kos (miroslav.kos at oracle.com) aoqi@0: */ aoqi@0: public class MetroTubelineAssembler implements TubelineAssembler { aoqi@0: aoqi@0: private static final String COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE = "com.sun.metro.soap.dump"; aoqi@0: public static final MetroConfigNameImpl JAXWS_TUBES_CONFIG_NAMES = new MetroConfigNameImpl("jaxws-tubes-default.xml", "jaxws-tubes.xml"); aoqi@0: aoqi@0: private static enum Side { aoqi@0: aoqi@0: Client("client"), aoqi@0: Endpoint("endpoint"); aoqi@0: private final String name; aoqi@0: aoqi@0: private Side(String name) { aoqi@0: this.name = name; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String toString() { aoqi@0: return name; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static class MessageDumpingInfo { aoqi@0: aoqi@0: final boolean dumpBefore; aoqi@0: final boolean dumpAfter; aoqi@0: final Level logLevel; aoqi@0: aoqi@0: MessageDumpingInfo(boolean dumpBefore, boolean dumpAfter, Level logLevel) { aoqi@0: this.dumpBefore = dumpBefore; aoqi@0: this.dumpAfter = dumpAfter; aoqi@0: this.logLevel = logLevel; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static final Logger LOGGER = Logger.getLogger(MetroTubelineAssembler.class); aoqi@0: private final BindingID bindingId; aoqi@0: private final TubelineAssemblyController tubelineAssemblyController; aoqi@0: aoqi@0: public MetroTubelineAssembler(final BindingID bindingId, MetroConfigName metroConfigName) { aoqi@0: this.bindingId = bindingId; aoqi@0: this.tubelineAssemblyController = new TubelineAssemblyController(metroConfigName); aoqi@0: } aoqi@0: aoqi@0: TubelineAssemblyController getTubelineAssemblyController() { aoqi@0: return tubelineAssemblyController; aoqi@0: } aoqi@0: aoqi@0: @NotNull aoqi@0: public Tube createClient(@NotNull ClientTubeAssemblerContext jaxwsContext) { aoqi@0: if (LOGGER.isLoggable(Level.FINER)) { aoqi@0: LOGGER.finer("Assembling client-side tubeline for WS endpoint: " + jaxwsContext.getAddress().getURI().toString()); aoqi@0: } aoqi@0: aoqi@0: DefaultClientTubelineAssemblyContext context = createClientContext(jaxwsContext); aoqi@0: aoqi@0: Collection tubeCreators = tubelineAssemblyController.getTubeCreators(context); aoqi@0: aoqi@0: for (TubeCreator tubeCreator : tubeCreators) { aoqi@0: tubeCreator.updateContext(context); aoqi@0: } aoqi@0: aoqi@0: TubelineAssemblyDecorator decorator = TubelineAssemblyDecorator.composite( aoqi@0: ServiceFinder.find(TubelineAssemblyDecorator.class, context.getContainer())); aoqi@0: aoqi@0: boolean first = true; aoqi@0: for (TubeCreator tubeCreator : tubeCreators) { aoqi@0: final MessageDumpingInfo msgDumpInfo = setupMessageDumping(tubeCreator.getMessageDumpPropertyBase(), Side.Client); aoqi@0: aoqi@0: final Tube oldTubelineHead = context.getTubelineHead(); aoqi@0: LoggingDumpTube afterDumpTube = null; aoqi@0: if (msgDumpInfo.dumpAfter) { aoqi@0: afterDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.After, context.getTubelineHead()); aoqi@0: context.setTubelineHead(afterDumpTube); aoqi@0: } aoqi@0: aoqi@0: if (!context.setTubelineHead(decorator.decorateClient(tubeCreator.createTube(context), context))) { // no new tube has been created aoqi@0: if (afterDumpTube != null) { aoqi@0: context.setTubelineHead(oldTubelineHead); // removing possible "after" message dumping tube aoqi@0: } aoqi@0: } else { aoqi@0: final String loggedTubeName = context.getTubelineHead().getClass().getName(); aoqi@0: if (afterDumpTube != null) { aoqi@0: afterDumpTube.setLoggedTubeName(loggedTubeName); aoqi@0: } aoqi@0: aoqi@0: if (msgDumpInfo.dumpBefore) { aoqi@0: final LoggingDumpTube beforeDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.Before, context.getTubelineHead()); aoqi@0: beforeDumpTube.setLoggedTubeName(loggedTubeName); aoqi@0: context.setTubelineHead(beforeDumpTube); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (first) { aoqi@0: context.setTubelineHead(decorator.decorateClientTail(context.getTubelineHead(), context)); aoqi@0: first = false; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return decorator.decorateClientHead(context.getTubelineHead(), context); aoqi@0: } aoqi@0: aoqi@0: @NotNull aoqi@0: public Tube createServer(@NotNull ServerTubeAssemblerContext jaxwsContext) { aoqi@0: if (LOGGER.isLoggable(Level.FINER)) { aoqi@0: LOGGER.finer("Assembling endpoint tubeline for WS endpoint: " + jaxwsContext.getEndpoint().getServiceName() + "::" + jaxwsContext.getEndpoint().getPortName()); aoqi@0: } aoqi@0: aoqi@0: DefaultServerTubelineAssemblyContext context = createServerContext(jaxwsContext); aoqi@0: aoqi@0: // FIXME endpoint URI for provider case aoqi@0: Collection tubeCreators = tubelineAssemblyController.getTubeCreators(context); aoqi@0: for (TubeCreator tubeCreator : tubeCreators) { aoqi@0: tubeCreator.updateContext(context); aoqi@0: } aoqi@0: aoqi@0: TubelineAssemblyDecorator decorator = TubelineAssemblyDecorator.composite( aoqi@0: ServiceFinder.find(TubelineAssemblyDecorator.class, context.getEndpoint().getContainer())); aoqi@0: aoqi@0: boolean first = true; aoqi@0: for (TubeCreator tubeCreator : tubeCreators) { aoqi@0: final MessageDumpingInfo msgDumpInfo = setupMessageDumping(tubeCreator.getMessageDumpPropertyBase(), Side.Endpoint); aoqi@0: aoqi@0: final Tube oldTubelineHead = context.getTubelineHead(); aoqi@0: LoggingDumpTube afterDumpTube = null; aoqi@0: if (msgDumpInfo.dumpAfter) { aoqi@0: afterDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.After, context.getTubelineHead()); aoqi@0: context.setTubelineHead(afterDumpTube); aoqi@0: } aoqi@0: aoqi@0: if (!context.setTubelineHead(decorator.decorateServer(tubeCreator.createTube(context), context))) { // no new tube has been created aoqi@0: if (afterDumpTube != null) { aoqi@0: context.setTubelineHead(oldTubelineHead); // removing possible "after" message dumping tube aoqi@0: } aoqi@0: } else { aoqi@0: final String loggedTubeName = context.getTubelineHead().getClass().getName(); aoqi@0: if (afterDumpTube != null) { aoqi@0: afterDumpTube.setLoggedTubeName(loggedTubeName); aoqi@0: } aoqi@0: aoqi@0: if (msgDumpInfo.dumpBefore) { aoqi@0: final LoggingDumpTube beforeDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.Before, context.getTubelineHead()); aoqi@0: beforeDumpTube.setLoggedTubeName(loggedTubeName); aoqi@0: context.setTubelineHead(beforeDumpTube); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (first) { aoqi@0: context.setTubelineHead(decorator.decorateServerTail(context.getTubelineHead(), context)); aoqi@0: first = false; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return decorator.decorateServerHead(context.getTubelineHead(), context); aoqi@0: } aoqi@0: aoqi@0: private MessageDumpingInfo setupMessageDumping(String msgDumpSystemPropertyBase, Side side) { aoqi@0: boolean dumpBefore = false; aoqi@0: boolean dumpAfter = false; aoqi@0: Level logLevel = Level.INFO; aoqi@0: aoqi@0: // checking common properties aoqi@0: Boolean value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE); aoqi@0: if (value != null) { aoqi@0: dumpBefore = value.booleanValue(); aoqi@0: dumpAfter = value.booleanValue(); aoqi@0: } aoqi@0: aoqi@0: value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".before"); aoqi@0: dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; aoqi@0: aoqi@0: value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".after"); aoqi@0: dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; aoqi@0: aoqi@0: Level levelValue = getLevelValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".level"); aoqi@0: if (levelValue != null) { aoqi@0: logLevel = levelValue; aoqi@0: } aoqi@0: aoqi@0: // narrowing to proper communication side on common properties aoqi@0: value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString()); aoqi@0: if (value != null) { aoqi@0: dumpBefore = value.booleanValue(); aoqi@0: dumpAfter = value.booleanValue(); aoqi@0: } aoqi@0: aoqi@0: value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".before"); aoqi@0: dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; aoqi@0: aoqi@0: value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".after"); aoqi@0: dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; aoqi@0: aoqi@0: levelValue = getLevelValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".level"); aoqi@0: if (levelValue != null) { aoqi@0: logLevel = levelValue; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: // checking general tube-specific properties aoqi@0: value = getBooleanValue(msgDumpSystemPropertyBase); aoqi@0: if (value != null) { aoqi@0: dumpBefore = value.booleanValue(); aoqi@0: dumpAfter = value.booleanValue(); aoqi@0: } aoqi@0: aoqi@0: value = getBooleanValue(msgDumpSystemPropertyBase + ".before"); aoqi@0: dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; aoqi@0: aoqi@0: value = getBooleanValue(msgDumpSystemPropertyBase + ".after"); aoqi@0: dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; aoqi@0: aoqi@0: levelValue = getLevelValue(msgDumpSystemPropertyBase + ".level"); aoqi@0: if (levelValue != null) { aoqi@0: logLevel = levelValue; aoqi@0: } aoqi@0: aoqi@0: // narrowing to proper communication side on tube-specific properties aoqi@0: msgDumpSystemPropertyBase += "." + side.toString(); aoqi@0: aoqi@0: value = getBooleanValue(msgDumpSystemPropertyBase); aoqi@0: if (value != null) { aoqi@0: dumpBefore = value.booleanValue(); aoqi@0: dumpAfter = value.booleanValue(); aoqi@0: } aoqi@0: aoqi@0: value = getBooleanValue(msgDumpSystemPropertyBase + ".before"); aoqi@0: dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; aoqi@0: aoqi@0: value = getBooleanValue(msgDumpSystemPropertyBase + ".after"); aoqi@0: dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; aoqi@0: aoqi@0: levelValue = getLevelValue(msgDumpSystemPropertyBase + ".level"); aoqi@0: if (levelValue != null) { aoqi@0: logLevel = levelValue; aoqi@0: } aoqi@0: aoqi@0: return new MessageDumpingInfo(dumpBefore, dumpAfter, logLevel); aoqi@0: } aoqi@0: aoqi@0: private Boolean getBooleanValue(String propertyName) { aoqi@0: Boolean retVal = null; aoqi@0: aoqi@0: String stringValue = System.getProperty(propertyName); aoqi@0: if (stringValue != null) { aoqi@0: retVal = Boolean.valueOf(stringValue); aoqi@0: LOGGER.fine(TubelineassemblyMessages.MASM_0018_MSG_LOGGING_SYSTEM_PROPERTY_SET_TO_VALUE(propertyName, retVal)); aoqi@0: } aoqi@0: aoqi@0: return retVal; aoqi@0: } aoqi@0: aoqi@0: private Level getLevelValue(String propertyName) { aoqi@0: Level retVal = null; aoqi@0: aoqi@0: String stringValue = System.getProperty(propertyName); aoqi@0: if (stringValue != null) { aoqi@0: // if value is not null => property is set, we will try to override the default logging level aoqi@0: LOGGER.fine(TubelineassemblyMessages.MASM_0018_MSG_LOGGING_SYSTEM_PROPERTY_SET_TO_VALUE(propertyName, stringValue)); aoqi@0: try { aoqi@0: retVal = Level.parse(stringValue); aoqi@0: } catch (IllegalArgumentException ex) { aoqi@0: LOGGER.warning(TubelineassemblyMessages.MASM_0019_MSG_LOGGING_SYSTEM_PROPERTY_ILLEGAL_VALUE(propertyName, stringValue), ex); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return retVal; aoqi@0: } aoqi@0: aoqi@0: // Extension point to change Tubeline Assembly behaviour: override if necessary ... aoqi@0: protected DefaultServerTubelineAssemblyContext createServerContext(ServerTubeAssemblerContext jaxwsContext) { aoqi@0: return new DefaultServerTubelineAssemblyContext(jaxwsContext); aoqi@0: } aoqi@0: aoqi@0: // Extension point to change Tubeline Assembly behaviour: override if necessary ... aoqi@0: protected DefaultClientTubelineAssemblyContext createClientContext(ClientTubeAssemblerContext jaxwsContext) { aoqi@0: return new DefaultClientTubelineAssemblyContext(jaxwsContext); aoqi@0: } aoqi@0: aoqi@0: }