001    /* 
002     * Copyright 2008-2009 the original author or authors.
003     * The contents of this file are subject to the Mozilla Public License
004     * Version 1.1 (the "License"); you may not use this file except in
005     * compliance with the License. You may obtain a copy of the License at
006     * http://www.mozilla.org/MPL/
007     *
008     * Software distributed under the License is distributed on an "AS IS"
009     * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
010     * License for the specific language governing rights and limitations
011     * under the License.
012     */
013     
014    package com.mtgi.jmx.export.naming;
015    
016    import java.util.regex.Pattern;
017    
018    import javax.management.MalformedObjectNameException;
019    import javax.management.ObjectName;
020    
021    import org.springframework.beans.factory.annotation.Required;
022    import org.springframework.jmx.export.naming.ObjectNamingStrategy;
023    
024    /**
025     * <p>A delegating naming strategy, which collects all JMX beans into a single
026     * domain by application name.  The original domain of all beans collected into
027     * the application is converted into the 'package' property, which is set at
028     * the beginning of the property list.</p>
029     * 
030     * <p>For example, <code>com.mtgi:group=analytics,name=BehaviorTrackingLog</code>
031     * would become <code>myapp:package=com.mtgi,group=analytics,name=BehaviorTrackingLog</code>
032     * if the application name is "myapp".</p>
033     * 
034     * <p>Useful primarily for complex deployments, where many applications
035     * might use the same framework classes (therefore increasing the risk of a naming
036     * collision).</p>
037     */
038    public class ApplicationNamingStrategy implements ObjectNamingStrategy {
039    
040            private static final Pattern QUOTE_NEEDED = Pattern.compile("[\\\\*?\n\",:=\\s]");
041            
042            private String application;
043            private ObjectNamingStrategy delegate;
044    
045            @Required
046            public void setApplication(String application) {
047                    this.application = quote(application);
048            }
049    
050            @Required
051            public void setDelegate(ObjectNamingStrategy delegate) {
052                    this.delegate = delegate;
053            }
054    
055            public ObjectName getObjectName(Object managedBean, String beanKey)
056                            throws MalformedObjectNameException {
057                    ObjectName base = delegate.getObjectName(managedBean, beanKey);
058    
059                    StringBuffer name = new StringBuffer(application).append(':');
060                    String domain = base.getDomain();
061                    String properties = base.getKeyPropertyListString();
062                    if (domain != null) {
063                            name.append("package=").append(quote(domain));
064                            if (properties != null)
065                                    name.append(',');
066                    }
067                    if (properties != null)
068                            name.append(properties);
069                    
070                    return ObjectName.getInstance(name.toString());
071            }
072    
073            /** reluctantly quote the given input string (quoting only applied if the string contains control characters) */
074            public static final String quote(String input) {
075                    if (QUOTE_NEEDED.matcher(input).find())
076                            return ObjectName.quote(input);
077                    return input;
078            }
079    }