Package com.sun.jdmk.internal

Source Code of com.sun.jdmk.internal.ReconnectMBeanServerConnectionFactory

/*
* @(#)file      ReconnectMBeanServerConnectionFactory.java
* @(#)author    Sun Microsystems, Inc.
* @(#)version   1.13
* @(#)lastedit  07/03/08
* @(#)build     @BUILD_TAG_PLACEHOLDER@
*
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007 Sun Microsystems, Inc. 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 http://opendmk.dev.java.net/legal_notices/licenses.txt or in the
* LEGAL_NOTICES folder that accompanied this code. 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 found at
*     http://opendmk.dev.java.net/legal_notices/licenses.txt
* or in the LEGAL_NOTICES folder that accompanied this code.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.
*
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
*
*       "Portions Copyrighted [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 or 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.jdmk.internal;

import java.io.IOException;
import java.io.Serializable;

import java.util.Map;

import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectionNotification;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanServerConnection;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.Notification;
import javax.management.MBeanServer;

import javax.security.auth.Subject;

import javax.management.remote.JMXServiceURL;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;

import com.sun.jdmk.remote.cascading.BasicMBeanServerConnectionFactory;
import com.sun.jdmk.remote.cascading.MBeanServerConnectionFactory;

/**
* A basic {@link MBeanServerConnectionFactory} that wraps a
* {@link JMXConnector}.
* This implementation does support transparent reconnection for JMXConnector
* created with a deterministic JMXService URL.
* The reconnection is bound by an envelop time. Reconnection occurs after
* a period of time. Both values are expressed in milliseconds and are provided
* at construction time. If envelopTime == 0, no reconnection is done.
**/
public class ReconnectMBeanServerConnectionFactory
    extends BasicMBeanServerConnectionFactory implements Runnable,
               Serializable {
    private static final long serialVersionUID = -5764359043690071419L;
   
    private long envelopTime;
    private long period;
    private boolean stop = false;
    private transient boolean failed = false;

    private final NotificationBroadcasterSupport broadcaster =
  new NotificationBroadcasterSupport();

    private JMXServiceURL url;
    private Map map;
   
    private String currentConnectionId;
    private transient JMXConnector connector = null;
    private transient MBeanServerConnection connection = null;
    private final NotificationListener listener;

    /**
     * Creates a new <tt>ReconnectMBeanServerConnectionFactory</tt> for
     * the given {@link JMXServiceURL url.}
     * @param url Used to create JMXConnector.
     * @param map Used to create JMXConnector.
     * @param envelopTime Reconnect time limit. If envelopTime == 0,
     * no reconnection is done.
     *
     * @throws IOException If connection fails.
     */
    public ReconnectMBeanServerConnectionFactory(JMXServiceURL url,
             Map map,
             long envelopTime,
             long period)
  throws IOException {
  super(null, null);
  this.url = url;
  this.map = map;
  this.envelopTime = envelopTime;
  this.period = period;
  this.listener =
      new NotificationListener() {
        public void handleNotification(Notification n,
               Object handback) {
      handleConnectionNotification(n,handback);
        }
    };
  if(getJMXConnector() == null)
      if(envelopTime == 0)
    throw new IOException("Unable to connect to " + url);
      else
    reconnect();
  else {
      currentConnectionId = getConnectionId();
  }
    }
   
    /*
     * Return the url used to create and connector the JMXConnector.
     * @return the url.
     */
    public JMXServiceURL getURL() {
  return url;
    }

    private static JMXConnector makeConnector(JMXServiceURL url,
                Map map
  throws IOException {
  JMXConnector c = null;
  try {
      c = JMXConnectorFactory.connect(url, map);
  }catch(IOException e) {
      //
  }
  return c;
    }
   
    /**
     * Call this method to stop the ongoing reconnection (if any).
     * In case reconnection is ongoing, "jmx.remote.connection.failed"
     * notification is sent.
     */
    public synchronized void stopReconnection() {
  stop = true;
    }

    public void run() {
  long startTime = System.currentTimeMillis();
  long currentTime;
  JMXConnector old = getJMXConnector();
  String connectionId = null;
  do{
      try {
    JMXConnector c = makeConnector(url, map);

    if(c == null) throw new Exception("Not connected");

    c.addConnectionNotificationListener(listener,
                null,
                null);
    synchronized (this) {
        connector=c;
        connection = null;
    }

    connectionId = c.getConnectionId();
    JMXConnectionNotification notif =
        new JMXConnectionNotification("jmx.remote.connection.open",
              "",
              connectionId,
              0,
              "",
              "");
    broadcaster.sendNotification(notif);
    return;
      }catch(Exception e) {
    //e.printStackTrace();
    try {
        Thread.sleep(period);
    }catch(Exception ex) {}
      }
      currentTime =  System.currentTimeMillis();
  }while(((currentTime - startTime) < envelopTime) && !stop);
 
  if(!stop) {
      if(currentConnectionId == null)
    currentConnectionId = "NeverConnectedConnection";
     
      JMXConnectionNotification notif =
    new JMXConnectionNotification("jmx.remote.connection.failed",
                "",
                currentConnectionId,
                0,
                "",
                "");
      broadcaster.sendNotification(notif);
      try {
    currentConnectionId = getConnectionId();
      }catch(Exception e) {
    currentConnectionId = null;
      }
  }
    }
   
    private void reconnect() {
  //Launch reconnection
  if(envelopTime > 0) {
      Thread thread = new Thread(this);
      thread.start();
 
    }

    public void handleConnectionNotification(Notification notification,
               java.lang.Object handback) {
  if(notification.getType().equals("jmx.remote.connection.failed")) {
      //if(notification.getMessage().startsWith("Failed to communicate with the server: java.rmi.UnmarshalException: error unmarshalling return; nested exception is:")) {
      //System.out.println("WORKAROUND, DO NOTHING");
      //return;
      //}

      //Remove from failed connector
      try {
    getJMXConnector().
        removeConnectionNotificationListener(listener);
      }catch(Exception e) {
    //We should have it all the time.
    //Don't now if we are automaticaly removed on failed?
      }
      reconnect();
  } else
      broadcaster.sendNotification(notification);
    }
   
    // MBeanServerConnectionFactory
    //
    public void
  addConnectionNotificationListener(NotificationListener l,
            NotificationFilter filter,
            Object handback) {
  broadcaster.addNotificationListener(l,
              filter,
              handback);
    }

    // MBeanServerConnectionFactory
    //
    public void
  removeConnectionNotificationListener(NotificationListener l)
  throws ListenerNotFoundException {
  broadcaster.removeNotificationListener(l);
    }

    // MBeanServerConnectionFactory
    //
    public void removeConnectionNotificationListener(NotificationListener l,
                 NotificationFilter f,
                 Object handback)
  throws ListenerNotFoundException {
  broadcaster.removeNotificationListener(l,f,handback);
    }
   
    /**
     * Creates a new <tt>ReconnectMBeanServerConnectionFactory</tt> for
     * the given {@link JMXServiceURL url.}
     * @param url Used to create JMXConnector.
     * @param map Used to create JMXConnector.
     * @param envelopTime Reconnect time limit. If envelopTime == 0 no
     * reconnection is done.
     *
     * @throws IOException If connection fails.
     */
    public static MBeanServerConnectionFactory newInstance(JMXServiceURL url,
                 Map map,
                 long envelopTime,
                 long period)
  throws IOException {
  return new ReconnectMBeanServerConnectionFactory(url,
               map,
               envelopTime,
               period);
    }

    public synchronized JMXConnector getJMXConnector() {
  try {
      if (connector == null) {
    connector = makeConnector(url, map);
    connector.addConnectionNotificationListener(listener,null,
                  connector);
    connection = null;
      }
  } catch (IOException io) {
      // OK. return old one if any.
  }
  return connector;
    }

    public synchronized MBeanServerConnection getMBeanServerConnection()
  throws IOException {
  if (failed) throw new IOException("connection already failed");
  if (getJMXConnector()==null)
      throw new IOException("Unable to connect");
  if (connection == null)
      connection = getJMXConnector().
    getMBeanServerConnection(getDelegationSubject());
  return this.connection;
    }

}
TOP

Related Classes of com.sun.jdmk.internal.ReconnectMBeanServerConnectionFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.