|
From: <ls...@us...> - 2007-09-08 16:47:37
|
Revision: 3472
http://jnode.svn.sourceforge.net/jnode/?rev=3472&view=rev
Author: lsantha
Date: 2007-09-08 09:47:35 -0700 (Sat, 08 Sep 2007)
Log Message:
-----------
openjdk integration
Added Paths:
-----------
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ArrayQueue.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientListenerInfo.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientNotifForwarder.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/NotificationBuffer.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/NotificationBufferFilter.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ProxyInputStream.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ProxyRef.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/RMIExporter.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ServerNotifForwarder.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/Unmarshal.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/package.html
trunk/core/src/openjdk/com/com/sun/jmx/remote/security/
trunk/core/src/openjdk/com/com/sun/jmx/remote/security/FileLoginModule.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/security/JMXSubjectDomainCombiner.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/security/MBeanServerAccessController.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/security/MBeanServerFileAccessController.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/security/NotificationAccessController.java
trunk/core/src/openjdk/com/com/sun/jmx/remote/security/SubjectDelegator.java
trunk/core/src/openjdk/com/com/sun/management/GarbageCollectorMXBean.java
trunk/core/src/openjdk/com/com/sun/management/GcInfo.java
trunk/core/src/openjdk/com/com/sun/management/HotSpotDiagnosticMXBean.java
trunk/core/src/openjdk/com/com/sun/management/OSMBeanFactory.java
trunk/core/src/openjdk/com/com/sun/management/OperatingSystemMXBean.java
trunk/core/src/openjdk/com/com/sun/management/UnixOperatingSystem.java
trunk/core/src/openjdk/com/com/sun/management/UnixOperatingSystemMXBean.java
trunk/core/src/openjdk/com/com/sun/management/mgmt-overview.html
trunk/core/src/openjdk/com/com/sun/management/package.html
trunk/core/src/openjdk/java/java/lang/management/ManagementFactory.java
trunk/core/src/openjdk/java/java/lang/management/MemoryUsage.java
trunk/core/src/openjdk/java/java/lang/management/ThreadInfo.java
trunk/core/src/openjdk/java/java/lang/management/package.html
trunk/core/src/openjdk/javax/javax/management/AndQueryExp.java
trunk/core/src/openjdk/javax/javax/management/Attribute.java
trunk/core/src/openjdk/javax/javax/management/AttributeChangeNotification.java
trunk/core/src/openjdk/javax/javax/management/AttributeChangeNotificationFilter.java
trunk/core/src/openjdk/javax/javax/management/AttributeList.java
trunk/core/src/openjdk/javax/javax/management/AttributeNotFoundException.java
trunk/core/src/openjdk/javax/javax/management/AttributeValueExp.java
trunk/core/src/openjdk/javax/javax/management/BadAttributeValueExpException.java
trunk/core/src/openjdk/javax/javax/management/BadBinaryOpValueExpException.java
trunk/core/src/openjdk/javax/javax/management/BadStringOperationException.java
trunk/core/src/openjdk/javax/javax/management/BetweenQueryExp.java
trunk/core/src/openjdk/javax/javax/management/BinaryOpValueExp.java
trunk/core/src/openjdk/javax/javax/management/BinaryRelQueryExp.java
trunk/core/src/openjdk/javax/javax/management/BooleanValueExp.java
trunk/core/src/openjdk/javax/javax/management/ClassAttributeValueExp.java
trunk/core/src/openjdk/javax/javax/management/DefaultLoaderRepository.java
trunk/core/src/openjdk/javax/javax/management/DescriptorAccess.java
trunk/core/src/openjdk/javax/javax/management/DynamicMBean.java
trunk/core/src/openjdk/javax/javax/management/InQueryExp.java
trunk/core/src/openjdk/javax/javax/management/InstanceAlreadyExistsException.java
trunk/core/src/openjdk/javax/javax/management/InstanceNotFoundException.java
trunk/core/src/openjdk/javax/javax/management/InstanceOfQueryExp.java
trunk/core/src/openjdk/javax/javax/management/IntrospectionException.java
trunk/core/src/openjdk/javax/javax/management/InvalidApplicationException.java
trunk/core/src/openjdk/javax/javax/management/InvalidAttributeValueException.java
trunk/core/src/openjdk/javax/javax/management/JMException.java
trunk/core/src/openjdk/javax/javax/management/JMRuntimeException.java
trunk/core/src/openjdk/javax/javax/management/ListenerNotFoundException.java
trunk/core/src/openjdk/javax/javax/management/MBeanException.java
trunk/core/src/openjdk/javax/javax/management/MBeanPermission.java
trunk/core/src/openjdk/javax/javax/management/MBeanRegistration.java
trunk/core/src/openjdk/javax/javax/management/MBeanRegistrationException.java
trunk/core/src/openjdk/javax/javax/management/MBeanServerBuilder.java
trunk/core/src/openjdk/javax/javax/management/MBeanServerDelegateMBean.java
trunk/core/src/openjdk/javax/javax/management/MBeanServerFactory.java
trunk/core/src/openjdk/javax/javax/management/MBeanServerNotification.java
trunk/core/src/openjdk/javax/javax/management/MBeanServerPermission.java
trunk/core/src/openjdk/javax/javax/management/MBeanTrustPermission.java
trunk/core/src/openjdk/javax/javax/management/MalformedObjectNameException.java
trunk/core/src/openjdk/javax/javax/management/MatchQueryExp.java
trunk/core/src/openjdk/javax/javax/management/NotCompliantMBeanException.java
trunk/core/src/openjdk/javax/javax/management/NotQueryExp.java
trunk/core/src/openjdk/javax/javax/management/Notification.java
trunk/core/src/openjdk/javax/javax/management/NotificationBroadcaster.java
trunk/core/src/openjdk/javax/javax/management/NotificationEmitter.java
trunk/core/src/openjdk/javax/javax/management/NotificationFilter.java
trunk/core/src/openjdk/javax/javax/management/NotificationFilterSupport.java
trunk/core/src/openjdk/javax/javax/management/NotificationListener.java
trunk/core/src/openjdk/javax/javax/management/NumericValueExp.java
trunk/core/src/openjdk/javax/javax/management/ObjectInstance.java
trunk/core/src/openjdk/javax/javax/management/OperationsException.java
trunk/core/src/openjdk/javax/javax/management/OrQueryExp.java
trunk/core/src/openjdk/javax/javax/management/PersistentMBean.java
trunk/core/src/openjdk/javax/javax/management/QualifiedAttributeValueExp.java
trunk/core/src/openjdk/javax/javax/management/Query.java
trunk/core/src/openjdk/javax/javax/management/QueryEval.java
trunk/core/src/openjdk/javax/javax/management/QueryExp.java
trunk/core/src/openjdk/javax/javax/management/ReflectionException.java
trunk/core/src/openjdk/javax/javax/management/RuntimeErrorException.java
trunk/core/src/openjdk/javax/javax/management/RuntimeMBeanException.java
trunk/core/src/openjdk/javax/javax/management/RuntimeOperationsException.java
trunk/core/src/openjdk/javax/javax/management/ServiceNotFoundException.java
trunk/core/src/openjdk/javax/javax/management/StringValueExp.java
trunk/core/src/openjdk/javax/javax/management/build.xml
trunk/core/src/openjdk/javax/javax/management/loading/ClassLoaderRepository.java
trunk/core/src/openjdk/javax/javax/management/loading/DefaultLoaderRepository.java
trunk/core/src/openjdk/javax/javax/management/loading/MLet.java
trunk/core/src/openjdk/javax/javax/management/loading/MLetContent.java
trunk/core/src/openjdk/javax/javax/management/loading/MLetMBean.java
trunk/core/src/openjdk/javax/javax/management/loading/MLetObjectInputStream.java
trunk/core/src/openjdk/javax/javax/management/loading/MLetParser.java
trunk/core/src/openjdk/javax/javax/management/loading/PrivateMLet.java
trunk/core/src/openjdk/javax/javax/management/loading/package.html
trunk/core/src/openjdk/javax/javax/management/modelmbean/
trunk/core/src/openjdk/javax/javax/management/modelmbean/DescriptorSupport.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/InvalidTargetObjectTypeException.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/ModelMBean.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/ModelMBeanAttributeInfo.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/ModelMBeanConstructorInfo.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/ModelMBeanInfo.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/ModelMBeanInfoSupport.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/ModelMBeanNotificationBroadcaster.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/ModelMBeanNotificationInfo.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/ModelMBeanOperationInfo.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/RequiredModelMBean.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/XMLParseException.java
trunk/core/src/openjdk/javax/javax/management/modelmbean/package.html
trunk/core/src/openjdk/javax/javax/management/monitor/
trunk/core/src/openjdk/javax/javax/management/monitor/CounterMonitor.java
trunk/core/src/openjdk/javax/javax/management/monitor/CounterMonitorMBean.java
trunk/core/src/openjdk/javax/javax/management/monitor/GaugeMonitor.java
trunk/core/src/openjdk/javax/javax/management/monitor/GaugeMonitorMBean.java
trunk/core/src/openjdk/javax/javax/management/monitor/Monitor.java
trunk/core/src/openjdk/javax/javax/management/monitor/MonitorMBean.java
trunk/core/src/openjdk/javax/javax/management/monitor/MonitorNotification.java
trunk/core/src/openjdk/javax/javax/management/monitor/MonitorSettingException.java
trunk/core/src/openjdk/javax/javax/management/monitor/StringMonitor.java
trunk/core/src/openjdk/javax/javax/management/monitor/StringMonitorMBean.java
trunk/core/src/openjdk/javax/javax/management/monitor/package.html
trunk/core/src/openjdk/javax/javax/management/openmbean/CompositeData.java
trunk/core/src/openjdk/javax/javax/management/openmbean/CompositeDataSupport.java
trunk/core/src/openjdk/javax/javax/management/openmbean/InvalidKeyException.java
trunk/core/src/openjdk/javax/javax/management/openmbean/InvalidOpenTypeException.java
trunk/core/src/openjdk/javax/javax/management/openmbean/KeyAlreadyExistsException.java
trunk/core/src/openjdk/javax/javax/management/openmbean/OpenDataException.java
trunk/core/src/openjdk/javax/javax/management/openmbean/OpenMBeanConstructorInfo.java
trunk/core/src/openjdk/javax/javax/management/openmbean/OpenMBeanInfo.java
trunk/core/src/openjdk/javax/javax/management/openmbean/OpenMBeanInfoSupport.java
trunk/core/src/openjdk/javax/javax/management/openmbean/OpenMBeanOperationInfo.java
trunk/core/src/openjdk/javax/javax/management/openmbean/TabularData.java
trunk/core/src/openjdk/javax/javax/management/openmbean/TabularDataSupport.java
trunk/core/src/openjdk/javax/javax/management/openmbean/TabularType.java
trunk/core/src/openjdk/javax/javax/management/openmbean/package.html
trunk/core/src/openjdk/javax/javax/management/package.html
trunk/core/src/openjdk/javax/javax/management/relation/
trunk/core/src/openjdk/javax/javax/management/relation/InvalidRelationIdException.java
trunk/core/src/openjdk/javax/javax/management/relation/InvalidRelationServiceException.java
trunk/core/src/openjdk/javax/javax/management/relation/InvalidRelationTypeException.java
trunk/core/src/openjdk/javax/javax/management/relation/InvalidRoleInfoException.java
trunk/core/src/openjdk/javax/javax/management/relation/InvalidRoleValueException.java
trunk/core/src/openjdk/javax/javax/management/relation/MBeanServerNotificationFilter.java
trunk/core/src/openjdk/javax/javax/management/relation/Relation.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationException.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationNotFoundException.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationNotification.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationService.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationServiceMBean.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationServiceNotRegisteredException.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationSupport.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationSupportMBean.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationType.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationTypeNotFoundException.java
trunk/core/src/openjdk/javax/javax/management/relation/RelationTypeSupport.java
trunk/core/src/openjdk/javax/javax/management/relation/Role.java
trunk/core/src/openjdk/javax/javax/management/relation/RoleInfo.java
trunk/core/src/openjdk/javax/javax/management/relation/RoleInfoNotFoundException.java
trunk/core/src/openjdk/javax/javax/management/relation/RoleList.java
trunk/core/src/openjdk/javax/javax/management/relation/RoleNotFoundException.java
trunk/core/src/openjdk/javax/javax/management/relation/RoleResult.java
trunk/core/src/openjdk/javax/javax/management/relation/RoleStatus.java
trunk/core/src/openjdk/javax/javax/management/relation/RoleUnresolved.java
trunk/core/src/openjdk/javax/javax/management/relation/RoleUnresolvedList.java
trunk/core/src/openjdk/javax/javax/management/relation/package.html
trunk/core/src/openjdk/javax/javax/management/remote/JMXAddressable.java
trunk/core/src/openjdk/javax/javax/management/remote/JMXAuthenticator.java
trunk/core/src/openjdk/javax/javax/management/remote/JMXConnectionNotification.java
trunk/core/src/openjdk/javax/javax/management/remote/JMXConnectorServer.java
trunk/core/src/openjdk/javax/javax/management/remote/JMXConnectorServerMBean.java
trunk/core/src/openjdk/javax/javax/management/remote/JMXConnectorServerProvider.java
trunk/core/src/openjdk/javax/javax/management/remote/JMXPrincipal.java
trunk/core/src/openjdk/javax/javax/management/remote/JMXServerErrorException.java
trunk/core/src/openjdk/javax/javax/management/remote/MBeanServerForwarder.java
trunk/core/src/openjdk/javax/javax/management/remote/NotificationResult.java
trunk/core/src/openjdk/javax/javax/management/remote/SubjectDelegationPermission.java
trunk/core/src/openjdk/javax/javax/management/remote/TargetedNotification.java
trunk/core/src/openjdk/javax/javax/management/remote/package.html
trunk/core/src/openjdk/javax/javax/management/remote/rmi/
trunk/core/src/openjdk/javax/javax/management/remote/rmi/NoCallStackClassLoader.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/RMIConnection.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/RMIConnectionImpl.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/RMIConnector.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/RMIConnectorServer.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/RMIIIOPServerImpl.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/RMIJRMPServerImpl.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/RMIServer.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/RMIServerImpl.java
trunk/core/src/openjdk/javax/javax/management/remote/rmi/package.html
trunk/core/src/openjdk/javax/javax/management/timer/
trunk/core/src/openjdk/javax/javax/management/timer/Timer.java
trunk/core/src/openjdk/javax/javax/management/timer/TimerAlarmClockNotification.java
trunk/core/src/openjdk/javax/javax/management/timer/TimerMBean.java
trunk/core/src/openjdk/javax/javax/management/timer/TimerNotification.java
trunk/core/src/openjdk/javax/javax/management/timer/package.html
trunk/core/src/openjdk/sun/sun/management/FileSystem.java
trunk/core/src/openjdk/sun/sun/management/FileSystemImpl.java
trunk/core/src/openjdk/sun/sun/management/Flag.java
trunk/core/src/openjdk/sun/sun/management/GarbageCollectorImpl.java
trunk/core/src/openjdk/sun/sun/management/GcInfoBuilder.java
trunk/core/src/openjdk/sun/sun/management/GcInfoCompositeData.java
trunk/core/src/openjdk/sun/sun/management/HotSpotDiagnostic.java
trunk/core/src/openjdk/sun/sun/management/HotspotClassLoading.java
trunk/core/src/openjdk/sun/sun/management/HotspotClassLoadingMBean.java
trunk/core/src/openjdk/sun/sun/management/HotspotCompilation.java
trunk/core/src/openjdk/sun/sun/management/HotspotCompilationMBean.java
trunk/core/src/openjdk/sun/sun/management/HotspotMemory.java
trunk/core/src/openjdk/sun/sun/management/HotspotMemoryMBean.java
trunk/core/src/openjdk/sun/sun/management/HotspotRuntime.java
trunk/core/src/openjdk/sun/sun/management/HotspotRuntimeMBean.java
trunk/core/src/openjdk/sun/sun/management/HotspotThread.java
trunk/core/src/openjdk/sun/sun/management/HotspotThreadMBean.java
trunk/core/src/openjdk/sun/sun/management/ManagementFactory.java
trunk/core/src/openjdk/sun/sun/management/MemoryImpl.java
trunk/core/src/openjdk/sun/sun/management/MemoryManagerImpl.java
trunk/core/src/openjdk/sun/sun/management/MemoryPoolImpl.java
trunk/core/src/openjdk/sun/sun/management/MethodInfo.java
trunk/core/src/openjdk/sun/sun/management/NotificationEmitterSupport.java
trunk/core/src/openjdk/sun/sun/management/OperatingSystemImpl.java
trunk/core/src/openjdk/sun/sun/management/RuntimeImpl.java
trunk/core/src/openjdk/sun/sun/management/Sensor.java
trunk/core/src/openjdk/sun/sun/management/ThreadImpl.java
trunk/core/src/openjdk/sun/sun/management/VMManagement.java
trunk/core/src/openjdk/sun/sun/management/VMManagementImpl.java
trunk/core/src/openjdk/sun/sun/management/counter/
trunk/core/src/openjdk/sun/sun/management/counter/AbstractCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/ByteArrayCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/Counter.java
trunk/core/src/openjdk/sun/sun/management/counter/LongArrayCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/LongCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/StringCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/Units.java
trunk/core/src/openjdk/sun/sun/management/counter/Variability.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/
trunk/core/src/openjdk/sun/sun/management/counter/perf/ByteArrayCounterSnapshot.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/InstrumentationException.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/LongArrayCounterSnapshot.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/LongCounterSnapshot.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/PerfByteArrayCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/PerfDataEntry.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/PerfDataType.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/PerfInstrumentation.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/PerfLongArrayCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/PerfLongCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/PerfStringCounter.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/Prologue.java
trunk/core/src/openjdk/sun/sun/management/counter/perf/StringCounterSnapshot.java
trunk/core/src/openjdk/sun/sun/management/jmxremote/
trunk/core/src/openjdk/sun/sun/management/jmxremote/SingleEntryRegistry.java
trunk/core/src/openjdk/sun/sun/management/jmxremote/package.html
Added: trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java
===================================================================
--- trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java (rev 0)
+++ trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ArrayNotificationBuffer.java 2007-09-08 16:47:35 UTC (rev 3472)
@@ -0,0 +1,754 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.remote.internal;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MalformedObjectNameException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerDelegate;
+import javax.management.MBeanServerNotification;
+import javax.management.Notification;
+import javax.management.NotificationBroadcaster;
+import javax.management.NotificationFilter;
+import javax.management.NotificationFilterSupport;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.QueryEval;
+import javax.management.QueryExp;
+
+import javax.management.remote.NotificationResult;
+import javax.management.remote.TargetedNotification;
+
+import com.sun.jmx.remote.util.EnvHelp;
+import com.sun.jmx.remote.util.ClassLogger;
+
+/** A circular buffer of notifications received from an MBean server. */
+public class ArrayNotificationBuffer implements NotificationBuffer {
+
+ private boolean disposed = false;
+
+ // FACTORY STUFF, INCLUDING SHARING
+
+ private static final
+ HashMap<MBeanServer,ArrayNotificationBuffer> mbsToBuffer =
+ new HashMap<MBeanServer,ArrayNotificationBuffer>(1);
+ private final Collection<ShareBuffer> sharers = new HashSet<ShareBuffer>(1);
+
+ public static synchronized NotificationBuffer
+ getNotificationBuffer(MBeanServer mbs, Map env) {
+
+ //Find out queue size
+ int queueSize = EnvHelp.getNotifBufferSize(env);
+
+ ArrayNotificationBuffer buf = mbsToBuffer.get(mbs);
+ if (buf == null) {
+ buf = new ArrayNotificationBuffer(mbs, queueSize);
+ mbsToBuffer.put(mbs, buf);
+ }
+ return buf.new ShareBuffer(queueSize);
+ }
+
+ public static synchronized void removeNotificationBuffer(MBeanServer mbs) {
+ mbsToBuffer.remove(mbs);
+ }
+
+ synchronized void addSharer(ShareBuffer sharer) {
+ if (sharer.getSize() > queueSize)
+ resize(sharer.getSize());
+ sharers.add(sharer);
+ }
+
+ void removeSharer(ShareBuffer sharer) {
+ boolean empty;
+ synchronized (this) {
+ sharers.remove(sharer);
+ empty = sharers.isEmpty();
+ if (!empty) {
+ int max = 0;
+ for (ShareBuffer buf : sharers) {
+ int bufsize = buf.getSize();
+ if (bufsize > max)
+ max = bufsize;
+ }
+ if (max < queueSize)
+ resize(max);
+ }
+ }
+ if (empty)
+ dispose();
+ }
+
+ private void resize(int newSize) {
+ if (newSize == queueSize)
+ return;
+ while (queue.size() > newSize)
+ dropNotification();
+ queue.resize(newSize);
+ queueSize = newSize;
+ }
+
+ private class ShareBuffer implements NotificationBuffer {
+ ShareBuffer(int size) {
+ this.size = size;
+ addSharer(this);
+ }
+
+ public NotificationResult
+ fetchNotifications(NotificationBufferFilter filter,
+ long startSequenceNumber,
+ long timeout,
+ int maxNotifications)
+ throws InterruptedException {
+ NotificationBuffer buf = ArrayNotificationBuffer.this;
+ return buf.fetchNotifications(filter, startSequenceNumber,
+ timeout, maxNotifications);
+ }
+
+ public void dispose() {
+ ArrayNotificationBuffer.this.removeSharer(this);
+ }
+
+ int getSize() {
+ return size;
+ }
+
+ private final int size;
+ }
+
+
+ // ARRAYNOTIFICATIONBUFFER IMPLEMENTATION
+
+ private ArrayNotificationBuffer(MBeanServer mbs, int queueSize) {
+ if (logger.traceOn())
+ logger.trace("Constructor", "queueSize=" + queueSize);
+
+ if (mbs == null || queueSize < 1)
+ throw new IllegalArgumentException("Bad args");
+
+ this.mBeanServer = mbs;
+ this.queueSize = queueSize;
+ this.queue = new ArrayQueue<NamedNotification>(queueSize);
+ this.earliestSequenceNumber = System.currentTimeMillis();
+ this.nextSequenceNumber = this.earliestSequenceNumber;
+
+ createListeners();
+
+ logger.trace("Constructor", "ends");
+ }
+
+ private synchronized boolean isDisposed() {
+ return disposed;
+ }
+
+ public void dispose() {
+ logger.trace("dispose", "starts");
+
+ synchronized(this) {
+ removeNotificationBuffer(mBeanServer);
+ disposed = true;
+ //Notify potential waiting fetchNotification call
+ notifyAll();
+ }
+
+ destroyListeners();
+
+ logger.trace("dispose", "ends");
+ }
+
+ /**
+ * <p>Fetch notifications that match the given listeners.</p>
+ *
+ * <p>The operation only considers notifications with a sequence
+ * number at least <code>startSequenceNumber</code>. It will take
+ * no longer than <code>timeout</code>, and will return no more
+ * than <code>maxNotifications</code> different notifications.</p>
+ *
+ * <p>If there are no notifications matching the criteria, the
+ * operation will block until one arrives, subject to the
+ * timeout.</p>
+ *
+ * @param filter an object that will add notifications to a
+ * {@code List<TargetedNotification>} if they match the current
+ * listeners with their filters.
+ * @param startSequenceNumber the first sequence number to
+ * consider.
+ * @param timeout the maximum time to wait. May be 0 to indicate
+ * not to wait if there are no notifications.
+ * @param maxNotifications the maximum number of notifications to
+ * return. May be 0 to indicate a wait for eligible notifications
+ * that will return a usable <code>nextSequenceNumber</code>. The
+ * {@link TargetedNotification} array in the returned {@link
+ * NotificationResult} may contain more than this number of
+ * elements but will not contain more than this number of
+ * different notifications.
+ */
+ public NotificationResult
+ fetchNotifications(NotificationBufferFilter filter,
+ long startSequenceNumber,
+ long timeout,
+ int maxNotifications)
+ throws InterruptedException {
+
+ logger.trace("fetchNotifications", "starts");
+
+ if (startSequenceNumber < 0 || isDisposed()) {
+ synchronized(this) {
+ return new NotificationResult(earliestSequenceNumber(),
+ nextSequenceNumber(),
+ new TargetedNotification[0]);
+ }
+ }
+
+ // Check arg validity
+ if (filter == null
+ || startSequenceNumber < 0 || timeout < 0
+ || maxNotifications < 0) {
+ logger.trace("fetchNotifications", "Bad args");
+ throw new IllegalArgumentException("Bad args to fetch");
+ }
+
+ if (logger.debugOn()) {
+ logger.trace("fetchNotifications",
+ "filter=" + filter + "; startSeq=" +
+ startSequenceNumber + "; timeout=" + timeout +
+ "; max=" + maxNotifications);
+ }
+
+ if (startSequenceNumber > nextSequenceNumber()) {
+ final String msg = "Start sequence number too big: " +
+ startSequenceNumber + " > " + nextSequenceNumber();
+ logger.trace("fetchNotifications", msg);
+ throw new IllegalArgumentException(msg);
+ }
+
+ /* Determine the end time corresponding to the timeout value.
+ Caller may legitimately supply Long.MAX_VALUE to indicate no
+ timeout. In that case the addition will overflow and produce
+ a negative end time. Set end time to Long.MAX_VALUE in that
+ case. We assume System.currentTimeMillis() is positive. */
+ long endTime = System.currentTimeMillis() + timeout;
+ if (endTime < 0) // overflow
+ endTime = Long.MAX_VALUE;
+
+ if (logger.debugOn())
+ logger.debug("fetchNotifications", "endTime=" + endTime);
+
+ /* We set earliestSeq the first time through the loop. If we
+ set it here, notifications could be dropped before we
+ started examining them, so earliestSeq might not correspond
+ to the earliest notification we examined. */
+ long earliestSeq = -1;
+ long nextSeq = startSequenceNumber;
+ List<TargetedNotification> notifs =
+ new ArrayList<TargetedNotification>();
+
+ /* On exit from this loop, notifs, earliestSeq, and nextSeq must
+ all be correct values for the returned NotificationResult. */
+ while (true) {
+ logger.debug("fetchNotifications", "main loop starts");
+
+ NamedNotification candidate;
+
+ /* Get the next available notification regardless of filters,
+ or wait for one to arrive if there is none. */
+ synchronized (this) {
+
+ /* First time through. The current earliestSequenceNumber
+ is the first one we could have examined. */
+ if (earliestSeq < 0) {
+ earliestSeq = earliestSequenceNumber();
+ if (logger.debugOn()) {
+ logger.debug("fetchNotifications",
+ "earliestSeq=" + earliestSeq);
+ }
+ if (nextSeq < earliestSeq) {
+ nextSeq = earliestSeq;
+ logger.debug("fetchNotifications",
+ "nextSeq=earliestSeq");
+ }
+ } else
+ earliestSeq = earliestSequenceNumber();
+
+ /* If many notifications have been dropped since the
+ last time through, nextSeq could now be earlier
+ than the current earliest. If so, notifications
+ may have been lost and we return now so the caller
+ can see this next time it calls. */
+ if (nextSeq < earliestSeq) {
+ logger.trace("fetchNotifications",
+ "nextSeq=" + nextSeq + " < " + "earliestSeq=" +
+ earliestSeq + " so may have lost notifs");
+ break;
+ }
+
+ if (nextSeq < nextSequenceNumber()) {
+ candidate = notificationAt(nextSeq);
+ if (logger.debugOn()) {
+ logger.debug("fetchNotifications", "candidate: " +
+ candidate);
+ logger.debug("fetchNotifications", "nextSeq now " +
+ nextSeq);
+ }
+ } else {
+ /* nextSeq is the largest sequence number. If we
+ already got notifications, return them now.
+ Otherwise wait for some to arrive, with
+ timeout. */
+ if (notifs.size() > 0) {
+ logger.debug("fetchNotifications",
+ "no more notifs but have some so don't wait");
+ break;
+ }
+ long toWait = endTime - System.currentTimeMillis();
+ if (toWait <= 0) {
+ logger.debug("fetchNotifications", "timeout");
+ break;
+ }
+
+ /* dispose called */
+ if (isDisposed()) {
+ if (logger.debugOn())
+ logger.debug("fetchNotifications",
+ "dispose callled, no wait");
+ return new NotificationResult(earliestSequenceNumber(),
+ nextSequenceNumber(),
+ new TargetedNotification[0]);
+ }
+
+ if (logger.debugOn())
+ logger.debug("fetchNotifications",
+ "wait(" + toWait + ")");
+ wait(toWait);
+
+ continue;
+ }
+ }
+
+ /* We have a candidate notification. See if it matches
+ our filters. We do this outside the synchronized block
+ so we don't hold up everyone accessing the buffer
+ (including notification senders) while we evaluate
+ potentially slow filters. */
+ ObjectName name = candidate.getObjectName();
+ Notification notif = candidate.getNotification();
+ List<TargetedNotification> matchedNotifs =
+ new ArrayList<TargetedNotification>();
+ logger.debug("fetchNotifications",
+ "applying filter to candidate");
+ filter.apply(matchedNotifs, name, notif);
+
+ if (matchedNotifs.size() > 0) {
+ /* We only check the max size now, so that our
+ returned nextSeq is as large as possible. This
+ prevents the caller from thinking it missed
+ interesting notifications when in fact we knew they
+ weren't. */
+ if (maxNotifications <= 0) {
+ logger.debug("fetchNotifications",
+ "reached maxNotifications");
+ break;
+ }
+ --maxNotifications;
+ if (logger.debugOn())
+ logger.debug("fetchNotifications", "add: " +
+ matchedNotifs);
+ notifs.addAll(matchedNotifs);
+ }
+
+ ++nextSeq;
+ } // end while
+
+ /* Construct and return the result. */
+ int nnotifs = notifs.size();
+ TargetedNotification[] resultNotifs =
+ new TargetedNotification[nnotifs];
+ notifs.toArray(resultNotifs);
+ NotificationResult nr =
+ new NotificationResult(earliestSeq, nextSeq, resultNotifs);
+ if (logger.debugOn())
+ logger.debug("fetchNotifications", nr.toString());
+ logger.trace("fetchNotifications", "ends");
+
+ return nr;
+ }
+
+ synchronized long earliestSequenceNumber() {
+ return earliestSequenceNumber;
+ }
+
+ synchronized long nextSequenceNumber() {
+ return nextSequenceNumber;
+ }
+
+ synchronized void addNotification(NamedNotification notif) {
+ if (logger.traceOn())
+ logger.trace("addNotification", notif.toString());
+
+ while (queue.size() >= queueSize) {
+ dropNotification();
+ if (logger.debugOn()) {
+ logger.debug("addNotification",
+ "dropped oldest notif, earliestSeq=" +
+ earliestSequenceNumber);
+ }
+ }
+ queue.add(notif);
+ nextSequenceNumber++;
+ if (logger.debugOn())
+ logger.debug("addNotification", "nextSeq=" + nextSequenceNumber);
+ notifyAll();
+ }
+
+ private void dropNotification() {
+ queue.remove(0);
+ earliestSequenceNumber++;
+ }
+
+ synchronized NamedNotification notificationAt(long seqNo) {
+ long index = seqNo - earliestSequenceNumber;
+ if (index < 0 || index > Integer.MAX_VALUE) {
+ final String msg = "Bad sequence number: " + seqNo + " (earliest "
+ + earliestSequenceNumber + ")";
+ logger.trace("notificationAt", msg);
+ throw new IllegalArgumentException(msg);
+ }
+ return queue.get((int) index);
+ }
+
+ private static class NamedNotification {
+ NamedNotification(ObjectName sender, Notification notif) {
+ this.sender = sender;
+ this.notification = notif;
+ }
+
+ ObjectName getObjectName() {
+ return sender;
+ }
+
+ Notification getNotification() {
+ return notification;
+ }
+
+ public String toString() {
+ return "NamedNotification(" + sender + ", " + notification + ")";
+ }
+
+ private final ObjectName sender;
+ private final Notification notification;
+ }
+
+ /*
+ * Add our listener to every NotificationBroadcaster MBean
+ * currently in the MBean server and to every
+ * NotificationBroadcaster later created.
+ *
+ * It would be really nice if we could just do
+ * mbs.addNotificationListener(new ObjectName("*:*"), ...);
+ * Definitely something for the next version of JMX.
+ *
+ * There is a nasty race condition that we must handle. We
+ * first register for MBean-creation notifications so we can add
+ * listeners to new MBeans, then we query the existing MBeans to
+ * add listeners to them. The problem is that a new MBean could
+ * arrive after we register for creations but before the query has
+ * completed. Then we could see the MBean both in the query and
+ * in an MBean-creation notification, and we would end up
+ * registering our listener twice.
+ *
+ * To solve this problem, we arrange for new MBeans that arrive
+ * while the query is being done to be added to the Set createdDuringQuery
+ * and we do not add a listener immediately. When the query is done,
+ * we atomically turn off the addition of new names to createdDuringQuery
+ * and add all the names that were there to the result of the query.
+ * Since we are dealing with Sets, the result is the same whether or not
+ * the newly-created MBean was included in the query result.
+ *
+ * It is important not to hold any locks during the operation of adding
+ * listeners to MBeans. An MBean's addNotificationListener can be
+ * arbitrary user code, and this could deadlock with any locks we hold
+ * (see bug 6239400). The corollary is that we must not do any operations
+ * in this method or the methods it calls that require locks.
+ */
+ private void createListeners() {
+ logger.debug("createListeners", "starts");
+
+ synchronized (this) {
+ createdDuringQuery = new HashSet<ObjectName>();
+ }
+
+ try {
+ addNotificationListener(MBeanServerDelegate.DELEGATE_NAME,
+ creationListener, creationFilter, null);
+ logger.debug("createListeners", "added creationListener");
+ } catch (Exception e) {
+ final String msg = "Can't add listener to MBean server delegate: ";
+ RuntimeException re = new IllegalArgumentException(msg + e);
+ EnvHelp.initCause(re, e);
+ logger.fine("createListeners", msg + e);
+ logger.debug("createListeners", e);
+ throw re;
+ }
+
+ /* Spec doesn't say whether Set returned by QueryNames can be modified
+ so we clone it. */
+ Set<ObjectName> names = queryNames(null, broadcasterQuery);
+ names = new HashSet<ObjectName>(names);
+
+ synchronized (this) {
+ names.addAll(createdDuringQuery);
+ createdDuringQuery = null;
+ }
+
+ for (ObjectName name : names)
+ addBufferListener(name);
+ logger.debug("createListeners", "ends");
+ }
+
+ private void addBufferListener(ObjectName name) {
+ if (logger.debugOn())
+ logger.debug("addBufferListener", name.toString());
+ try {
+ addNotificationListener(name, bufferListener, null, name);
+ } catch (Exception e) {
+ logger.trace("addBufferListener", e);
+ /* This can happen if the MBean was unregistered just
+ after the query. Or user NotificationBroadcaster might
+ throw unexpected exception. */
+ }
+ }
+
+ private void removeBufferListener(ObjectName name) {
+ if (logger.debugOn())
+ logger.debug("removeBufferListener", name.toString());
+ try {
+ removeNotificationListener(name, bufferListener);
+ } catch (Exception e) {
+ logger.trace("removeBufferListener", e);
+ }
+ }
+
+ private void addNotificationListener(final ObjectName name,
+ final NotificationListener listener,
+ final NotificationFilter filter,
+ final Object handback)
+ throws Exception {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ public Void run() throws InstanceNotFoundException {
+ mBeanServer.addNotificationListener(name,
+ listener,
+ filter,
+ handback);
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ throw extractException(e);
+ }
+ }
+
+ private void removeNotificationListener(final ObjectName name,
+ final NotificationListener listener)
+ throws Exception {
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ public Void run() throws Exception {
+ mBeanServer.removeNotificationListener(name, listener);
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ throw extractException(e);
+ }
+ }
+
+ private Set<ObjectName> queryNames(final ObjectName name,
+ final QueryExp query) {
+ PrivilegedAction<Set<ObjectName>> act =
+ new PrivilegedAction<Set<ObjectName>>() {
+ public Set<ObjectName> run() {
+ return mBeanServer.queryNames(name, query);
+ }
+ };
+ try {
+ return AccessController.doPrivileged(act);
+ } catch (RuntimeException e) {
+ logger.fine("queryNames", "Failed to query names: " + e);
+ logger.debug("queryNames", e);
+ throw e;
+ }
+ }
+
+ private static boolean isInstanceOf(final MBeanServer mbs,
+ final ObjectName name,
+ final String className) {
+ PrivilegedExceptionAction<Boolean> act =
+ new PrivilegedExceptionAction<Boolean>() {
+ public Boolean run() throws InstanceNotFoundException {
+ return mbs.isInstanceOf(name, className);
+ }
+ };
+ try {
+ return AccessController.doPrivileged(act);
+ } catch (Exception e) {
+ logger.fine("isInstanceOf", "failed: " + e);
+ logger.debug("isInstanceOf", e);
+ return false;
+ }
+ }
+
+ /* This method must not be synchronized. See the comment on the
+ * createListeners method.
+ *
+ * The notification could arrive after our buffer has been destroyed
+ * or even during its destruction. So we always add our listener
+ * (without synchronization), then we check if the buffer has been
+ * destroyed and if so remove the listener we just added.
+ */
+ private void createdNotification(MBeanServerNotification n) {
+ final String shouldEqual =
+ MBeanServerNotification.REGISTRATION_NOTIFICATION;
+ if (!n.getType().equals(shouldEqual)) {
+ logger.warning("createNotification", "bad type: " + n.getType());
+ return;
+ }
+
+ ObjectName name = n.getMBeanName();
+ if (logger.debugOn())
+ logger.debug("createdNotification", "for: " + name);
+
+ synchronized (this) {
+ if (createdDuringQuery != null) {
+ createdDuringQuery.add(name);
+ return;
+ }
+ }
+
+ if (isInstanceOf(mBeanServer, name, broadcasterClass)) {
+ addBufferListener(name);
+ if (isDisposed())
+ removeBufferListener(name);
+ }
+ }
+
+ private class BufferListener implements NotificationListener {
+ public void handleNotification(Notification notif, Object handback) {
+ if (logger.debugOn()) {
+ logger.debug("BufferListener.handleNotification",
+ "notif=" + notif + "; handback=" + handback);
+ }
+ ObjectName name = (ObjectName) handback;
+ addNotification(new NamedNotification(name, notif));
+ }
+ }
+
+ private final NotificationListener bufferListener = new BufferListener();
+
+ private static class BroadcasterQuery
+ extends QueryEval implements QueryExp {
+ private static final long serialVersionUID = 7378487660587592048L;
+
+ public boolean apply(final ObjectName name) {
+ final MBeanServer mbs = QueryEval.getMBeanServer();
+ return isInstanceOf(mbs, name, broadcasterClass);
+ }
+ }
+ private static final QueryExp broadcasterQuery = new BroadcasterQuery();
+
+ private static final NotificationFilter creationFilter;
+ static {
+ NotificationFilterSupport nfs = new NotificationFilterSupport();
+ nfs.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION);
+ creationFilter = nfs;
+ }
+
+ private final NotificationListener creationListener =
+ new NotificationListener() {
+ public void handleNotification(Notification notif,
+ Object handback) {
+ logger.debug("creationListener", "handleNotification called");
+ createdNotification((MBeanServerNotification) notif);
+ }
+ };
+
+ private void destroyListeners() {
+ logger.debug("destroyListeners", "starts");
+ try {
+ removeNotificationListener(MBeanServerDelegate.DELEGATE_NAME,
+ creationListener);
+ } catch (Exception e) {
+ logger.warning("remove listener from MBeanServer delegate", e);
+ }
+ Set<ObjectName> names = queryNames(null, broadcasterQuery);
+ for (final ObjectName name : names) {
+ if (logger.debugOn())
+ logger.debug("destroyListeners",
+ "remove listener from " + name);
+ removeBufferListener(name);
+ }
+ logger.debug("destroyListeners", "ends");
+ }
+
+ /**
+ * Iterate until we extract the real exception
+ * from a stack of PrivilegedActionExceptions.
+ */
+ private static Exception extractException(Exception e) {
+ while (e instanceof PrivilegedActionException) {
+ e = ((PrivilegedActionException)e).getException();
+ }
+ return e;
+ }
+
+ private static final ClassLogger logger =
+ new ClassLogger("javax.management.remote.misc",
+ "ArrayNotificationBuffer");
+
+ private final MBeanServer mBeanServer;
+ private final ArrayQueue<NamedNotification> queue;
+ private int queueSize;
+ private long earliestSequenceNumber;
+ private long nextSequenceNumber;
+ private Set<ObjectName> createdDuringQuery;
+
+ static final String broadcasterClass =
+ NotificationBroadcaster.class.getName();
+}
Added: trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ArrayQueue.java
===================================================================
--- trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ArrayQueue.java (rev 0)
+++ trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ArrayQueue.java 2007-09-08 16:47:35 UTC (rev 3472)
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.remote.internal;
+
+import java.util.AbstractList;
+import java.util.Iterator;
+
+public class ArrayQueue<T> extends AbstractList<T> {
+ public ArrayQueue(int capacity) {
+ this.capacity = capacity + 1;
+ this.queue = newArray(capacity + 1);
+ this.head = 0;
+ this.tail = 0;
+ }
+
+ public void resize(int newcapacity) {
+ int size = size();
+ if (newcapacity < size)
+ throw new IndexOutOfBoundsException("Resizing would lose data");
+ newcapacity++;
+ if (newcapacity == this.capacity)
+ return;
+ T[] newqueue = newArray(newcapacity);
+ for (int i = 0; i < size; i++)
+ newqueue[i] = get(i);
+ this.capacity = newcapacity;
+ this.queue = newqueue;
+ this.head = 0;
+ this.tail = size;
+ }
+
+ @SuppressWarnings("unchecked")
+ private T[] newArray(int size) {
+ return (T[]) new Object[size];
+ }
+
+ public boolean add(T o) {
+ queue[tail] = o;
+ int newtail = (tail + 1) % capacity;
+ if (newtail == head)
+ throw new IndexOutOfBoundsException("Queue full");
+ tail = newtail;
+ return true; // we did add something
+ }
+
+ public T remove(int i) {
+ if (i != 0)
+ throw new IllegalArgumentException("Can only remove head of queue");
+ if (head == tail)
+ throw new IndexOutOfBoundsException("Queue empty");
+ T removed = queue[head];
+ queue[head] = null;
+ head = (head + 1) % capacity;
+ return removed;
+ }
+
+ public T get(int i) {
+ int size = size();
+ if (i < 0 || i >= size) {
+ final String msg = "Index " + i + ", queue size " + size;
+ throw new IndexOutOfBoundsException(msg);
+ }
+ int index = (head + i) % capacity;
+ return queue[index];
+ }
+
+ public int size() {
+ // Can't use % here because it's not mod: -3 % 2 is -1, not +1.
+ int diff = tail - head;
+ if (diff < 0)
+ diff += capacity;
+ return diff;
+ }
+
+ private int capacity;
+ private T[] queue;
+ private int head;
+ private int tail;
+}
Added: trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java
===================================================================
--- trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java (rev 0)
+++ trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java 2007-09-08 16:47:35 UTC (rev 3472)
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2003-2005 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.jmx.remote.internal;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+
+import com.sun.jmx.remote.util.ClassLogger;
+import com.sun.jmx.remote.util.EnvHelp;
+
+public abstract class ClientCommunicatorAdmin {
+ public ClientCommunicatorAdmin(long period) {
+ this.period = period;
+
+ if (period > 0) {
+ checker = new Checker();
+
+ Thread t = new Thread(checker);
+ t.setDaemon(true);
+ t.start();
+ } else
+ checker = null;
+ }
+
+ /**
+ * Called by a client to inform of getting an IOException.
+ */
+ public void gotIOException (IOException ioe) throws IOException {
+ restart(ioe);
+ }
+
+ /**
+ * Called by this class to check a client connection.
+ */
+ protected abstract void checkConnection() throws IOException;
+
+ /**
+ * Tells a client to re-start again.
+ */
+ protected abstract void doStart() throws IOException;
+
+ /**
+ * Tells a client to stop because failing to call checkConnection.
+ */
+ protected abstract void doStop();
+
+ /**
+ * Terminates this object.
+ */
+ public void terminate() {
+ synchronized(lock) {
+ if (state == TERMINATED) {
+ return;
+ }
+
+ state = TERMINATED;
+
+ lock.notifyAll();
+
+ if (checker != null)
+ checker.stop();
+ }
+ }
+
+ private void restart(IOException ioe) throws IOException {
+ // check state
+ synchronized(lock) {
+ if (state == TERMINATED) {
+ throw new IOException("The client has been closed.");
+ } else if (state == FAILED) { // already failed to re-start by another thread
+ throw ioe;
+ } else if (state == RE_CONNECTING) {
+ // restart process has been called by another thread
+ // we need to wait
+ while(state == RE_CONNECTING) {
+ try {
+ lock.wait();
+ } catch (InterruptedException ire) {
+ // be asked to give up
+ InterruptedIOException iioe = new InterruptedIOException(ire.toString());
+ EnvHelp.initCause(iioe, ire);
+
+ throw iioe;
+ }
+ }
+
+ if (state == TERMINATED) {
+ throw new IOException("The client has been closed.");
+ } else if (state != CONNECTED) {
+ // restarted is failed by another thread
+ throw ioe;
+ }
+ } else {
+ state = RE_CONNECTING;
+ lock.notifyAll();
+ }
+ }
+
+ // re-starting
+ try {
+ doStart();
+ synchronized(lock) {
+ if (state == TERMINATED) {
+ throw new IOException("The client has been closed.");
+ }
+
+ state = CONNECTED;
+
+ lock.notifyAll();
+ }
+
+ return;
+ } catch (Exception e) {
+ logger.warning("restart", "Failed to restart: " + e);
+ logger.debug("restart",e);
+
+ synchronized(lock) {
+ if (state == TERMINATED) {
+ throw new IOException("The client has been closed.");
+ }
+
+ state = FAILED;
+
+ lock.notifyAll();
+ }
+
+ try {
+ doStop();
+ } catch (Exception eee) {
+ // OK.
+ // We know there is a problem.
+ }
+
+ terminate();
+
+ throw ioe;
+ }
+ }
+
+// --------------------------------------------------------------
+// private varaibles
+// --------------------------------------------------------------
+ private class Checker implements Runnable {
+ public void run() {
+ myThread = Thread.currentThread();
+
+ while (state != TERMINATED && !myThread.isInterrupted()) {
+ try {
+ Thread.sleep(period);
+ } catch (InterruptedException ire) {
+ // OK.
+ // We will check the state at the following steps
+ }
+
+ if (state == TERMINATED || myThread.isInterrupted()) {
+ break;
+ }
+
+ try {
+ checkConnection();
+ } catch (Exception e) {
+ synchronized(lock) {
+ if (state == TERMINATED || myThread.isInterrupted()) {
+ break;
+ }
+ }
+
+ e = (Exception)EnvHelp.getCause(e);
+
+ if (e instanceof IOException &&
+ !(e instanceof InterruptedIOException)) {
+ try {
+ restart((IOException)e);
+ } catch (Exception ee) {
+ logger.warning("Checker-run",
+ "Failed to check connection: "+ e);
+ logger.warning("Checker-run", "stopping");
+ logger.debug("Checker-run",e);
+
+ break;
+ }
+ } else {
+ logger.warning("Checker-run",
+ "Failed to check the connection: " + e);
+ logger.debug("Checker-run",e);
+
+ // XXX stop checking?
+
+ break;
+ }
+ }
+ }
+
+ if (logger.traceOn()) {
+ logger.trace("Checker-run", "Finished.");
+ }
+ }
+
+ private void stop() {
+ if (myThread != null && myThread != Thread.currentThread()) {
+ myThread.interrupt();
+ }
+ }
+
+ private Thread myThread;
+ }
+
+// --------------------------------------------------------------
+// private variables
+// --------------------------------------------------------------
+ private final Checker checker;
+ private long period;
+
+ // state
+ private final static int CONNECTED = 0;
+ private final static int RE_CONNECTING = 1;
+ private final static int FAILED = 2;
+ private final static int TERMINATED = 3;
+
+ private int state = CONNECTED;
+
+ private final int[] lock = new int[0];
+
+ private static final ClassLogger logger =
+ new ClassLogger("javax.management.remote.misc",
+ "ClientCommunicatorAdmin");
+}
Added: trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientListenerInfo.java
===================================================================
--- trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientListenerInfo.java (rev 0)
+++ trunk/core/src/openjdk/com/com/sun/jmx/remote/internal/ClientListenerInfo.java 2007-09-08 16:47:35 UTC (rev 3472)
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2003-2006 Sun Micros...
[truncated message content] |