src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java
author mbaesken
Fri, 08 Jun 2018 13:06:08 +0200
changeset 50464 102ae98c917c
parent 50113 caf115bb98ad
child 58480 8ca46e186a63
permissions -rw-r--r--
8204539: improve error messages in matchJavaTZ [windows] Reviewed-by: coffeys, clanger, goetz
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50113
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     1
/*
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     2
 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     4
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    10
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    15
 * accompanied this code).
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    16
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    20
 *
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    23
 * questions.
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    24
 */
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    25
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    26
package jdk.management.jfr;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    27
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    28
import java.io.IOException;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    29
import java.io.InputStream;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    30
import java.io.StringReader;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    31
import java.nio.file.Paths;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    32
import java.security.AccessControlContext;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    33
import java.security.AccessController;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    34
import java.security.PrivilegedAction;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    35
import java.text.ParseException;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    36
import java.time.Instant;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    37
import java.util.ArrayList;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    38
import java.util.Arrays;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    39
import java.util.Collections;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    40
import java.util.HashMap;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    41
import java.util.List;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    42
import java.util.Map;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    43
import java.util.Objects;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    44
import java.util.concurrent.ConcurrentHashMap;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    45
import java.util.concurrent.CopyOnWriteArrayList;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    46
import java.util.concurrent.atomic.AtomicLong;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    47
import java.util.function.Consumer;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    48
import java.util.function.Function;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    49
import java.util.function.Predicate;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    50
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    51
import javax.management.AttributeChangeNotification;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    52
import javax.management.AttributeNotFoundException;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    53
import javax.management.ListenerNotFoundException;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    54
import javax.management.MBeanException;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    55
import javax.management.MBeanNotificationInfo;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    56
import javax.management.Notification;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    57
import javax.management.NotificationBroadcasterSupport;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    58
import javax.management.NotificationEmitter;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    59
import javax.management.NotificationFilter;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    60
import javax.management.NotificationListener;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    61
import javax.management.ObjectName;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    62
import javax.management.ReflectionException;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    63
import javax.management.StandardEmitterMBean;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    64
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    65
import jdk.jfr.Configuration;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    66
import jdk.jfr.EventType;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    67
import jdk.jfr.FlightRecorder;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    68
import jdk.jfr.FlightRecorderListener;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    69
import jdk.jfr.FlightRecorderPermission;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    70
import jdk.jfr.Recording;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    71
import jdk.jfr.RecordingState;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    72
import jdk.jfr.internal.management.ManagementSupport;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    73
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    74
// Instantiated by service provider
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    75
final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements FlightRecorderMXBean, NotificationEmitter {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    76
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    77
    final class MXBeanListener implements FlightRecorderListener {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    78
        private final NotificationListener listener;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    79
        private final NotificationFilter filter;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    80
        private final Object handback;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    81
        private final AccessControlContext context;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    82
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    83
        public MXBeanListener(NotificationListener listener, NotificationFilter filter, Object handback) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    84
            this.context = AccessController.getContext();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    85
            this.listener = listener;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    86
            this.filter = filter;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    87
            this.handback = handback;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    88
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    89
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    90
        public void recordingStateChanged(Recording recording) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    91
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    92
                @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    93
                public Void run() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    94
                    sendNotification(createNotication(recording));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    95
                    return null;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    96
                }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    97
            }, context);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    98
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
    99
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   100
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   101
    private static final String ATTRIBUTE_RECORDINGS = "Recordings";
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   102
    private static final String OPTION_MAX_SIZE = "maxSize";
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   103
    private static final String OPTION_MAX_AGE = "maxAge";
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   104
    private static final String OPTION_NAME = "name";
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   105
    private static final String OPTION_DISK = "disk";
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   106
    private static final String OPTION_DUMP_ON_EXIT = "dumpOnExit";
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   107
    private static final String OPTION_DURATION = "duration";
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   108
    private static final List<String> OPTIONS = Arrays.asList(new String[] { OPTION_DUMP_ON_EXIT, OPTION_DURATION, OPTION_NAME, OPTION_MAX_AGE, OPTION_MAX_SIZE, OPTION_DISK, });
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   109
    private final StreamManager streamHandler = new StreamManager();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   110
    private final Map<Long, Object> changes = new ConcurrentHashMap<>();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   111
    private final AtomicLong sequenceNumber = new AtomicLong();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   112
    private final List<MXBeanListener> listeners = new CopyOnWriteArrayList<>();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   113
    private FlightRecorder recorder;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   114
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   115
    FlightRecorderMXBeanImpl() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   116
        super(FlightRecorderMXBean.class, true, new NotificationBroadcasterSupport(createNotificationInfo()));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   117
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   118
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   119
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   120
    public void startRecording(long id) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   121
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   122
        getExistingRecording(id).start();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   123
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   124
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   125
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   126
    public boolean stopRecording(long id) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   127
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   128
        return getExistingRecording(id).stop();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   129
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   130
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   131
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   132
    public void closeRecording(long id) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   133
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   134
        getExistingRecording(id).close();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   135
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   136
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   137
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   138
    public long openStream(long id, Map<String, String> options) throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   139
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   140
        if (!FlightRecorder.isInitialized()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   141
            throw new IllegalArgumentException("No recording available with id " + id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   142
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   143
        // Make local copy to prevent concurrent modification
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   144
        Map<String, String> s = options == null ? new HashMap<>() : new HashMap<>(options);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   145
        Instant starttime = MBeanUtils.parseTimestamp(s.get("startTime"), Instant.MIN);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   146
        Instant endtime = MBeanUtils.parseTimestamp(s.get("endTime"), Instant.MAX);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   147
        int blockSize = MBeanUtils.parseBlockSize(s.get("blockSize"), StreamManager.DEFAULT_BLOCK_SIZE);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   148
        InputStream is = getExistingRecording(id).getStream(starttime, endtime);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   149
        if (is == null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   150
            throw new IOException("No recording data available");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   151
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   152
        return streamHandler.create(is, blockSize).getId();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   153
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   154
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   155
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   156
    public void closeStream(long streamIdentifier) throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   157
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   158
        streamHandler.getStream(streamIdentifier).close();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   159
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   160
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   161
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   162
    public byte[] readStream(long streamIdentifier) throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   163
        MBeanUtils.checkMonitor();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   164
        return streamHandler.getStream(streamIdentifier).read();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   165
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   166
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   167
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   168
    public List<RecordingInfo> getRecordings() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   169
        MBeanUtils.checkMonitor();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   170
        if (!FlightRecorder.isInitialized()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   171
            return Collections.emptyList();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   172
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   173
        return MBeanUtils.transformList(getRecorder().getRecordings(), RecordingInfo::new);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   174
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   175
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   176
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   177
    public List<ConfigurationInfo> getConfigurations() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   178
        MBeanUtils.checkMonitor();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   179
        return MBeanUtils.transformList(Configuration.getConfigurations(), ConfigurationInfo::new);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   180
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   181
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   182
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   183
    public List<EventTypeInfo> getEventTypes() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   184
        MBeanUtils.checkMonitor();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   185
        List<EventType> eventTypes = AccessController.doPrivileged(new PrivilegedAction<List<EventType>>() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   186
            @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   187
            public List<EventType> run() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   188
                return ManagementSupport.getEventTypes();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   189
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   190
        }, null, new FlightRecorderPermission("accessFlightRecorder"));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   191
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   192
        return MBeanUtils.transformList(eventTypes, EventTypeInfo::new);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   193
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   194
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   195
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   196
    public Map<String, String> getRecordingSettings(long recording) throws IllegalArgumentException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   197
        MBeanUtils.checkMonitor();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   198
        return getExistingRecording(recording).getSettings();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   199
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   200
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   201
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   202
    public void setRecordingSettings(long recording, Map<String, String> values) throws IllegalArgumentException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   203
        Objects.requireNonNull(values);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   204
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   205
        getExistingRecording(recording).setSettings(values);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   206
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   207
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   208
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   209
    public long newRecording() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   210
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   211
        getRecorder(); // ensure notification listener is setup
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   212
        return AccessController.doPrivileged(new PrivilegedAction<Recording>() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   213
            @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   214
            public Recording run() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   215
                return new Recording();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   216
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   217
        }, null, new FlightRecorderPermission("accessFlightRecorder")).getId();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   218
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   219
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   220
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   221
    public long takeSnapshot() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   222
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   223
        return getRecorder().takeSnapshot().getId();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   224
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   225
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   226
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   227
    public void setConfiguration(long recording, String configuration) throws IllegalArgumentException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   228
        Objects.requireNonNull(configuration);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   229
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   230
        try {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   231
            Configuration c = Configuration.create(new StringReader(configuration));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   232
            getExistingRecording(recording).setSettings(c.getSettings());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   233
        } catch (IOException | ParseException e) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   234
            throw new IllegalArgumentException("Could not parse configuration", e);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   235
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   236
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   237
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   238
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   239
    public void setPredefinedConfiguration(long recording, String configurationName) throws IllegalArgumentException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   240
        Objects.requireNonNull(configurationName);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   241
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   242
        Recording r = getExistingRecording(recording);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   243
        for (Configuration c : Configuration.getConfigurations()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   244
            if (c.getName().equals(configurationName)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   245
                r.setSettings(c.getSettings());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   246
                return;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   247
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   248
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   249
        throw new IllegalArgumentException("Could not find configuration with name " + configurationName);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   250
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   251
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   252
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   253
    public void copyTo(long recording, String path) throws IOException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   254
        Objects.requireNonNull(path);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   255
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   256
        getExistingRecording(recording).dump(Paths.get(path));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   257
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   258
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   259
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   260
    public void setRecordingOptions(long recording, Map<String, String> options) throws IllegalArgumentException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   261
        Objects.requireNonNull(options);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   262
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   263
        // Make local copy to prevent concurrent modification
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   264
        Map<String, String> ops = new HashMap<String, String>(options);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   265
        for (Map.Entry<String, String> entry : ops.entrySet()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   266
            Object key = entry.getKey();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   267
            Object value = entry.getValue();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   268
            if (!(key instanceof String)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   269
                throw new IllegalArgumentException("Option key must not be null, or other type than " + String.class);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   270
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   271
            if (!OPTIONS.contains(key)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   272
                throw new IllegalArgumentException("Unknown recording option: " + key + ". Valid options are " + OPTIONS + ".");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   273
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   274
            if (value != null && !(value instanceof String)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   275
                throw new IllegalArgumentException("Incorrect value for option " + key + ". Values must be of type " + String.class + " .");
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   276
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   277
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   278
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   279
        Recording r = getExistingRecording(recording);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   280
        validateOption(ops, OPTION_DUMP_ON_EXIT, MBeanUtils::booleanValue);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   281
        validateOption(ops, OPTION_DISK, MBeanUtils::booleanValue);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   282
        validateOption(ops, OPTION_NAME, Function.identity());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   283
        validateOption(ops, OPTION_MAX_AGE, MBeanUtils::duration);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   284
        validateOption(ops, OPTION_MAX_SIZE, MBeanUtils::size);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   285
        validateOption(ops, OPTION_DURATION, MBeanUtils::duration);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   286
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   287
        // All OK, now set them.atomically
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   288
        setOption(ops, OPTION_DUMP_ON_EXIT, "false", MBeanUtils::booleanValue, x -> r.setDumpOnExit(x));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   289
        setOption(ops, OPTION_DISK, "true", MBeanUtils::booleanValue, x -> r.setToDisk(x));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   290
        setOption(ops, OPTION_NAME, String.valueOf(r.getId()), Function.identity(), x -> r.setName(x));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   291
        setOption(ops, OPTION_MAX_AGE, null, MBeanUtils::duration, x -> r.setMaxAge(x));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   292
        setOption(ops, OPTION_MAX_SIZE, "0", MBeanUtils::size, x -> r.setMaxSize(x));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   293
        setOption(ops, OPTION_DURATION, null, MBeanUtils::duration, x -> r.setDuration(x));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   294
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   295
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   296
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   297
    public Map<String, String> getRecordingOptions(long recording) throws IllegalArgumentException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   298
        MBeanUtils.checkMonitor();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   299
        Recording r = getExistingRecording(recording);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   300
        Map<String, String> options = new HashMap<>(10);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   301
        options.put(OPTION_DUMP_ON_EXIT, String.valueOf(r.getDumpOnExit()));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   302
        options.put(OPTION_DISK, String.valueOf(r.isToDisk()));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   303
        options.put(OPTION_NAME, String.valueOf(r.getName()));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   304
        options.put(OPTION_MAX_AGE, ManagementSupport.formatTimespan(r.getMaxAge(), " "));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   305
        Long maxSize = r.getMaxSize();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   306
        options.put(OPTION_MAX_SIZE, String.valueOf(maxSize == null ? "0" : maxSize.toString()));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   307
        options.put(OPTION_DURATION, ManagementSupport.formatTimespan(r.getDuration(), " "));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   308
        return options;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   309
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   310
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   311
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   312
    public long cloneRecording(long id, boolean stop) throws IllegalStateException, SecurityException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   313
        MBeanUtils.checkControl();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   314
        return getRecording(id).copy(stop).getId();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   315
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   316
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   317
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   318
    public ObjectName getObjectName() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   319
        return MBeanUtils.createObjectName();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   320
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   321
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   322
    private Recording getExistingRecording(long id) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   323
        if (FlightRecorder.isInitialized()) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   324
            Recording recording = getRecording(id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   325
            if (recording != null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   326
                return recording;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   327
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   328
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   329
        throw new IllegalArgumentException("No recording available with id " + id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   330
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   331
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   332
    private Recording getRecording(long id) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   333
        List<Recording> recs = getRecorder().getRecordings();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   334
        return recs.stream().filter(r -> r.getId() == id).findFirst().orElse(null);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   335
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   336
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   337
    private static <T, U> void setOption(Map<String, String> options, String name, String defaultValue, Function<String, U> converter, Consumer<U> setter) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   338
        if (!options.containsKey(name)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   339
            return;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   340
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   341
        String v = options.get(name);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   342
        if (v == null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   343
            v = defaultValue;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   344
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   345
        try {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   346
            setter.accept(converter.apply(v));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   347
        } catch (IllegalArgumentException iae) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   348
            throw new IllegalArgumentException("Not a valid value for option '" + name + "'. " + iae.getMessage());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   349
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   350
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   351
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   352
    private static <T, U> void validateOption(Map<String, String> options, String name, Function<String, U> validator) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   353
        try {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   354
            String v = options.get(name);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   355
            if (v == null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   356
                return; // OK, will set default
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   357
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   358
            validator.apply(v);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   359
        } catch (IllegalArgumentException iae) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   360
            throw new IllegalArgumentException("Not a valid value for option '" + name + "'. " + iae.getMessage());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   361
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   362
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   363
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   364
    private FlightRecorder getRecorder() throws SecurityException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   365
        // Synchronize on some private object that is always available
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   366
        synchronized (streamHandler) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   367
            if (recorder == null) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   368
                recorder = AccessController.doPrivileged(new PrivilegedAction<FlightRecorder>() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   369
                    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   370
                    public FlightRecorder run() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   371
                        return FlightRecorder.getFlightRecorder();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   372
                    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   373
                }, null, new FlightRecorderPermission("accessFlightRecorder"));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   374
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   375
            return recorder;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   376
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   377
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   378
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   379
    private static MBeanNotificationInfo[] createNotificationInfo() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   380
        String[] types = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE };
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   381
        String name = AttributeChangeNotification.class.getName();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   382
        String description = "Notifies if the RecordingState has changed for one of the recordings, for example if a recording starts or stops";
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   383
        MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   384
        return new MBeanNotificationInfo[] { info };
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   385
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   386
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   387
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   388
    public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   389
        MXBeanListener mxbeanListener = new MXBeanListener(listener, filter, handback);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   390
        listeners.add(mxbeanListener);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   391
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   392
            @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   393
            public Void run(){
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   394
                FlightRecorder.addListener(mxbeanListener);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   395
                return null;
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   396
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   397
        }, null, new FlightRecorderPermission("accessFlightRecorder"));
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   398
        super.addNotificationListener(listener, filter, handback);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   399
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   400
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   401
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   402
    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   403
        removeListeners( x -> listener == x.listener);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   404
        super.removeNotificationListener(listener);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   405
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   406
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   407
    @Override
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   408
    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   409
        removeListeners( x -> listener == x.listener && filter == x.filter && handback == x.handback);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   410
        super.removeNotificationListener(listener, filter, handback);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   411
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   412
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   413
    private void removeListeners(Predicate<MXBeanListener> p) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   414
        List<MXBeanListener> toBeRemoved = new ArrayList<>(listeners.size());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   415
        for (MXBeanListener l : listeners) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   416
            if (p.test(l)) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   417
                toBeRemoved.add(l);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   418
                FlightRecorder.removeListener(l);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   419
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   420
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   421
        listeners.removeAll(toBeRemoved);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   422
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   423
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   424
    private Notification createNotication(Recording recording) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   425
        try {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   426
            Long id = recording.getId();
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   427
            Object oldValue = changes.get(recording.getId());
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   428
            Object newValue = getAttribute(ATTRIBUTE_RECORDINGS);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   429
            if (recording.getState() != RecordingState.CLOSED) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   430
                changes.put(id, newValue);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   431
            } else {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   432
                changes.remove(id);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   433
            }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   434
            return new AttributeChangeNotification(getObjectName(), sequenceNumber.incrementAndGet(), System.currentTimeMillis(), "Recording " + recording.getName() + " is "
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   435
                    + recording.getState(), ATTRIBUTE_RECORDINGS, newValue.getClass().getName(), oldValue, newValue);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   436
        } catch (AttributeNotFoundException | MBeanException | ReflectionException e) {
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   437
            throw new RuntimeException("Could not create notifcation for FlightRecorderMXBean. " + e.getMessage(), e);
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   438
        }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   439
    }
caf115bb98ad 8199712: Flight Recorder
egahlin
parents:
diff changeset
   440
}