You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@clerezza.apache.org by re...@apache.org on 2010/08/27 22:39:04 UTC

svn commit: r990257 - in /incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/clerezza/ src/main/java/o...

Author: reto
Date: Fri Aug 27 20:39:03 2010
New Revision: 990257

URL: http://svn.apache.org/viewvc?rev=990257&view=rev
Log:
CLEREZZA-286: externalizing provider

Added:
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/   (with props)
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/pom.xml
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingMGraph.java
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingProvider.java
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/resources/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/resources/META-INF/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/resources/META-INF/services/
    incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider

Propchange: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Aug 27 20:39:03 2010
@@ -0,0 +1 @@
+target

Added: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/pom.xml
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/pom.xml?rev=990257&view=auto
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/pom.xml (added)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/pom.xml Fri Aug 27 20:39:03 2010
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<artifactId>org.apache.clerezza.parent</artifactId>
+		<groupId>org.apache.clerezza</groupId>
+		<version>0.2-incubating-SNAPSHOT</version>
+	</parent>
+	<groupId>org.apache.clerezza</groupId>
+	<artifactId>org.apache.clerezza.rdf.storage.externalizer</artifactId>
+	<packaging>bundle</packaging>
+	<version>0.1-incubating-SNAPSHOT</version>
+	<name>Clerezza - SCB Literal Externalizing Storage Provider</name>
+	<description>A Storage Provider storing large literals to files before
+	and relying on another provider for storing triples.</description>
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>org.osgi.core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.osgi</groupId>
+			<artifactId>org.osgi.compendium</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.clerezza</groupId>
+			<artifactId>org.apache.clerezza.rdf.core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.apache.felix.scr.annotations</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-simple</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+</project>

