All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.xml.ws.config.management.persistence.JdbcConfigReader Maven / Gradle / Ivy

There is a newer version: 4.0.4
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.xml.ws.config.management.persistence;

import com.sun.istack.logging.Logger;
import com.sun.xml.ws.metro.api.config.management.ConfigReader;
import com.sun.xml.ws.api.config.management.EndpointCreationAttributes;
import com.sun.xml.ws.metro.api.config.management.EndpointStarter;
import com.sun.xml.ws.metro.api.config.management.NamedParameters;
import com.sun.xml.ws.metro.api.config.management.ManagedEndpoint;
import com.sun.xml.ws.api.config.management.policy.ManagedServiceAssertion;
import com.sun.xml.ws.api.config.management.policy.ManagedServiceAssertion.ImplementationRecord;
import com.sun.xml.ws.commons.DelayedTaskManager;
import com.sun.xml.ws.commons.DelayedTaskManager.DelayedTask;
import com.sun.xml.ws.config.management.ManagementConstants;
import com.sun.xml.ws.config.management.ManagementMessages;
import com.sun.xml.ws.config.management.ManagementUtil;
import com.sun.xml.ws.config.management.ManagementUtil.JdbcTableNames;
import com.sun.xml.ws.config.management.server.ReDelegate;
import com.sun.xml.ws.policy.PolicyConstants;

import java.io.Reader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import javax.sql.DataSource;
import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceException;

/**
 * This implementation polls a JDBC data sources for changes and if it finds a new
 * configuration, it reconfigures the managed endpoint.
 *
 * This implementation starts the endpoint immediately unless the ManagedService
 * start attribute was set to "notify". Otherwise it will start the endpoint
 * only when it finds new configuration data.
 *
 * @param  The endpoint implementation class type.
 * @author Fabian Ritzmann
 */
public class JdbcConfigReader implements ConfigReader {

    private static final Logger LOGGER = Logger.getLogger(JdbcConfigReader.class);
    private static final QName POLLING_INTERVAL_PARAMETER_NAME =
            new QName(PolicyConstants.SUN_MANAGEMENT_NAMESPACE, "PollingInterval");
    private static final long DEFAULT_POLLING_INTERVAL = 10000L;

    private ManagedEndpoint endpoint;
    private ManagedServiceAssertion assertion;
    private EndpointCreationAttributes creationAttributes;
    private ClassLoader endpointClassLoader;
    private EndpointStarter endpointStarter;
    private long pollingInterval;

    private volatile ConfigPoller poller = null;


    public synchronized void init(ManagedEndpoint endpoint, ManagedServiceAssertion assertion,
            EndpointCreationAttributes attributes, ClassLoader classLoader, EndpointStarter starter) {
        this.endpoint = endpoint;
        this.assertion = assertion;
        this.creationAttributes = attributes;
        this.endpointClassLoader = classLoader;
        this.endpointStarter = starter;

        this.pollingInterval = DEFAULT_POLLING_INTERVAL;
        final ImplementationRecord record = assertion.getConfigReaderImplementation();
        if (record != null) {
            final String className = record.getImplementation();
            if (className == null || className.equals(JdbcConfigReader.class.getName())) {
                String pollingIntervalText = null;
                try {
                    final Map classParameters = record.getParameters();
                    pollingIntervalText = classParameters.get(POLLING_INTERVAL_PARAMETER_NAME);
                    if (pollingIntervalText != null) {
                        this.pollingInterval = Long.parseLong(pollingIntervalText);
                    }
                } catch (NumberFormatException e) {
                    throw LOGGER.logSevereException(new WebServiceException(
                            ManagementMessages.WSM_5039_FAILED_NUMBER_CONVERSION(
                            POLLING_INTERVAL_PARAMETER_NAME, pollingIntervalText), e));
                }
            }
        }
    }

    public synchronized void start(NamedParameters parameters) throws IllegalStateException {
        if (this.poller != null && !this.poller.isStopped()) {
            throw LOGGER.logSevereException(new IllegalStateException(
                    ManagementMessages.WSM_5087_FAILED_POLLER_START()));
        }
        this.poller = new ConfigPoller(this.endpoint, this.assertion, this.creationAttributes,
                this.endpointClassLoader, this.endpointStarter, this.pollingInterval);
        this.poller.start();
    }

    public synchronized void stop() throws IllegalStateException {
        if (poller == null) {
            throw LOGGER.logSevereException(new IllegalStateException(
                    ManagementMessages.WSM_5033_POLLER_STOP_FAILED(getClass().getName())));
        }
        poller.stop();
    }


    /**
     * This implementation polls the database for a new version of the configuration
     * data. It reconfigures the endpoint as soon as it finds a new version.
     *
     * This implementation starts the endpoint immediately unless the ManagedService
     * start attribute was set to "notify". Otherwise it will start the endpoint
     * only when it finds new configuration data.
     *
     * @param  The endpoint implementation class type.
     */
    private static class ConfigPoller implements DelayedTask {

        private static final String START_ATTRIBUTE_NOTIFY_VALUE_NAME = "notify";
        private static final String POLLER_NAME = "Configuration management JDBC poller";

        private final ManagedEndpoint endpoint;
        private final EndpointCreationAttributes creationAttributes;
        private final ClassLoader classLoader;
        private final EndpointStarter endpointStarter;
        private final ManagedServiceAssertion managedService;
        private final long executionDelay;
        private final DelayedTaskManager taskManager =
                DelayedTaskManager.createSingleThreadedManager("config-management-jdbc-poller");

