Java tutorial
/******************************************************************************* * Copyright (c) 2010 Bryan Hunt & Ed Merks. * 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 * * Contributors: * Bryan Hunt & Ed Merks - initial API and implementation *******************************************************************************/ package org.eclipselabs.mongoemf.handlers; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.impl.URIHandlerImpl; import org.eclipselabs.emongo.MongoDatabaseProvider; import org.eclipselabs.mongoemf.InputStreamFactory; import org.eclipselabs.mongoemf.Keywords; import org.eclipselabs.mongoemf.MongoUtils; import org.eclipselabs.mongoemf.Options; import org.eclipselabs.mongoemf.OutputStreamFactory; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.ReadPreference; /** * This EMF URI handler interfaces to MongoDB. This URI handler can handle URIs with the "mongodb" * scheme. The URI path must have exactly 3 segments and be of the form /database/collection/{id} * where id is optional the first time the EMF object is saved. When building queries, do not * specify an id, but make sure path has 3 segments by placing a "/" after the collection. * * Note that if the id is not specified when the object is first saved, MongoDB will assign the id * and the URI of the EMF Resource will be modified to include the id in the URI. Examples of valid * URIs: * * mongodb://localhost/data/people/ * mongodb://localhost/data/people/4d0a3e259095b5b334a59df0 * * This class is intended to be used with the IResourceSetFactory service. If you are not using the * factory service, you will have to supply instances of IMongoLocator, IIntputStreamFActory, and * IOutputStreamFactory. * * @author bhunt * */ public class MongoURIHandlerImpl extends URIHandlerImpl { /** * * @param databaseLocator an instance of the mongo locator service * @param inputStreamFactory an instance of the input stream factory service * @param outputStreamFactory an instance of the output stream factory service */ public MongoURIHandlerImpl(Map<String, MongoDatabaseProvider> mongoDatabaseProviders, InputStreamFactory inputStreamFactory, OutputStreamFactory outputStreamFactory) { this.mongoDatabaseProviders = mongoDatabaseProviders; this.inputStreamFactory = inputStreamFactory; this.outputStreamFactory = outputStreamFactory; } @Override public boolean canHandle(URI uri) { // This handler should only accept URIs with the scheme "mongodb" return "mongodb".equalsIgnoreCase(uri.scheme()); } @Override public OutputStream createOutputStream(final URI uri, final Map<?, ?> options) throws IOException { // This function may be called with a URI path with or without an id. If an id is not specified // the EMF resource URI will be modified to include the id generated by MongoDB. return outputStreamFactory.createOutputStream(uri, options, getCollection(uri, options), getResponse(options)); } @Override public InputStream createInputStream(final URI uri, final Map<?, ?> options) throws IOException { return inputStreamFactory.createInputStream(uri, options, getCollection(uri, options), getResponse(options)); } @Override public void delete(URI uri, Map<?, ?> options) throws IOException { // It is assumed that delete is called with the URI path /database/collection/id DBCollection collection = getCollection(uri, options); collection.findAndRemove(new BasicDBObject(Keywords.ID_KEY, MongoUtils.getID(uri))); } @Override public boolean exists(URI uri, Map<?, ?> options) { if (uri.query() != null) return false; try { DBCollection collection = getCollection(uri, options); return collection.findOne(new BasicDBObject(Keywords.ID_KEY, MongoUtils.getID(uri))) != null; } catch (Throwable exception) { return false; } } /** * This function locates the MongoDB collection instance corresponding to the collection * identifier extracted from the URI. The URI path must have exactly 3 segments and be of the form * mongodb://host:[port]/database/collection/{id} where id is optional. * * @param uri the MongoDB collection identifier * @param options the load or save options as appropriate * @return the MongoDB collection corresponding to the URI * @throws IOException if the URI is malformed or the collection could not otherwise be resolved */ private DBCollection getCollection(URI uri, Map<?, ?> options) throws IOException { // We assume that the URI path has the form /database/collection/{id} making the // collection segment # 1. if (uri.segmentCount() != 3) throw new IOException("The URI is not of the form 'mongodb:/database/collection/{id}"); MongoDatabaseProvider mongoDatabaseProvider = mongoDatabaseProviders .get(uri.trimQuery().trimFragment().trimSegments(2).toString()); if (mongoDatabaseProvider == null) throw new IOException("Database is not available"); DB database = mongoDatabaseProvider.getDB(); if (database == null) throw new IOException("Database is not available"); DBCollection dbCollection = database.getCollection(uri.segment(1)); ReadPreference readPreference = (ReadPreference) options.get(Options.OPTION_READ_PREFERENCE); if (readPreference != null) dbCollection.setReadPreference(readPreference); return dbCollection; } private Map<String, MongoDatabaseProvider> mongoDatabaseProviders; private InputStreamFactory inputStreamFactory; private OutputStreamFactory outputStreamFactory; }