/*******************************************************************************
* Copyright (c) 2012 IBM Corporation.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v. 1.0 which accompanies this distribution.
*
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
*
* Samuel Padgett - initial API and implementation
* Michael Fiedler - updates to use Jena TDB instead of Derby
*******************************************************************************/
package org.eclipse.lyo.server.oauth.consumerstore;
import org.apache.log4j.Logger;
import org.eclipse.lyo.server.oauth.core.consumer.AbstractConsumerStore;
import org.eclipse.lyo.server.oauth.core.consumer.ConsumerStoreException;
import org.eclipse.lyo.server.oauth.core.consumer.LyoOAuthConsumer;
import com.hp.hpl.jena.tdb.TDBFactory;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ResIterator;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.shared.Command;
import com.hp.hpl.jena.shared.JenaException;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.shared.PropertyNotFoundException;
import com.hp.hpl.jena.vocabulary.RDF;
/**
* A simple RDF consumer store backed by a Jena TDB native datastore
**/
public class RdfConsumerStore extends AbstractConsumerStore {
protected final static String LYO_OAUTH_NAMESPACE = "http://eclipse.org/lyo/server/oauth#";
protected final static String CONSUMER_RESOURCE = LYO_OAUTH_NAMESPACE
+ "Consumer";
protected final static String CALLBACK_URL = LYO_OAUTH_NAMESPACE
+ "callback";
protected final static String CONSUMER_NAME = LYO_OAUTH_NAMESPACE
+ "consumerName";
protected final static String CONSUMER_KEY = LYO_OAUTH_NAMESPACE
+ "consumerKey";
protected final static String CONSUMER_SECRET = LYO_OAUTH_NAMESPACE
+ "consumerSecret";
protected final static String PROVISIONAL = LYO_OAUTH_NAMESPACE
+ "provisional";
protected final static String TRUSTED = LYO_OAUTH_NAMESPACE + "trusted";
protected final static String DB = "RDFStore"; // database type
private Logger logger = Logger.getLogger(RdfConsumerStore.class);
private Model model;
private Dataset dataset;
public RdfConsumerStore() throws ConsumerStoreException,
ClassNotFoundException {
createDataset();
if (this.dataset != null) {
createModel(this.dataset);
loadConsumers();
}
}
public RdfConsumerStore(Dataset dataset) throws ConsumerStoreException {
this.dataset = dataset;
createModel(this.dataset);
loadConsumers();
}
public RdfConsumerStore(Model model) throws ConsumerStoreException {
createDataset();
if (this.dataset != null) {
this.model = model;
dataset.setDefaultModel(this.model);
loadConsumers();
}
}
protected void createDataset() {
try {
this.dataset = TDBFactory.createDataset(DB);
} catch (Exception e) {
logger.error("Could not create dataset for OAuth consumer store.", e);
}
}
protected void createModel(Dataset dataset) {
try {
this.model = dataset.getDefaultModel();
} catch (Exception e) {
logger.error("Could not create model for OAuth consumer store.", e);
}
}
protected void loadConsumers() throws ConsumerStoreException {
try {
model.enterCriticalSection(Lock.READ);
ResIterator i = model.listResourcesWithProperty(RDF.type,
model.createResource(CONSUMER_RESOURCE));
while (i.hasNext()) {
Resource consumerResource = i.next();
try {
add(fromResource(consumerResource));
} catch (PropertyNotFoundException e) {
// The resource is missing some properties.
// Not good, but other consumer resources might
// be OK, so continue. (Log the error, though.)
logger.error(
"Could not load consumer "
+ consumerResource.getProperty(model
.createProperty(CONSUMER_NAME))
+ " ("
+ consumerResource.getProperty(model
.createProperty(CONSUMER_KEY))
+ ")", e);
} catch (JenaException e) {
// Some other runtime exception occurred.
throw new ConsumerStoreException(e);
}
}
} finally {
model.leaveCriticalSection();
}
}
@Override
public LyoOAuthConsumer addConsumer(final LyoOAuthConsumer consumer)
throws ConsumerStoreException {
if (model == null) {
throw new ConsumerStoreException("Consumer store not initialized.");
}
try {
model.enterCriticalSection(Lock.WRITE);
model.executeInTransaction(new Command() {
@Override
public Object execute() {
removeProperties(consumer);
toResource(consumer);
return consumer;
}
});
return add(consumer);
} catch (JenaException e) {
throw new ConsumerStoreException(e);
} finally {
model.leaveCriticalSection();
}
}
@Override
public LyoOAuthConsumer removeConsumer(final String consumerKey)
throws ConsumerStoreException {
if (model == null) {
throw new ConsumerStoreException("Consumer store not initialized.");
}
try {
model.enterCriticalSection(Lock.WRITE);
model.executeInTransaction(new Command() {
@Override
public Object execute() {
removeProperties(consumerKey);
return consumerKey;
}
});
return remove(consumerKey);
} catch (JenaException e) {
throw new ConsumerStoreException(e);
} finally {
model.leaveCriticalSection();
}
}
@Override
public LyoOAuthConsumer updateConsumer(LyoOAuthConsumer consumer)
throws ConsumerStoreException {
// addConsumer() also works for update.
return addConsumer(consumer);
}
@Override
public void closeConsumerStore() {
if (this.model != null) {
model.close();
}
if (this.dataset != null) {
dataset.close();
}
}
/**
* Removes any properties previously associated with the consumer.
*
* @param consumerKey
* the consumer key
*/
protected void removeProperties(String consumerKey) {
ResIterator i = model.listResourcesWithProperty(
model.createProperty(CONSUMER_KEY),
model.createLiteral(consumerKey));
while (i.hasNext()) {
i.next().removeProperties();
}
}
/**
* Removes any properties previously associated with the consumer.
*
* @param consumer the consumer
*/
protected void removeProperties(LyoOAuthConsumer consumer) {
removeProperties(consumer.consumerKey);
}
protected Resource toResource(LyoOAuthConsumer consumer) {
Resource resource = model.createResource();
resource.addProperty(RDF.type, model.createResource(CONSUMER_RESOURCE));
resource.addProperty(model.createProperty(CONSUMER_NAME),
consumer.getName());
resource.addProperty(model.createProperty(CONSUMER_KEY),
consumer.consumerKey);
resource.addProperty(model.createProperty(CONSUMER_SECRET),
consumer.consumerSecret);
resource.addProperty(model.createProperty(PROVISIONAL),
(consumer.isProvisional()) ? "true" : "false");
resource.addProperty(model.createProperty(TRUSTED),
(consumer.isTrusted()) ? "true" : "false");
return resource;
}
protected LyoOAuthConsumer fromResource(Resource resource) {
String key = resource.getRequiredProperty(
model.createProperty(CONSUMER_KEY)).getString();
String secret = resource.getRequiredProperty(
model.createProperty(CONSUMER_SECRET)).getString();
LyoOAuthConsumer consumer = new LyoOAuthConsumer(key, secret);
consumer.setName(resource.getRequiredProperty(
model.createProperty(CONSUMER_NAME)).getString());
String provisional = resource.getProperty(
model.createProperty(PROVISIONAL)).getString();
consumer.setProvisional("true".equals(provisional));
String trusted = resource.getProperty(model.createProperty(TRUSTED))
.getString();
consumer.setTrusted("true".equals(trusted));
return consumer;
}
}