/*******************************************************************************
* Copyright (c) 2008 Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* File: $Source$
* Created by: Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
* Created on: Jul 14, 2008
* Revision: $Id$
*
* Contributors:
* Cambridge Semantics Incorporated - initial API and implementation
*******************************************************************************/
package org.openanzo.datasource.services;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.StringTokenizer;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.openanzo.datasource.DatasourceDictionary;
import org.openanzo.datasource.IAuthorizationService;
import org.openanzo.datasource.IDatasource;
import org.openanzo.datasource.IDatasourceListener;
import org.openanzo.datasource.IIndexService;
import org.openanzo.datasource.IModelService;
import org.openanzo.datasource.IQueryService;
import org.openanzo.datasource.IReplicationService;
import org.openanzo.datasource.IResetService;
import org.openanzo.datasource.IServerQuadStoreProvider;
import org.openanzo.datasource.IUpdateService;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.LogUtils;
import org.openanzo.ontologies.system.Datasource;
import org.openanzo.ontologies.system.SystemFactory;
import org.openanzo.rdf.Constants;
import org.openanzo.rdf.IDataset;
import org.openanzo.rdf.INamedGraph;
import org.openanzo.rdf.NamedGraph;
import org.openanzo.rdf.URI;
import org.openanzo.services.IStatisticsProvider;
import org.openanzo.services.ServicesDictionary;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base datasource
*
* @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com</a>)
*
*/
abstract public class BaseDatasource implements IDatasource {
protected static final Logger log = LoggerFactory.getLogger(BaseDatasource.class);
protected org.openanzo.rdf.INamedGraph capabilities;
protected final CopyOnWriteArrayList<IDatasourceListener> listeners = new CopyOnWriteArrayList<IDatasourceListener>();
protected URI instanceURI;
protected Collection<String> uriPatterns;
protected boolean isPrimary = false;
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
protected final ArrayList<ServiceRegistration> serviceRegistrations = new ArrayList<ServiceRegistration>();
protected boolean enableCaching = true;
protected boolean resetEnabled = false;
/**
* Create base datasource with given instance uri
*
* @param instanceURI
* instanceuri for datasource
* @param isPrimary
* is this the primary datasource
*/
public BaseDatasource(URI instanceURI, boolean isPrimary, Collection<String> uriPatterns, boolean enableCaching, boolean resetEnabled) {
constructor(instanceURI, isPrimary, uriPatterns, enableCaching, resetEnabled);
}
/**
* Create base datasource based on configuration properties
*
* @param configProperties
* the configuration properties for the datasource
*/
public BaseDatasource(Dictionary<? extends Object, ? extends Object> configProperties) {
String iu = ServicesDictionary.getInstanceURI(configProperties);
Boolean isPrimary = DatasourceDictionary.getIsPrimary(configProperties);
Boolean ec = DatasourceDictionary.getEnableCaching(configProperties, true);
Boolean resetEnabledObj = DatasourceDictionary.getResetEnabled(configProperties);
Collection<String> patterns = new ArrayList<String>();
String patternString = DatasourceDictionary.getUriPatterns(configProperties);
if (patternString != null) {
StringTokenizer st = new StringTokenizer(patternString, ",");
while (st.hasMoreElements()) {
String pattern = st.nextToken();
patterns.add(pattern);
}
}
constructor(iu != null ? Constants.valueFactory.createURI(iu) : null, isPrimary != null ? isPrimary : false, patterns, ec != null ? ec.booleanValue() : true, resetEnabledObj != null ? resetEnabledObj.booleanValue() : false);
}
/**
*
*/
public BaseDatasource() {
}
protected void constructor(URI instanceURI, boolean isPrimary, Collection<String> uriPatterns, boolean enableCaching, boolean resetEnabled) {
this.instanceURI = instanceURI;
this.isPrimary = isPrimary;
this.enableCaching = enableCaching;
this.resetEnabled = resetEnabled;
this.uriPatterns = uriPatterns;
}
public boolean isPrimary() {
return isPrimary;
}
/**
* Setup the capabilities graph based on the configuration properties
*/
public void setupCapabilities() {
if (capabilities == null) {
capabilities = new NamedGraph(getInstanceURI());
Datasource datasource = SystemFactory.createDatasource(getInstanceURI(), capabilities);
datasource.setIsPrimary(isPrimary());
for (String pattern : uriPatterns) {
datasource.addUriPattern(pattern);
}
}
}
public URI getInstanceURI() {
return instanceURI;
}
public void registerDatasourceListener(IDatasourceListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
public void unregisterDatasourceListener(IDatasourceListener listener) {
listeners.remove(listener);
}
/**
* Notify the listeners that reset is starting
*/
public void resetStarting() {
for (IDatasourceListener listener : listeners) {
try {
listener.resetStarting();
} catch (Throwable t) {
log.error(LogUtils.SERVER_INTERNAL_MARKER, "Error in listener's reset starting", t);
}
}
}
/**
* Notify the listeners to do their reset code
*/
public void reset() {
for (IDatasourceListener listener : listeners) {
try {
listener.reset();
} catch (Throwable t) {
log.error(LogUtils.SERVER_INTERNAL_MARKER, "Error in listener's reset", t);
}
}
}
/**
* Notify the listeners that reset is finished
*/
public void postReset() {
for (IDatasourceListener listener : listeners) {
try {
listener.postReset();
} catch (Throwable t) {
log.error(LogUtils.SERVER_INTERNAL_MARKER, "Error in listener's post reset", t);
}
}
}
/**
* Notify the listeners that reset is finished
*/
public void resetFinished() {
for (IDatasourceListener listener : listeners) {
try {
listener.resetFinished();
} catch (Throwable t) {
log.error(LogUtils.SERVER_INTERNAL_MARKER, "Error in listener's reset finished", t);
}
}
}
public INamedGraph getCapabilities() {
return capabilities;
}
@SuppressWarnings("unchecked")
public <ServiceType> ServiceType getService(Class<ServiceType> clazz) {
if (clazz.equals(IAuthorizationService.class)) {
return (ServiceType) getAuthorizationService();
} else if (clazz.equals(IModelService.class)) {
return (ServiceType) getModelService();
} else if (clazz.equals(IUpdateService.class)) {
return (ServiceType) getUpdateService();
} else if (clazz.equals(IReplicationService.class)) {
return (ServiceType) getReplicationService();
} else if (clazz.equals(IResetService.class)) {
return (ServiceType) getResetService();
} else if (clazz.equals(IQueryService.class)) {
return (ServiceType) getQueryService();
} else if (clazz.equals(IIndexService.class)) {
return (ServiceType) getIndexService();
} else if (clazz.equals(IServerQuadStoreProvider.class)) {
return (ServiceType) getServerQuadStoreProvider();
} else {
throw new RuntimeException("Unknown service type requested");
}
}
public ReentrantReadWriteLock getLockProvider() {
return lock;
}
/**
* Setup the statistics objects and register with OSGI
*
* @param context
* bundlecontex for datasource
*/
public void setupStats(BundleContext context) {
if (getModelService() != null) {
serviceRegistrations.add(context.registerService(IStatisticsProvider.class.getName(), getModelService(), null));
}
if (getUpdateService() != null) {
serviceRegistrations.add(context.registerService(IStatisticsProvider.class.getName(), getUpdateService(), null));
}
if (getResetService() != null) {
serviceRegistrations.add(context.registerService(IStatisticsProvider.class.getName(), getResetService(), null));
}
if (getReplicationService() != null) {
serviceRegistrations.add(context.registerService(IStatisticsProvider.class.getName(), getReplicationService(), null));
}
if (getIndexService() != null) {
serviceRegistrations.add(context.registerService(IStatisticsProvider.class.getName(), getIndexService(), null));
}
if (getAuthorizationService() != null) {
serviceRegistrations.add(context.registerService(IStatisticsProvider.class.getName(), getAuthorizationService(), null));
}
if (getQueryService() != null) {
serviceRegistrations.add(context.registerService(IStatisticsProvider.class.getName(), getQueryService(), null));
}
}
/**
* Unregister the stats objects
*/
public void cleanupStats() {
for (ServiceRegistration serviceReg : serviceRegistrations) {
serviceReg.unregister();
}
serviceRegistrations.clear();
}
protected static String generateDatasourceName(String name, URI instanceUri) {
try {
return "Datasource=" + name + "_" + URLEncoder.encode(instanceUri.toString(), Constants.byteEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("This should never happen since UTF-8 is always supported");
}
}
public void executeCommand(String command, IDataset request, IDataset response) throws AnzoException {
}
}