/*
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.xml.internal.ws.assembler;

import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.logging.Logger;
import com.sun.xml.internal.ws.api.BindingID;
import com.sun.xml.internal.ws.api.pipe.ClientTubeAssemblerContext;
import com.sun.xml.internal.ws.api.pipe.ServerTubeAssemblerContext;
import com.sun.xml.internal.ws.api.pipe.Tube;
import com.sun.xml.internal.ws.api.pipe.TubelineAssembler;
import com.sun.xml.internal.ws.assembler.dev.TubelineAssemblyDecorator;
import com.sun.xml.internal.ws.dump.LoggingDumpTube;
import com.sun.xml.internal.ws.resources.TubelineassemblyMessages;
import com.sun.xml.internal.ws.util.ServiceFinder;

import java.util.Collection;
import java.util.logging.Level;

TODO: Write some description here ...
Author:Miroslav Kos (miroslav.kos at oracle.com)
/** * TODO: Write some description here ... * * @author Miroslav Kos (miroslav.kos at oracle.com) */
public class MetroTubelineAssembler implements TubelineAssembler { private static final String COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE = "com.sun.metro.soap.dump"; public static final MetroConfigNameImpl JAXWS_TUBES_CONFIG_NAMES = new MetroConfigNameImpl("jaxws-tubes-default.xml", "jaxws-tubes.xml"); private static enum Side { Client("client"), Endpoint("endpoint"); private final String name; private Side(String name) { this.name = name; } @Override public String toString() { return name; } } private static class MessageDumpingInfo { final boolean dumpBefore; final boolean dumpAfter; final Level logLevel; MessageDumpingInfo(boolean dumpBefore, boolean dumpAfter, Level logLevel) { this.dumpBefore = dumpBefore; this.dumpAfter = dumpAfter; this.logLevel = logLevel; } } private static final Logger LOGGER = Logger.getLogger(MetroTubelineAssembler.class); private final BindingID bindingId; private final TubelineAssemblyController tubelineAssemblyController; public MetroTubelineAssembler(final BindingID bindingId, MetroConfigName metroConfigName) { this.bindingId = bindingId; this.tubelineAssemblyController = new TubelineAssemblyController(metroConfigName); } TubelineAssemblyController getTubelineAssemblyController() { return tubelineAssemblyController; } @NotNull public Tube createClient(@NotNull ClientTubeAssemblerContext jaxwsContext) { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("Assembling client-side tubeline for WS endpoint: " + jaxwsContext.getAddress().getURI().toString()); } DefaultClientTubelineAssemblyContext context = createClientContext(jaxwsContext); Collection<TubeCreator> tubeCreators = tubelineAssemblyController.getTubeCreators(context); for (TubeCreator tubeCreator : tubeCreators) { tubeCreator.updateContext(context); } TubelineAssemblyDecorator decorator = TubelineAssemblyDecorator.composite( ServiceFinder.find(TubelineAssemblyDecorator.class, context.getContainer())); boolean first = true; for (TubeCreator tubeCreator : tubeCreators) { final MessageDumpingInfo msgDumpInfo = setupMessageDumping(tubeCreator.getMessageDumpPropertyBase(), Side.Client); final Tube oldTubelineHead = context.getTubelineHead(); LoggingDumpTube afterDumpTube = null; if (msgDumpInfo.dumpAfter) { afterDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.After, context.getTubelineHead()); context.setTubelineHead(afterDumpTube); } if (!context.setTubelineHead(decorator.decorateClient(tubeCreator.createTube(context), context))) { // no new tube has been created if (afterDumpTube != null) { context.setTubelineHead(oldTubelineHead); // removing possible "after" message dumping tube } } else { final String loggedTubeName = context.getTubelineHead().getClass().getName(); if (afterDumpTube != null) { afterDumpTube.setLoggedTubeName(loggedTubeName); } if (msgDumpInfo.dumpBefore) { final LoggingDumpTube beforeDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.Before, context.getTubelineHead()); beforeDumpTube.setLoggedTubeName(loggedTubeName); context.setTubelineHead(beforeDumpTube); } } if (first) { context.setTubelineHead(decorator.decorateClientTail(context.getTubelineHead(), context)); first = false; } } return decorator.decorateClientHead(context.getTubelineHead(), context); } @NotNull public Tube createServer(@NotNull ServerTubeAssemblerContext jaxwsContext) { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("Assembling endpoint tubeline for WS endpoint: " + jaxwsContext.getEndpoint().getServiceName() + "::" + jaxwsContext.getEndpoint().getPortName()); } DefaultServerTubelineAssemblyContext context = createServerContext(jaxwsContext); // FIXME endpoint URI for provider case Collection<TubeCreator> tubeCreators = tubelineAssemblyController.getTubeCreators(context); for (TubeCreator tubeCreator : tubeCreators) { tubeCreator.updateContext(context); } TubelineAssemblyDecorator decorator = TubelineAssemblyDecorator.composite( ServiceFinder.find(TubelineAssemblyDecorator.class, context.getEndpoint().getContainer())); boolean first = true; for (TubeCreator tubeCreator : tubeCreators) { final MessageDumpingInfo msgDumpInfo = setupMessageDumping(tubeCreator.getMessageDumpPropertyBase(), Side.Endpoint); final Tube oldTubelineHead = context.getTubelineHead(); LoggingDumpTube afterDumpTube = null; if (msgDumpInfo.dumpAfter) { afterDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.After, context.getTubelineHead()); context.setTubelineHead(afterDumpTube); } if (!context.setTubelineHead(decorator.decorateServer(tubeCreator.createTube(context), context))) { // no new tube has been created if (afterDumpTube != null) { context.setTubelineHead(oldTubelineHead); // removing possible "after" message dumping tube } } else { final String loggedTubeName = context.getTubelineHead().getClass().getName(); if (afterDumpTube != null) { afterDumpTube.setLoggedTubeName(loggedTubeName); } if (msgDumpInfo.dumpBefore) { final LoggingDumpTube beforeDumpTube = new LoggingDumpTube(msgDumpInfo.logLevel, LoggingDumpTube.Position.Before, context.getTubelineHead()); beforeDumpTube.setLoggedTubeName(loggedTubeName); context.setTubelineHead(beforeDumpTube); } } if (first) { context.setTubelineHead(decorator.decorateServerTail(context.getTubelineHead(), context)); first = false; } } return decorator.decorateServerHead(context.getTubelineHead(), context); } private MessageDumpingInfo setupMessageDumping(String msgDumpSystemPropertyBase, Side side) { boolean dumpBefore = false; boolean dumpAfter = false; Level logLevel = Level.INFO; // checking common properties Boolean value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE); if (value != null) { dumpBefore = value.booleanValue(); dumpAfter = value.booleanValue(); } value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".before"); dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".after"); dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; Level levelValue = getLevelValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + ".level"); if (levelValue != null) { logLevel = levelValue; } // narrowing to proper communication side on common properties value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString()); if (value != null) { dumpBefore = value.booleanValue(); dumpAfter = value.booleanValue(); } value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".before"); dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; value = getBooleanValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".after"); dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; levelValue = getLevelValue(COMMON_MESSAGE_DUMP_SYSTEM_PROPERTY_BASE + "." + side.toString() + ".level"); if (levelValue != null) { logLevel = levelValue; } // checking general tube-specific properties value = getBooleanValue(msgDumpSystemPropertyBase); if (value != null) { dumpBefore = value.booleanValue(); dumpAfter = value.booleanValue(); } value = getBooleanValue(msgDumpSystemPropertyBase + ".before"); dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; value = getBooleanValue(msgDumpSystemPropertyBase + ".after"); dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; levelValue = getLevelValue(msgDumpSystemPropertyBase + ".level"); if (levelValue != null) { logLevel = levelValue; } // narrowing to proper communication side on tube-specific properties msgDumpSystemPropertyBase += "." + side.toString(); value = getBooleanValue(msgDumpSystemPropertyBase); if (value != null) { dumpBefore = value.booleanValue(); dumpAfter = value.booleanValue(); } value = getBooleanValue(msgDumpSystemPropertyBase + ".before"); dumpBefore = (value != null) ? value.booleanValue() : dumpBefore; value = getBooleanValue(msgDumpSystemPropertyBase + ".after"); dumpAfter = (value != null) ? value.booleanValue() : dumpAfter; levelValue = getLevelValue(msgDumpSystemPropertyBase + ".level"); if (levelValue != null) { logLevel = levelValue; } return new MessageDumpingInfo(dumpBefore, dumpAfter, logLevel); } private Boolean getBooleanValue(String propertyName) { Boolean retVal = null; String stringValue = System.getProperty(propertyName); if (stringValue != null) { retVal = Boolean.valueOf(stringValue); LOGGER.fine(TubelineassemblyMessages.MASM_0018_MSG_LOGGING_SYSTEM_PROPERTY_SET_TO_VALUE(propertyName, retVal)); } return retVal; } private Level getLevelValue(String propertyName) { Level retVal = null; String stringValue = System.getProperty(propertyName); if (stringValue != null) { // if value is not null => property is set, we will try to override the default logging level LOGGER.fine(TubelineassemblyMessages.MASM_0018_MSG_LOGGING_SYSTEM_PROPERTY_SET_TO_VALUE(propertyName, stringValue)); try { retVal = Level.parse(stringValue); } catch (IllegalArgumentException ex) { LOGGER.warning(TubelineassemblyMessages.MASM_0019_MSG_LOGGING_SYSTEM_PROPERTY_ILLEGAL_VALUE(propertyName, stringValue), ex); } } return retVal; } // Extension point to change Tubeline Assembly behaviour: override if necessary ... protected DefaultServerTubelineAssemblyContext createServerContext(ServerTubeAssemblerContext jaxwsContext) { return new DefaultServerTubelineAssemblyContext(jaxwsContext); } // Extension point to change Tubeline Assembly behaviour: override if necessary ... protected DefaultClientTubelineAssemblyContext createClientContext(ClientTubeAssemblerContext jaxwsContext) { return new DefaultClientTubelineAssemblyContext(jaxwsContext); } }