blob: f746ce19a1b07fd89baf189a25ac389d8d5c3f8b [file] [log] [blame]
package brooklyn.entity.database.derby
import java.util.Collection
import java.util.Map
import javax.management.InstanceNotFoundException
import javax.management.ObjectName
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import brooklyn.entity.Entity
import brooklyn.entity.basic.AbstractEntity
import brooklyn.entity.basic.Attributes
import brooklyn.entity.basic.legacy.JavaApp
import brooklyn.entity.basic.lifecycle.legacy.SshBasedAppSetup
import brooklyn.entity.database.Database
import brooklyn.entity.database.Schema
import brooklyn.event.adapter.SensorRegistry
import brooklyn.event.adapter.legacy.OldJmxSensorAdapter
import brooklyn.event.adapter.legacy.ValueProvider
import brooklyn.event.basic.BasicAttributeSensor
import brooklyn.event.basic.BasicConfigKey
import brooklyn.location.PortRange
import brooklyn.location.basic.SshMachineLocation
import com.google.common.base.Preconditions
/**
* An {@link Entity} that represents a single Derby SQL database server instance.
*
* TODO work in progress
*/
public class DerbyDatabase extends JavaApp implements Database {
private static final Logger log = LoggerFactory.getLogger(DerbyDatabase.class)
public static final BasicConfigKey<PortRange> SUGGESTED_JDBC_PORT = [PortRange, "derby.jdbcPort", "Suggested JDBC port" ]
public static final BasicConfigKey<String> VIRTUAL_HOST_NAME = [String, "derby.virtualHost", "Derby virtual host name" ]
public static final BasicAttributeSensor<Integer> JDBC_PORT = [ Integer, "jdbc.port", "JDBC port" ]
String virtualHost
Collection<String> schemaNames = []
Map<String, DerbySchema> schemas = [:]
public DerbyDatabase(Map properties=[:]) {
super(properties)
virtualHost = getConfig(VIRTUAL_HOST_NAME) ?: properties.virtualHost ?: "localhost"
setConfig(VIRTUAL_HOST_NAME, virtualHost)
setAttribute(Attributes.JMX_USER, properties.user ?: "admin")
setAttribute(Attributes.JMX_PASSWORD, properties.password ?: "admin")
if (properties.schema) schemaNames.add properties.schema
if (properties.schemas) schemaNames.addAll properties.schemas
}
public SshBasedAppSetup newDriver(SshMachineLocation machine) {
return DerbySetup.newInstance(this, machine)
}
public void connectSensors() {
super.connectSensors()
sensorRegistry.addSensor(JavaApp.SERVICE_UP, { computeNodeUp() } as ValueProvider)
}
@Override
public void postStart() {
super.postStart()
schemaNames.each { String name -> createSchema(name) }
}
@Override
public void preStop() {
super.preStop()
schemas.each { String name, DerbySchema schema -> schema.destroy() }
}
public void createSchema(String name, Map properties=[:]) {
properties.owner = this
properties.name = name
schemas.put name, new DerbySchema(properties)
}
public Collection<Schema> getSchemas() {
return schemas.values()
}
public void addSchema(Schema schema) {
schemas.put schema.name, schema
}
public void removeSchema(String schemaName) {
schemas.remove(schemaName)
}
@Override
public Collection<String> toStringFieldsToInclude() {
return super.toStringFieldsToInclude() + ['jdbcPort']
}
protected boolean computeNodeUp() {
ValueProvider<String> provider = jmxAdapter.newAttributeProvider("org.apache.derby:type=ServerInformation,name=ServerInformation", "ProductVersion")
try {
String productVersion = provider.compute()
return (productVersion == getAttribute(Attributes.VERSION))
} catch (InstanceNotFoundException infe) {
return false
}
}
}
public class DerbySchema extends AbstractEntity implements Schema {
String virtualHost
String name
protected ObjectName virtualHostManager
protected ObjectName exchange
transient OldJmxSensorAdapter jmxAdapter
transient SensorRegistry sensorRegistry
public DerbySchema(Map properties=[:], Entity owner=null) {
super(properties, owner)
Preconditions.checkNotNull properties.name, "Name must be specified"
name = properties.name
virtualHost = getConfig(DerbyDatabase.VIRTUAL_HOST_NAME) ?: properties.virtualHost ?: "localhost"
setConfig(DerbyDatabase.VIRTUAL_HOST_NAME, virtualHost)
virtualHostManager = new ObjectName("org.apache.derby:type=VirtualHost.VirtualHostManager,VirtualHost=\"${virtualHost}\"")
init()
jmxAdapter = ((DerbyDatabase) this.owner).jmxAdapter
sensorRegistry = new SensorRegistry(this)
create()
}
public void init() {
setConfig SCHEMA_NAME, name
exchange = new ObjectName("org.apache.derby:type=VirtualHost.Exchange,VirtualHost=\"${virtualHost}\",name=\"amq.direct\",ExchangeType=direct")
}
public void addJmxSensors() {
String schema = "org.apache.derby:type=VirtualHost.Schema,VirtualHost=\"${virtualHost}\",name=\"${name}\""
sensorRegistry.addSensor(SCHEMA_DEPTH, jmxAdapter.newAttributeProvider(schema, "SchemaDepth"))
sensorRegistry.addSensor(MESSAGE_COUNT, jmxAdapter.newAttributeProvider(schema, "MessageCount"))
}
public void removeJmxSensors() {
String schema = "org.apache.derby:type=VirtualHost.Schema,VirtualHost=\"${virtualHost}\",name=\"${name}\""
sensorRegistry.removeSensor(SCHEMA_DEPTH)
sensorRegistry.removeSensor(MESSAGE_COUNT)
}
public void create() {
jmxAdapter.operation(virtualHostManager, "createNewSchema", name, owner.getAttribute(Attributes.JMX_USER), true)
jmxAdapter.operation(exchange, "createNewBinding", name, name)
addJmxSensors()
}
public void load() {
jmxAdapter.operation(exchange, "removeBinding", name, name)
jmxAdapter.operation(virtualHostManager, "deleteSchema", name)
removeJmxSensors()
}
/**
* Return the JDBC connection URL for the schema.
*/
public String getConnectionUrl() { return String.format("jdbc:derby:%s", name) }
@Override
public void destroy() {
sensorRegistry.close()
super.destroy()
}
@Override
public Collection<String> toStringFieldsToInclude() {
return super.toStringFieldsToInclude() + ['name']
}
}