/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and 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: /cvsroot/slrp/glitter/com.ibm.adtech.glitter/src/com/ibm/adtech/glitter/dataset/HTTPStreamingDataset.java,v $ * Created by: Lee Feigenbaum ( <a href="mailto:feigenbl@us.ibm.com">feigenbl@us.ibm.com </a>) * Created on: 10/23/2006 * Revision: $Id: HTTPStreamingDataset.java 164 2007-07-31 14:11:09Z mroy $ * * Contributors: * IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.glitter.dataset; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.openanzo.analysis.RequestAnalysis; import org.openanzo.exceptions.LogUtils; import org.openanzo.glitter.exception.UnknownGraphException; import org.openanzo.rdf.URI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This is the default implementation of an RDF dataset in Glitter. It retrieves all of the graphs via HTTP GET and returns them as byte-oriented InputStreams. * It's up to the consumer to parse the graphs, and as such, this will only be useful in limited cases. * * @author Lee * */ public class HTTPStreamingDataset extends QueryDataset { private static final Logger log = LoggerFactory.getLogger(HTTPStreamingDataset.class); static private final int MAX_THREADS = 6; private Map<URI, Future<InputStream>> defaultGraphs, namedGraphs; private ExecutorService threads; /** * Default constructor. */ public HTTPStreamingDataset() { this.defaultGraphs = new Hashtable<URI, Future<InputStream>>(); this.namedGraphs = new Hashtable<URI, Future<InputStream>>(); this.threads = Executors.newFixedThreadPool(MAX_THREADS); } static private class GraphRetriever implements Callable<InputStream> { private URI graph; protected GraphRetriever(URI graph) { this.graph = graph; } public InputStream call() throws IOException { return java.net.URI.create(this.graph.toString()).toURL().openStream(); } } private boolean retrieveGraph(URI name, Map<URI, Future<InputStream>> destination) { if (destination.containsKey(name)) return false; // not actually retrieving anything destination.put(name, this.threads.submit(new GraphRetriever(name))); return true; } public void addDefaultGraph(URI name) { retrieveGraph(name, this.defaultGraphs); } public void addNamedGraph(URI name) { retrieveGraph(name, this.namedGraphs); } public void setDefaultGraphs(Set<URI> graphs) { this.defaultGraphs = new Hashtable<URI, Future<InputStream>>(); for (URI u : graphs) addDefaultGraph(u); } public void setNamedGraphs(Set<URI> graphs) { this.namedGraphs = new Hashtable<URI, Future<InputStream>>(); for (URI u : graphs) addNamedGraph(u); } protected InputStream getGraph(URI name, Map<URI, Future<InputStream>> map) throws UnknownGraphException { Future<InputStream> content = map.get(name); if (content == null) throw new UnknownGraphException(name); try { return content.get(); // if necessary, waits for the thread to return } catch (InterruptedException e) { // TODO log in case we start going loop-the-loop here return getGraph(name, map); } catch (ExecutionException e) { throw new RuntimeException(e.getCause()); } } public InputStream getDefaultGraph(URI name) throws UnknownGraphException { return getGraph(name, this.defaultGraphs); } public InputStream getNamedGraph(URI name) throws UnknownGraphException { return getGraph(name, this.namedGraphs); } @Override public Set<URI> getDefaultGraphURIs() { return getNameIterator(this.defaultGraphs); } @Override public Set<URI> getNamedGraphURIs() { return getNameIterator(this.namedGraphs); } private Set<URI> getNameIterator(Map<URI, Future<InputStream>> graphs) { Set<URI> uris = new HashSet<URI>(); for (Iterator<URI> iter = graphs.keySet().iterator(); iter.hasNext();) { uris.add(iter.next()); } return uris; } @Override public Set<URI> getNamedDatasetURIs() { return null; } @Override public boolean isEmpty() { return (defaultGraphs == null || defaultGraphs.size() == 0) && (namedGraphs == null || namedGraphs.size() == 0); } @Override public String getCacheString() { long start = 0; boolean isEnabled = RequestAnalysis.getAnalysisLogger().isDebugEnabled(); if (log.isDebugEnabled() || isEnabled) { start = System.currentTimeMillis(); } try { StringBuilder sb = new StringBuilder(); sb.append('['); for (URI g : getDefaultGraphURIs()) { sb.append(g.getNamespace()); sb.append(g.getLocalName()); sb.append(','); } sb.append(']'); sb.append(':'); sb.append('['); for (URI g : getNamedGraphURIs()) { sb.append(g.getNamespace()); sb.append(g.getLocalName()); sb.append(','); } sb.append(']'); return sb.toString(); } finally { if (log.isDebugEnabled() || isEnabled) { if (log.isDebugEnabled()) { long end = System.currentTimeMillis(); log.debug(LogUtils.DATASOURCE_MARKER, "CreateQueryString time: " + (end - start)); } if (isEnabled) { RequestAnalysis.getAnalysisLogger().debug(LogUtils.TIMING_MARKER, "glitter_queryCacheCreateString,{}", Long.toString(System.currentTimeMillis() - start)); } start = System.currentTimeMillis(); } } } }