/**
* Copyright (c) 2002-2011 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.management;
import static java.lang.management.ManagementFactory.getPlatformMBeanServer;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import org.neo4j.kernel.KernelExtension.KernelData;
import org.neo4j.management.impl.ConfigurationBean;
import org.neo4j.management.impl.KernelProxy;
public final class Neo4jManager extends KernelProxy implements Kernel
{
public static Neo4jManager get()
{
return get( getPlatformMBeanServer() );
}
public static Neo4jManager get( String kernelIdentifier )
{
return get( getPlatformMBeanServer(), kernelIdentifier );
}
public static Neo4jManager get( JMXServiceURL url )
{
return get( connect( url, null, null ) );
}
public static Neo4jManager get( JMXServiceURL url, String kernelIdentifier )
{
return get( connect( url, null, null ), kernelIdentifier );
}
public static Neo4jManager get( JMXServiceURL url, String username, String password )
{
return get( connect( url, username, password ) );
}
public static Neo4jManager get( JMXServiceURL url, String username, String password,
String kernelIdentifier )
{
return get( connect( url, null, null ) );
}
private static MBeanServerConnection connect( JMXServiceURL url, String username,
String password )
{
Map<String, Object> environment = new HashMap<String, Object>();
if ( username != null && password != null )
{
environment.put( JMXConnector.CREDENTIALS, new String[] { username, password } );
}
else if ( username != password )
{
throw new IllegalArgumentException(
"User name and password must either both be specified, or both be null." );
}
try
{
try
{
return JMXConnectorFactory.connect( url, environment ).getMBeanServerConnection();
}
catch ( SecurityException e )
{
environment.put( RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE,
new SslRMIClientSocketFactory() );
return JMXConnectorFactory.connect( url, environment ).getMBeanServerConnection();
}
}
catch ( IOException e )
{
throw new IllegalStateException( "Connection failed.", e );
}
}
public static Neo4jManager get( MBeanServerConnection server )
{
server.getClass();
try
{
return get( server, server.queryNames( getObjectName( Kernel.class, null ), null ) );
}
catch ( IOException e )
{
throw new IllegalStateException( "Connection failed.", e );
}
}
public static Neo4jManager get( MBeanServerConnection server, String kernelIdentifier )
{
server.getClass();
kernelIdentifier.getClass();
try
{
return get( server, server.queryNames( getObjectName( Kernel.class, kernelIdentifier ),
null ) );
}
catch ( IOException e )
{
throw new IllegalStateException( "Connection failed.", e );
}
}
public static Neo4jManager[] getAll( MBeanServerConnection server )
{
try
{
Set<ObjectName> kernels = server.queryNames( getObjectName( Kernel.class, null ), null );
Neo4jManager[] managers = new Neo4jManager[kernels.size()];
Iterator<ObjectName> it = kernels.iterator();
for ( int i = 0; i < managers.length; i++ )
{
managers[i] = new Neo4jManager( server, proxy( server, Kernel.class, it.next() ) );
}
return managers;
}
catch ( IOException e )
{
throw new IllegalStateException( "Connection failed.", e );
}
}
private static Neo4jManager get( MBeanServerConnection server, Collection<ObjectName> kernels )
{
if ( kernels.size() == 0 )
{
throw new NoSuchElementException( "No matching Neo4j Graph Database running on server" );
}
else if ( kernels.size() == 1 )
{
return new Neo4jManager( server,
proxy( server, Kernel.class, kernels.iterator().next() ) );
}
else
{
throw new NoSuchElementException(
"Too many matching Neo4j Graph Databases running on server" );
}
}
private final ObjectName config;
public Neo4jManager( Kernel kernel )
{
this( getServer( kernel ), actual( kernel ) );
}
private static MBeanServerConnection getServer( Kernel kernel )
{
if ( kernel instanceof Proxy )
{
InvocationHandler handler = Proxy.getInvocationHandler( kernel );
if ( handler instanceof MBeanServerInvocationHandler )
{
return ( (MBeanServerInvocationHandler) handler ).getMBeanServerConnection();
}
}
else if ( kernel instanceof Neo4jManager )
{
return ( (Neo4jManager) kernel ).server;
}
throw new UnsupportedOperationException( "Cannot get server for kernel: " + kernel );
}
private static Kernel actual( Kernel kernel )
{
return kernel instanceof Neo4jManager ? ( (Neo4jManager) kernel ).kernel : kernel;
}
private Neo4jManager( MBeanServerConnection server, Kernel kernel )
{
super( server, kernel );
this.config = getObjectName( ConfigurationBean.CONFIGURATION_MBEAN_NAME );
}
public Cache getCacheBean()
{
return getBean( Cache.class );
}
public LockManager getLockManagerBean()
{
return getBean( LockManager.class );
}
public MemoryMapping getMemoryMappingBean()
{
return getBean( MemoryMapping.class );
}
public Primitives getPrimitivesBean()
{
return getBean( Primitives.class );
}
public StoreFile getStoreFileBean()
{
return getBean( StoreFile.class );
}
public TransactionManager getTransactionManagerBean()
{
return getBean( TransactionManager.class );
}
public XaManager getXaManagerBean()
{
return getBean( XaManager.class );
}
public Object getConfigurationParameter( String key )
{
try
{
return server.getAttribute( config, key );
}
catch ( AttributeNotFoundException e )
{
return null;
}
catch ( Exception e )
{
throw new IllegalStateException( "Could not access the configuration bean", e );
}
}
public Map<String, Object> getConfiguration()
{
final String[] keys;
final AttributeList attributes;
try
{
MBeanAttributeInfo[] keyInfo = server.getMBeanInfo( config ).getAttributes();
keys = new String[keyInfo.length];
for ( int i = 0; i < keys.length; i++ )
{
keys[i] = keyInfo[i].getName();
}
attributes = server.getAttributes( config, keys );
}
catch ( Exception e )
{
throw new IllegalStateException( "Could not access the configuration bean", e );
}
Map<String, Object> configuration = new HashMap<String, Object>();
for ( int i = 0; i < keys.length; i++ )
{
configuration.put( keys[i], attributes.get( i ) );
}
return configuration;
}
@Override
public <T> T getBean( Class<T> beanInterface )
{
return super.getBean( beanInterface );
}
public Date getKernelStartTime()
{
return kernel.getKernelStartTime();
}
public String getKernelVersion()
{
return kernel.getKernelVersion();
}
public ObjectName getMBeanQuery()
{
return kernel.getMBeanQuery();
}
public Date getStoreCreationDate()
{
return kernel.getStoreCreationDate();
}
public String getStoreDirectory()
{
return kernel.getStoreDirectory();
}
public String getStoreId()
{
return kernel.getStoreId();
}
public long getStoreLogVersion()
{
return kernel.getStoreLogVersion();
}
public boolean isReadOnly()
{
return kernel.isReadOnly();
}
public static JMXServiceURL getConnectionURL( KernelData kernel )
{
return KernelProxy.getConnectionURL( kernel );
}
}