Return-Path: X-Original-To: apmail-jackrabbit-commits-archive@www.apache.org Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B64407674 for ; Thu, 1 Dec 2011 14:43:35 +0000 (UTC) Received: (qmail 41292 invoked by uid 500); 1 Dec 2011 14:43:35 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 41255 invoked by uid 500); 1 Dec 2011 14:43:35 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 41248 invoked by uid 99); 1 Dec 2011 14:43:35 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Dec 2011 14:43:35 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Dec 2011 14:43:33 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 946D92388A3F; Thu, 1 Dec 2011 14:43:13 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1209107 - /jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/MongoPersistenceManager.java Date: Thu, 01 Dec 2011 14:43:13 -0000 To: commits@jackrabbit.apache.org From: stefan@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111201144313.946D92388A3F@eris.apache.org> Author: stefan Date: Thu Dec 1 14:43:11 2011 New Revision: 1209107 URL: http://svn.apache.org/viewvc?rev=1209107&view=rev Log: experimental mongodb support: verbose serialization format for debug purposes Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/MongoPersistenceManager.java Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/MongoPersistenceManager.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/MongoPersistenceManager.java?rev=1209107&r1=1209106&r2=1209107&view=diff ============================================================================== --- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/MongoPersistenceManager.java (original) +++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/MongoPersistenceManager.java Thu Dec 1 14:43:11 2011 @@ -38,7 +38,9 @@ import org.bson.types.ObjectId; import java.io.File; import java.io.InputStream; import java.security.MessageDigest; +import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Map; /** * @@ -124,8 +126,8 @@ public class MongoPersistenceManager ext return Serializer.fromBytes(id, bytes, Node.class); } else { return new StoredNode(id, - ((BasicDBObject) nodeObject.get(PROPERTIES_OBJECT)).toMap(), - (LinkedHashMap) ((BasicDBObject) nodeObject.get(PROPERTIES_OBJECT)).toMap()); + decodeKeys(((BasicDBObject) nodeObject.get(PROPERTIES_OBJECT)).toMap()), + (LinkedHashMap) decodeKeys(((BasicDBObject) nodeObject.get(CHILDREN_OBJECT)).toMap())); } } else { throw new NotFoundException(id); @@ -143,8 +145,8 @@ public class MongoPersistenceManager ext nodeObject = new BasicDBObject(ID_FIELD, key).append(DATA_FIELD, bytes); } else { nodeObject = new BasicDBObject(ID_FIELD, id) - .append(PROPERTIES_OBJECT, new BasicDBObject(node.getProperties())) - .append(CHILDREN_OBJECT, new BasicDBObject(node.getChildNodeEntries())); + .append(PROPERTIES_OBJECT, new BasicDBObject(encodeKeys(node.getProperties()))) + .append(CHILDREN_OBJECT, new BasicDBObject(encodeKeys(node.getChildNodeEntries()))); } try { nodes.insert(nodeObject); @@ -240,4 +242,115 @@ public class MongoPersistenceManager ext return f.getLength(); } + + protected static Map encodeKeys(Map map) { + boolean needsEncoding = false; + for (String key : map.keySet()) { + if (needsEncoding = needsEncoding(key)) { + break; + } + } + if (!needsEncoding) { + return map; + } + Map result; + if (map instanceof LinkedHashMap) { + result = new LinkedHashMap(map.size()); + } else { + result = new HashMap(map.size()); + } + for (Map.Entry entry : map.entrySet()) { + result.put(encodeName(entry.getKey()), entry.getValue()); + } + return result; + } + + protected static Map decodeKeys(Map map) { + boolean needsDecoding = false; + for (String key : map.keySet()) { + if (needsDecoding = needsDecoding(key)) { + break; + } + } + if (!needsDecoding) { + return map; + } + Map result; + if (map instanceof LinkedHashMap) { + result = new LinkedHashMap(map.size()); + } else { + result = new HashMap(map.size()); + } + for (Map.Entry entry : map.entrySet()) { + result.put(decodeName(entry.getKey()), entry.getValue()); + } + return result; + } + + protected final static String ENCODED_DOT = "_x46_"; + protected final static String ENCODED_DOLLAR_SIGN = "_x36_"; + + protected static boolean needsEncoding(String name) { + return name.startsWith("$") || name.indexOf('.') != -1; + } + + protected static boolean needsDecoding(String name) { + return name.startsWith(ENCODED_DOLLAR_SIGN) || name.indexOf(ENCODED_DOT) != -1; + } + + /** + * see http://www.mongodb.org/display/DOCS/Legal+Key+Names + * + * @param name + * @return + */ + protected static String encodeName(String name) { + StringBuilder buf = null; + for (int i = 0; i < name.length(); i++) { + if (i == 0 && name.charAt(i) == '$') { + // mongodb field names must not start with '$' + buf = new StringBuilder(); + buf.append(ENCODED_DOLLAR_SIGN); + } else if (name.charAt(i) == '.') { + // . is a reserved char for mongodb field names + if (buf == null) { + buf = new StringBuilder(name.substring(0, i)); + } + buf.append(ENCODED_DOT); + } else { + if (buf != null) { + buf.append(name.charAt(i)); + } + } + } + + return buf == null ? name : buf.toString(); + } + + protected static String decodeName(String name) { + StringBuilder buf = null; + + int lastPos = 0; + if (name.startsWith(ENCODED_DOLLAR_SIGN)) { + buf = new StringBuilder("$"); + lastPos = ENCODED_DOLLAR_SIGN.length(); + } + + int pos = -1; + while ((pos = name.indexOf(ENCODED_DOT, lastPos)) != -1) { + if (buf == null) { + buf = new StringBuilder(); + } + buf.append(name.substring(lastPos, pos)); + buf.append('.'); + lastPos = pos + ENCODED_DOT.length(); + } + + if (buf != null) { + buf.append(name.substring(lastPos)); + return buf.toString(); + } else { + return name; + } + } }