001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.mina.integration.jmx;
018
019import java.net.SocketAddress;
020import java.util.LinkedHashSet;
021import java.util.List;
022import java.util.Set;
023
024import javax.management.MBeanOperationInfo;
025import javax.management.MBeanParameterInfo;
026import javax.management.ObjectName;
027import javax.management.modelmbean.ModelMBeanOperationInfo;
028
029import ognl.Ognl;
030
031import org.apache.mina.core.service.IoService;
032import org.apache.mina.core.session.IoSession;
033import org.apache.mina.integration.ognl.IoSessionFinder;
034
035/**
036 * A JMX MBean wrapper for an {@link IoSession}.
037 *
038 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
039 */
040public class IoServiceMBean extends ObjectMBean<IoService> {
041
042    static String getSessionIdAsString(long l) {
043        // ID in MINA is a unsigned 32-bit integer.
044        String id = Long.toHexString(l).toUpperCase();
045        while (id.length() < 8) {
046            id = '0' + id; // padding
047        }
048        id = "0x" + id;
049        return id;
050    }
051
052    public IoServiceMBean(IoService source) {
053        super(source);
054    }
055
056    @Override
057    protected Object invoke0(String name, Object[] params, String[] signature) throws Exception {
058        if (name.equals("findSessions")) {
059            IoSessionFinder finder = new IoSessionFinder((String) params[0]);
060            return finder.find(getSource().getManagedSessions().values());
061        }
062
063        if (name.equals("findAndRegisterSessions")) {
064            IoSessionFinder finder = new IoSessionFinder((String) params[0]);
065            Set<IoSession> registeredSessions = new LinkedHashSet<IoSession>();
066            for (IoSession s : finder.find(getSource().getManagedSessions().values())) {
067                try {
068                    getServer().registerMBean(
069                            new IoSessionMBean(s),
070                            new ObjectName(getName().getDomain() + ":type=session,name="
071                                    + getSessionIdAsString(s.getId())));
072                    registeredSessions.add(s);
073                } catch (Exception e) {
074                    LOGGER.warn("Failed to register a session as a MBean: " + s, e);
075                }
076            }
077
078            return registeredSessions;
079        }
080
081        if (name.equals("findAndProcessSessions")) {
082            IoSessionFinder finder = new IoSessionFinder((String) params[0]);
083            String command = (String) params[1];
084            Object expr = Ognl.parseExpression(command);
085            Set<IoSession> matches = finder.find(getSource().getManagedSessions().values());
086
087            for (IoSession s : matches) {
088                try {
089                    Ognl.getValue(expr, s);
090                } catch (Exception e) {
091                    LOGGER.warn("Failed to execute '" + command + "' for: " + s, e);
092                }
093            }
094            return matches;
095        }
096
097        return super.invoke0(name, params, signature);
098    }
099
100    @Override
101    protected void addExtraOperations(List<ModelMBeanOperationInfo> operations) {
102        operations.add(new ModelMBeanOperationInfo("findSessions", "findSessions",
103                new MBeanParameterInfo[] { new MBeanParameterInfo("ognlQuery", String.class.getName(),
104                        "a boolean OGNL expression") }, Set.class.getName(), MBeanOperationInfo.INFO));
105        operations.add(new ModelMBeanOperationInfo("findAndRegisterSessions", "findAndRegisterSessions",
106                new MBeanParameterInfo[] { new MBeanParameterInfo("ognlQuery", String.class.getName(),
107                        "a boolean OGNL expression") }, Set.class.getName(), MBeanOperationInfo.ACTION_INFO));
108        operations.add(new ModelMBeanOperationInfo("findAndProcessSessions", "findAndProcessSessions",
109                new MBeanParameterInfo[] {
110                        new MBeanParameterInfo("ognlQuery", String.class.getName(), "a boolean OGNL expression"),
111                        new MBeanParameterInfo("ognlCommand", String.class.getName(),
112                                "an OGNL expression that modifies the state of the sessions in the match result") },
113                Set.class.getName(), MBeanOperationInfo.ACTION_INFO));
114    }
115
116    @Override
117    protected boolean isOperation(String methodName, Class<?>[] paramTypes) {
118        // Ignore some IoServide methods.
119        if (methodName.matches("(newSession|broadcast|(add|remove)Listener)")) {
120            return false;
121        }
122
123        if ((methodName.equals("bind") || methodName.equals("unbind"))
124                && (paramTypes.length > 1 || paramTypes.length == 1
125                        && !SocketAddress.class.isAssignableFrom(paramTypes[0]))) {
126            return false;
127        }
128
129        return super.isOperation(methodName, paramTypes);
130    }
131}