Added: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingMGraph.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingMGraph.java?rev=990257&view=auto
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingMGraph.java (added)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingMGraph.java Fri Aug 27 20:39:03 2010
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.clerezza.rdf.storage.externalizer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Iterator;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.NonLiteral;
+import org.apache.clerezza.rdf.core.Resource;
+import org.apache.clerezza.rdf.core.Triple;
+import org.apache.clerezza.rdf.core.TypedLiteral;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.impl.AbstractMGraph;
+import org.apache.clerezza.rdf.core.impl.TripleImpl;
+import org.apache.clerezza.rdf.core.impl.TypedLiteralImpl;
+
+/**
+ *
+ * @author reto
+ */
+/*
+ * This could be optimized by not using the notification mechanism provided by
+ * AbstractMGraph but intercept the notifictification of the basegraph
+ */
+class ExternalizingMGraph extends AbstractMGraph {
+	private final MGraph baseGraph;
+	private final File dataDir;
+
+	private static final UriRef base64Uri =
+			new UriRef("http://www.w3.org/2001/XMLSchema#base64Binary");
+	//not using a nown uri-scheme (such as urn:hash) to avoid collission with Uris in the graph
+	private static final String UriHashPrefix = "urn:x-litrep:";
+	private static final Charset UTF8 = Charset.forName("utf-8");
+	private static final byte[] DELIMITER = "^^".getBytes(UTF8);
+
+	public ExternalizingMGraph(MGraph baseGraph, File dataDir) {
+		this.baseGraph = baseGraph;
+		this.dataDir = dataDir;
+		System.out.println("Created externalizing mgraph with dir: "+dataDir);
+	}
+
+	@Override
+	protected Iterator<Triple> performFilter(NonLiteral subject, UriRef predicate, Resource object) {
+		if (object != null) {
+			if (needsReplacing(object)) {
+				return replaceReferences(baseGraph.filter(subject, predicate, replace((TypedLiteral)object)));
+			} else {
+				return baseGraph.filter(subject, predicate, object);
+			}
+		} else {
+			return replaceReferences(baseGraph.filter(subject, predicate, object));
+		}
+	}
+
+	@Override
+	public int size() {
+		return baseGraph.size();
+	}
+
+	@Override
+	public boolean performAdd(Triple triple) {
+		return baseGraph.add(replaceWithReference(triple));
+	}
+
+	@Override
+	public boolean performRemove(Triple triple) {
+		return baseGraph.remove(replaceWithReference(triple));
+	}
+
+	private Triple replaceWithReference(Triple triple) {
+		Resource object = triple.getObject();
+		if (needsReplacing(object)) {
+			return new TripleImpl(triple.getSubject(), triple.getPredicate(),
+					replace((TypedLiteral)object));
+		} else {
+			return triple;
+		}
+	}
+
+	/**
+	 * this method defines which resources are too be replaced, the rest of the
+	 * code only assumes the resource to be replaced to be a typed literal.
+	 * 
+	 * @param object
+	 * @return
+	 */
+	private boolean needsReplacing(Resource object) {
+		if (object instanceof TypedLiteral) {
+			if (((TypedLiteral)object).getDataType().equals(base64Uri)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private UriRef replace(TypedLiteral literal) {
+		FileOutputStream out = null;
+		try {
+			final byte[] serializedLiteral = serializeLiteral(literal);
+			MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
+			digest.update(serializedLiteral);
+			byte[] hash = digest.digest();
+			String base16Hash = toBase16(hash);
+			File storingFile = getStoringFile(base16Hash);
+			out = new FileOutputStream(storingFile);
+			out.write(serializedLiteral);
+			return new UriRef(UriHashPrefix + base16Hash);
+		} catch (IOException ex) {
+			throw new RuntimeException(ex);
+		} catch (NoSuchAlgorithmException ex) {
+			throw new RuntimeException(ex);
+		} finally {
+			try {
+				out.close();
+			} catch (IOException ex) {
+				throw new RuntimeException(ex);
+			}
+		}
+	}
+
+	/**
+	 * the first bytes are the datatype-uri followed by trailing "^^", the rest
+	 * the lexical form. everything encoded as utf-8
+	 * @return
+	 */
+	private byte[] serializeLiteral(TypedLiteral literal) {
+		try {
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			byte[] uriBytes = literal.getDataType().getUnicodeString().getBytes(UTF8);
+			out.write(uriBytes);
+			out.write(DELIMITER);
+			out.write(literal.getLexicalForm().getBytes(UTF8));
+			return out.toByteArray();
+		} catch (IOException ex) {
+			throw new RuntimeException(ex);
+		}
+	}
+
+	private TypedLiteral parseLiteral(File file) {
+
+		try {
+			InputStream in = new FileInputStream(file);
+			try {
+				ByteArrayOutputStream typeWriter = new ByteArrayOutputStream();
+				int posInDelimiter = 0;
+				for (int ch = in.read(); ch != -1; ch = in.read()) {
+					if (ch != DELIMITER[posInDelimiter]) {
+						posInDelimiter++;
+						if (DELIMITER.length == posInDelimiter) {
+							break;
+						}
+					} else {
+						if (posInDelimiter > 0) {
+							typeWriter.write(DELIMITER, 0, posInDelimiter);
+							posInDelimiter = 0;
+						}
+						typeWriter.write(ch);
+					}
+				}
+				UriRef type = new UriRef(new String(typeWriter.toByteArray(), UTF8));
+				typeWriter = null;
+				ByteArrayOutputStream dataWriter = new ByteArrayOutputStream((int) file.length());
+				for (int ch = in.read(); ch != -1; ch = in.read()) {
+					dataWriter.write(ch);
+				}
+				String lexicalForm = new String(dataWriter.toByteArray(), UTF8);
+				return new TypedLiteralImpl(lexicalForm, type);
+			} finally {
+				in.close();
+			}
+		} catch (IOException ex) {
+			throw new RuntimeException(ex);
+		}
+
+	}
+
+	private String toBase16(byte[] bytes) {
+		StringBuilder sb = new StringBuilder();
+		for (byte b : bytes) {
+			if (b < 16) {
+				sb.append('0');
+			}
+			sb.append(Integer.toHexString(b));
+		}
+		return sb.toString();
+	}
+
+	private File getStoringFile(String base16Hash) {
+		File dir1 = new File(dataDir, base16Hash.substring(0,4));
+		File dir2 = new File(dir1, base16Hash.substring(4,8));
+		dir2.mkdirs();
+		return new File(dir2, base16Hash.substring(8));
+	}
+
+	private Iterator<Triple> replaceReferences(final Iterator<Triple> base) {
+		return new Iterator<Triple>() {
+
+			@Override
+			public boolean hasNext() {
+				return base.hasNext();
+			}
+
+			@Override
+			public Triple next() {
+				return replaceReference(base.next());
+			}
+
+			@Override
+			public void remove() {
+				base.remove();
+			}
+
+			private Triple replaceReference(Triple triple) {
+				Resource object = triple.getObject();
+				if (object instanceof UriRef) {
+					String uriString = ((UriRef)object).getUnicodeString();
+					if (uriString.startsWith(UriHashPrefix)) {
+						File file = getStoringFile(uriString.substring(UriHashPrefix.length()));
+						return new TripleImpl(triple.getSubject(), triple.getPredicate(),
+								parseLiteral(file));
+					}
+				}
+				return triple;
+			}
+		};
+	}
+}

Added: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingProvider.java
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingProvider.java?rev=990257&view=auto
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingProvider.java (added)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/java/org/apache/clerezza/rdf/storage/externalizer/ExternalizingProvider.java Fri Aug 27 20:39:03 2010
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.clerezza.rdf.storage.externalizer;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import org.apache.clerezza.rdf.core.Graph;
+import org.apache.clerezza.rdf.core.MGraph;
+import org.apache.clerezza.rdf.core.TripleCollection;
+import org.apache.clerezza.rdf.core.UriRef;
+import org.apache.clerezza.rdf.core.access.EntityAlreadyExistsException;
+import org.apache.clerezza.rdf.core.access.EntityUndeletableException;
+import org.apache.clerezza.rdf.core.access.NoSuchEntityException;
+import org.apache.clerezza.rdf.core.access.TcManager;
+import org.apache.clerezza.rdf.core.access.WeightedTcProvider;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link org.apache.clerezza.rdf.core.access.WeightedTcProvider} storing
+ * large literals to the filesystem and the triples (with references
+ * instead of the literals) to another TcProvider.
+ *
+ * @author reto
+ *
+ */
+@Component
+@Service(WeightedTcProvider.class)
+@Property(name = "weight", intValue = 500 )
+public class ExternalizingProvider implements WeightedTcProvider {
+
+	private static final String EXTERNALIZEDLITERALS_SUFFIX = "-externalizedliterals";
+	@Reference
+	private TcManager tcManager;
+	/**
+	 *	directory where all graphs are stored
+	 */
+	private static final String RELATIVE_DATA_PATH_NAME = "externalized-literals/";
+	private File dataPath;
+	private static final Logger log = LoggerFactory.getLogger(ExternalizingProvider.class);
+	private int weight = 500;
+
+	public ExternalizingProvider() {
+	}
+
+	ExternalizingProvider(File directory) {
+		dataPath = directory;
+		tcManager = TcManager.getInstance();
+	}
+
+	public void activate(ComponentContext cCtx) {
+		log.info("Activating literal externalizing provider");
+		if (cCtx != null) {
+			weight = (Integer) cCtx.getProperties().get("weight");
+			dataPath = cCtx.getBundleContext().
+					getDataFile(RELATIVE_DATA_PATH_NAME);
+		}
+	}
+
+	public void deactivate(ComponentContext cCtx) {
+		dataPath = null;
+	}
+
+	@Override
+	public int getWeight() {
+		return weight;
+	}
+
+	/**
+	 * we don't do graphs
+	 * 
+	 * @param name
+	 * @return
+	 * @throws NoSuchEntityException
+	 */
+	@Override
+	public Graph getGraph(UriRef name) throws NoSuchEntityException {
+		throw new NoSuchEntityException(name);
+	}
+
+	@Override
+	public synchronized MGraph getMGraph(UriRef name) throws NoSuchEntityException {
+		if (name.getUnicodeString().endsWith(EXTERNALIZEDLITERALS_SUFFIX)) {
+			throw new IllegalArgumentException();
+		}
+		try {
+			final UriRef baseGraphName = new UriRef(name.getUnicodeString() + EXTERNALIZEDLITERALS_SUFFIX);
+			final MGraph baseGraph = AccessController.doPrivileged(new PrivilegedExceptionAction<MGraph>() {
+
+				@Override
+				public MGraph run() {
+					return tcManager.getMGraph(baseGraphName);
+				}
+			});
+			return new ExternalizingMGraph(baseGraph, getHashStoreDir(name));
+		} catch (PrivilegedActionException ex) {
+			Throwable cause = ex.getCause();
+			if (cause instanceof UnsupportedOperationException) {
+				throw (UnsupportedOperationException)cause;
+			}
+			if (cause instanceof EntityAlreadyExistsException) {
+				throw (EntityAlreadyExistsException)cause;
+			}
+			if (cause instanceof RuntimeException) {
+				throw (RuntimeException)cause;
+			}
+			throw new RuntimeException(cause);
+		}
+	}
+
+	@Override
+	public TripleCollection getTriples(UriRef name) throws NoSuchEntityException {
+		return getMGraph(name);
+
+	}
+
+	@Override
+	public synchronized MGraph createMGraph(UriRef name)
+			throws UnsupportedOperationException, EntityAlreadyExistsException {
+		try {
+			if (name.getUnicodeString().endsWith(EXTERNALIZEDLITERALS_SUFFIX)) {
+				throw new IllegalArgumentException();
+			}
+			final UriRef baseGraphName = new UriRef(name.getUnicodeString() + EXTERNALIZEDLITERALS_SUFFIX);
+			final MGraph baseGraph = AccessController.doPrivileged(new PrivilegedExceptionAction<MGraph>() {
+
+				@Override
+				public MGraph run() {
+					return tcManager.createMGraph(baseGraphName);
+				}
+			});
+			File hashStoreDir = getHashStoreDir(name);
+			hashStoreDir.mkdirs();
+			return new ExternalizingMGraph(baseGraph, hashStoreDir);
+		} catch (PrivilegedActionException ex) {
+			Throwable cause = ex.getCause();
+			if (cause instanceof UnsupportedOperationException) {
+				throw (UnsupportedOperationException)cause;
+			}
+			if (cause instanceof EntityAlreadyExistsException) {
+				throw (EntityAlreadyExistsException)cause;
+			}
+			if (cause instanceof RuntimeException) {
+				throw (RuntimeException)cause;
+			}
+			throw new RuntimeException(cause);
+		}
+	}
+
+	@Override
+	public Graph createGraph(UriRef name, TripleCollection triples)
+			throws UnsupportedOperationException, EntityAlreadyExistsException {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void deleteTripleCollection(UriRef name)
+			throws UnsupportedOperationException, NoSuchEntityException,
+			EntityUndeletableException {
+		try {
+			final UriRef baseGraphName = new UriRef(name.getUnicodeString() + EXTERNALIZEDLITERALS_SUFFIX);
+			AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+
+				@Override
+				public Object run() {
+					tcManager.deleteTripleCollection(baseGraphName);
+					return null;
+				}
+			});
+			delete(getHashStoreDir(name));
+		} catch (PrivilegedActionException ex) {
+			Throwable cause = ex.getCause();
+			if (cause instanceof UnsupportedOperationException) {
+				throw (UnsupportedOperationException)cause;
+			}
+			if (cause instanceof EntityAlreadyExistsException) {
+				throw (EntityAlreadyExistsException)cause;
+			}
+			if (cause instanceof RuntimeException) {
+				throw (RuntimeException)cause;
+			}
+			throw new RuntimeException(cause);
+		}
+	}
+
+	/**
+	 * Cleans the content of the specified directory recursively.
+	 * @param dir  Abstract path denoting the directory to clean.
+	 */
+	private static void cleanDirectory(File dir) {
+		File[] files = dir.listFiles();
+		if (files != null && files.length > 0) {
+			for (File file : files) {
+				delete(file);
+			}
+		}
+	}
+
+	/**
+	 * Deletes the specified file or directory.
+	 * @param file  Abstract path denoting the file or directory to clean.
+	 */
+	protected static void delete(File file) {
+		if (file.isDirectory()) {
+			cleanDirectory(file);
+		}
+		file.delete();
+	}
+
+	@Override
+	public Set<UriRef> getNames(Graph graph) {
+		//this could be done more efficiently with an index, could be done with
+		//a MultiBidiMap (BidiMap allowing multiple keys for the same value)
+		Set<UriRef> result = new HashSet<UriRef>();
+		for (UriRef name : listGraphs()) {
+			if (getGraph(name).equals(graph)) {
+				result.add(name);
+			}
+		}
+		return result;
+	}
+
+	@Override
+	public Set<UriRef> listTripleCollections() {
+		Set<UriRef> result = new HashSet<UriRef>();
+		result.addAll(listGraphs());
+		result.addAll(listMGraphs());
+		return result;
+	}
+
+	@Override
+	public Set<UriRef> listGraphs() {
+		return new HashSet<UriRef>();
+	}
+
+	@Override
+	public Set<UriRef> listMGraphs() {
+		Set<UriRef> result = getHashStoreUris();
+		for (Iterator<UriRef> it = result.iterator(); it.hasNext();) {
+			UriRef graphName = it.next();
+			final UriRef baseGraphName = new UriRef(graphName.getUnicodeString() + EXTERNALIZEDLITERALS_SUFFIX);
+			try {
+				tcManager.getMGraph(baseGraphName);
+			} catch (NoSuchEntityException e) {
+				log.warn("Store for exeternalized literals but no base graph found for {}.", graphName);
+				it.remove();
+			}
+
+		}
+		return result;
+	}
+
+	private File getHashStoreDir(UriRef name) {
+		try {
+			String subDirName = URLEncoder.encode(name.getUnicodeString(), "utf-8");
+			File result = new File(dataPath, subDirName);
+			return result;
+		} catch (UnsupportedEncodingException ex) {
+			throw new RuntimeException("utf-8 not supported", ex);
+		}
+	}
+
+	private Set<UriRef> getHashStoreUris() {
+		Set<UriRef> result = new HashSet<UriRef>();
+		if (dataPath.exists()) {
+			for (String mGraphDirName : dataPath.list()) {
+				try {
+					UriRef uri = new UriRef(URLDecoder.decode(mGraphDirName, "utf-8"));
+					result.add(uri);
+				} catch (UnsupportedEncodingException ex) {
+					throw new RuntimeException("utf-8 not supported", ex);
+				}
+			}
+		}
+		return result;
+	}
+}

Added: incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider
URL: http://svn.apache.org/viewvc/incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider?rev=990257&view=auto
==============================================================================
--- incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider (added)
+++ incubator/clerezza/trunk/org.apache.clerezza.parent/org.apache.clerezza.rdf.storage.externalizer/src/main/resources/META-INF/services/org.apache.clerezza.rdf.core.access.WeightedTcProvider Fri Aug 27 20:39:03 2010
@@ -0,0 +1 @@
+org.apache.clerezza.rdf.storage.externalizer.ExternalizingProvider
\ No newline at end of file