        private volatile boolean stopped;
        private volatile long version = 0L;

        public ConfigPoller(final ManagedEndpoint endpoint, final ManagedServiceAssertion assertion,
                final EndpointCreationAttributes attributes, final ClassLoader classLoader,
                final EndpointStarter starter, final long executionDelay) {
            this.endpoint = endpoint;
            this.creationAttributes = attributes;
            this.classLoader = classLoader;
            this.endpointStarter = starter;

            this.managedService = assertion;

            this.executionDelay = executionDelay;
            this.stopped = true;

            final String start = this.managedService.getStart();
            if (start == null || !start.equals(START_ATTRIBUTE_NOTIFY_VALUE_NAME)) {
                if (LOGGER.isLoggable(Level.CONFIG)) {
                    LOGGER.config(ManagementMessages.WSM_5035_START_ENDPOINT_IMMEDIATELY(start));
                }
                this.endpointStarter.startEndpoint();
            }
            else {
                if (LOGGER.isLoggable(Level.CONFIG)) {
                    LOGGER.config(ManagementMessages.WSM_5036_WAIT_ENDPOINT_START(start));
                }
            }
            
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine(ManagementMessages.WSM_5040_CREATED_POLLER(executionDelay));
            }
        }

        public String getName() {
            return POLLER_NAME;
        }

        public void run(final DelayedTaskManager manager) {
            if (stopped) {
                return;
            }

            Connection connection = null;
            DataSource source = null;
            try {
                final ImplementationRecord record = this.managedService.getConfigReaderImplementation();
                final JdbcTableNames tableNames = ManagementUtil.getJdbcTableNames(record,
                        JdbcConfigReader.class.getName());
                source = ManagementUtil.getJdbcDataSource(record,
                        JdbcConfigReader.class.getName());
                connection = source.getConnection();
                pollData(connection, tableNames, endpoint.getId());
                connection.close();
            } catch (SQLException e) {
                LOGGER.warning(ManagementMessages.WSM_5021_NO_DB_CONNECT(source), e);
            } catch (Throwable e) {
                LOGGER.severe(ManagementMessages.WSM_5037_FAILED_RECONFIGURE(), e);
            } finally {
                try {
                    if (connection != null) {
                        connection.close();
                    }
                } catch (SQLException e) {
                    LOGGER.warning(ManagementMessages.WSM_5022_NO_DB_CLOSE(connection), e);
                }

                if (!stopped) {
                    // schedule next run
                    this.taskManager.register(this, executionDelay, TimeUnit.MILLISECONDS);
                }
            }
        }

        synchronized void start() {
            LOGGER.entering();
            try {
                if (stopped) {
                    stopped = false;
                    this.taskManager.register(this, 0, TimeUnit.MILLISECONDS);
                } else {
                    LOGGER.warning(ManagementMessages.WSM_5034_DUPLICATE_START(getName()));
                }
            } finally {
                LOGGER.exiting();
            }
        }

        synchronized void stop() {
            LOGGER.entering();
            try {
                stopped = true;
            } finally {
                LOGGER.exiting();
            }
        }

        synchronized boolean isStopped() {
            return this.stopped;
        }

        private void pollData(final Connection connection, final JdbcTableNames tableNames, final String endpointId) {
            Statement statement = null;
            try {
                final String query = "SELECT " + tableNames.getVersionName() + ", " +
                        tableNames.getConfigName() + " FROM " + tableNames.getTableName() +
                        " WHERE " + tableNames.getIdName() + " = '" + endpointId + "' AND " +
                        tableNames.getVersionName() + " > " + this.version;
                if (LOGGER.isLoggable(Level.FINER)) {
                    LOGGER.finer(ManagementMessages.WSM_5023_EXECUTE_SQL(query));
                }
                statement = connection.createStatement();
                final ResultSet result = statement.executeQuery(query);
                if (result.next()) {
                    if (LOGGER.isLoggable(Level.FINE)) {
                        LOGGER.fine(ManagementMessages.WSM_5029_FOUND_UPDATED_CONFIG());
                    }
                    this.version = result.getLong(tableNames.getVersionName());
                    final Reader data = result.getCharacterStream(tableNames.getConfigName());
                    reconfigure(data);
                } else {
                    if (LOGGER.isLoggable(Level.FINEST)) {
                        LOGGER.finer(ManagementMessages.WSM_5030_NO_UPDATED_CONFIG());
                    }
                }
            } catch (SQLException e) {
                throw LOGGER.logSevereException(new WebServiceException(ManagementMessages.WSM_5038_FAILED_CONFIG_READ(), e));
            } finally {
                if (statement != null) {
                    try {
                        statement.close();
                    } catch (SQLException e) {
                        LOGGER.warning(ManagementMessages.WSM_5026_FAILED_STATEMENT_CLOSE(statement), e);
                    }
                }
            }
        }

        private void reconfigure(Reader reader) {
            final NamedParameters parameters = new NamedParameters()
                    .put(ManagedEndpoint.ENDPOINT_INSTANCE_PARAMETER_NAME, this.endpoint)
                    .put(ManagedEndpoint.CREATION_ATTRIBUTES_PARAMETER_NAME, this.creationAttributes)
                    .put(ManagedEndpoint.CLASS_LOADER_PARAMETER_NAME, this.classLoader)
                    .put(ManagementConstants.CONFIGURATION_DATA_PARAMETER_NAME, ManagementUtil.convert(reader));
            ReDelegate.recreate(parameters);
            this.endpointStarter.startEndpoint();
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy