Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 24499 invoked from network); 18 Oct 2007 18:35:40 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 18 Oct 2007 18:35:40 -0000 Received: (qmail 3002 invoked by uid 500); 18 Oct 2007 18:35:26 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 2966 invoked by uid 500); 18 Oct 2007 18:35:26 -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 2916 invoked by uid 99); 18 Oct 2007 18:35:26 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Oct 2007 11:35:26 -0700 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Oct 2007 18:35:28 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 3D91E1A9832; Thu, 18 Oct 2007 11:35:08 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r586058 [1/4] - in /jackrabbit/trunk/jackrabbit-spi-commons: ./ src/main/java/org/apache/jackrabbit/conversion/ src/main/java/org/apache/jackrabbit/identifier/ src/main/java/org/apache/jackrabbit/lock/ src/main/java/org/apache/jackrabbit/na... Date: Thu, 18 Oct 2007 18:35:01 -0000 To: commits@jackrabbit.apache.org From: angela@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20071018183508.3D91E1A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: angela Date: Thu Oct 18 11:34:57 2007 New Revision: 586058 URL: http://svn.apache.org/viewvc?rev=586058&view=rev Log: JCR-1169 Distribution of commons classes JCR-996 Name and Path interfaces in SPI Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingNameResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingPathResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/DefaultNamePathResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/GenerationalCache.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/IllegalNameException.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/MalformedPathException.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameException.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameParser.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NamePathResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingNameResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingPathResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathParser.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/lock/ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/lock/Locked.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/name/ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/name/NameConstants.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/name/NameFactoryImpl.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/name/PathBuilder.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/name/PathFactoryImpl.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/name/PathMap.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/namespace/ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/namespace/AbstractNamespaceResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/namespace/NamespaceAdder.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/namespace/NamespaceExtractor.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/namespace/NamespaceListener.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/namespace/NamespaceMapping.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/namespace/NamespaceResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/namespace/SessionNamespaceResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/nodetype/ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/nodetype/InvalidConstraintException.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/nodetype/InvalidNodeTypeDefException.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/nodetype/NodeTypeConflictException.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/conversion/ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/conversion/DummyNamespaceResolver.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/conversion/NameParserTest.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/conversion/ParsingNameResolverTest.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/conversion/ParsingPathResolverTest.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/conversion/PathParserTest.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/conversion/TestAll.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/name/ jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/name/JcrName.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/name/JcrPath.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/name/NameFactoryTest.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/name/PathBuilderTest.java (with props) jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/name/TestAll.java (with props) Removed: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/value/ValueFactoryImplEx.java Modified: jackrabbit/trunk/jackrabbit-spi-commons/pom.xml jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/AbstractIdFactory.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/IdFactoryImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/ChildInfoImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventFilterImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/EventImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/ItemInfoImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/NodeInfoImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/PropertyInfoImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/QItemDefinitionImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/QNodeDefinitionImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/QNodeTypeDefinitionImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/QPropertyDefinitionImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SerializableBatch.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/value/QValueFactoryImpl.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/value/ValueFormat.java jackrabbit/trunk/jackrabbit-spi-commons/src/test/java/org/apache/jackrabbit/value/QValueTest.java Modified: jackrabbit/trunk/jackrabbit-spi-commons/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/pom.xml?rev=586058&r1=586057&r2=586058&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/pom.xml (original) +++ jackrabbit/trunk/jackrabbit-spi-commons/pom.xml Thu Oct 18 11:34:57 2007 @@ -54,6 +54,26 @@ + + + + true + maven-compiler-plugin + + 1.4 + 1.4 + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/TestAll.java + + + + Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingNameResolver.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingNameResolver.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingNameResolver.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingNameResolver.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,100 @@ +/* + * 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.jackrabbit.conversion; + +import org.apache.jackrabbit.spi.Name; + +import javax.jcr.NamespaceException; + +/** + * Name resolver decorator that uses a generational cache to speed up + * parsing and formatting of JCR names. Uncached names are resolved using + * the underlying decorated name resolver. + */ +public class CachingNameResolver implements NameResolver { + + /** + * Decorated name resolver. + */ + private final NameResolver resolver; + + /** + * Generational cache. + */ + private final GenerationalCache cache; + + /** + * Creates a caching decorator for the given name resolver. The given + * generational cache is used for caching. + * + * @param resolver decorated name resolver + * @param cache generational cache + */ + public CachingNameResolver(NameResolver resolver, GenerationalCache cache) { + this.resolver = resolver; + this.cache = cache; + } + + /** + * Creates a caching decorator for the given name resolver. + * + * @param resolver name resolver + */ + public CachingNameResolver(NameResolver resolver) { + this(resolver, new GenerationalCache()); + } + + //-------------------------------------------------------< NameResolver >--- + /** + * Returns the qualified name for the given prefixed JCR name. The name + * is first looked up form the generational cache and the call gets + * delegated to the decorated name resolver only if the cache misses. + * + * @param name prefixed JCR name + * @return qualified name + * @throws IllegalNameException if the JCR name format is invalid + * @throws NamespaceException if the namespace prefix can not be resolved + */ + public Name getQName(String name) + throws IllegalNameException, NamespaceException { + Name qname = (Name) cache.get(name); + if (qname == null) { + qname = resolver.getQName(name); + cache.put(name, qname); + } + return qname; + } + + + /** + * Returns the prefixed JCR name for the given qualified name. The name + * is first looked up form the generational cache and the call gets + * delegated to the decorated name resolver only if the cache misses. + * + * @param qname qualified name + * @return prefixed JCR name + * @throws NamespaceException if the namespace URI can not be resolved + */ + public String getJCRName(Name qname) throws NamespaceException { + String name = (String) cache.get(qname); + if (name == null) { + name = resolver.getJCRName(qname); + cache.put(qname, name); + } + return name; + } +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingNameResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingNameResolver.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingPathResolver.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingPathResolver.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingPathResolver.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingPathResolver.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,102 @@ +/* + * 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.jackrabbit.conversion; + +import org.apache.jackrabbit.spi.Path; + +import javax.jcr.NamespaceException; + +/** + * Path resolver decorator that uses a generational cache to speed up + * parsing and formatting of JCR paths. Uncached paths are resolved using + * the underlying decorated path resolver. + */ +public class CachingPathResolver implements PathResolver { + + /** + * Decorated path resolver. + */ + private final PathResolver resolver; + + /** + * Generational cache. + */ + private final GenerationalCache cache; + + /** + * Creates a caching decorator for the given path resolver. The given + * generational cache is used for caching. + * + * @param resolver decorated path resolver + * @param cache generational cache + */ + public CachingPathResolver(PathResolver resolver, GenerationalCache cache) { + this.resolver = resolver; + this.cache = cache; + } + + /** + * Creates a caching decorator for the given path resolver. + * + * @param resolver name resolver + */ + public CachingPathResolver(PathResolver resolver) { + this(resolver, new GenerationalCache()); + } + + //--------------------------------------------------------< PathResolver > + + /** + * Returns the qualified path for the given prefixed JCR path. The path + * is first looked up form the generational cache and the call gets + * delegated to the decorated path resolver only if the cache misses. + * + * @param path prefixed JCR path + * @return qualified path + * @throws MalformedPathException if the JCR path format is invalid + * @throws IllegalNameException if any of the JCR names contained in the path are invalid. + * @throws NamespaceException if a namespace prefix can not be resolved + */ + public Path getQPath(String path) throws MalformedPathException, IllegalNameException, NamespaceException { + Path qpath = (Path) cache.get(path); + if (qpath == null) { + qpath = resolver.getQPath(path); + cache.put(path, qpath); + } + return qpath; + } + + + /** + * Returns the prefixed JCR path for the given qualified path. The path + * is first looked up form the generational cache and the call gets + * delegated to the decorated path resolver only if the cache misses. + * + * @param qpath qualified path + * @return prefixed JCR path + * @throws NamespaceException if a namespace URI can not be resolved + */ + public String getJCRPath(Path qpath) throws NamespaceException { + String path = (String) cache.get(qpath); + if (path == null) { + path = resolver.getJCRPath(qpath); + cache.put(qpath, path); + } + return path; + } + +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingPathResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/CachingPathResolver.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/DefaultNamePathResolver.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/DefaultNamePathResolver.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/DefaultNamePathResolver.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/DefaultNamePathResolver.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,75 @@ +/* + * 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.jackrabbit.conversion; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.Path; +import org.apache.jackrabbit.namespace.NamespaceResolver; +import org.apache.jackrabbit.name.NameFactoryImpl; +import org.apache.jackrabbit.name.PathFactoryImpl; + +import javax.jcr.NamespaceException; + +/** + * DefaultNamePathResolver... + */ +public class DefaultNamePathResolver implements NamePathResolver { + + private static Logger log = LoggerFactory.getLogger(DefaultNamePathResolver.class); + + private final NameResolver nResolver; + private final PathResolver pResolver; + + public DefaultNamePathResolver(NamespaceResolver nsResolver) { + this(nsResolver, false); + } + + public DefaultNamePathResolver(NamespaceResolver nsResolver, boolean enableCaching) { + NameResolver nr = new ParsingNameResolver(NameFactoryImpl.getInstance(), nsResolver); + PathResolver pr = new ParsingPathResolver(PathFactoryImpl.getInstance(), nr); + if (enableCaching) { + this.nResolver = new CachingNameResolver(nr); + this.pResolver = new CachingPathResolver(pr); + } else { + this.nResolver = nr; + this.pResolver = pr; + } + } + + public DefaultNamePathResolver(NameResolver nResolver, PathResolver pResolver) { + this.nResolver = nResolver; + this.pResolver = pResolver; + } + + public Name getQName(String name) throws IllegalNameException, NamespaceException { + return nResolver.getQName(name); + } + + public String getJCRName(Name name) throws NamespaceException { + return nResolver.getJCRName(name); + } + + public Path getQPath(String path) throws MalformedPathException, IllegalNameException, NamespaceException { + return pResolver.getQPath(path); + } + + public String getJCRPath(Path path) throws NamespaceException { + return pResolver.getJCRPath(path); + } +} \ No newline at end of file Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/DefaultNamePathResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/DefaultNamePathResolver.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/GenerationalCache.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/GenerationalCache.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/GenerationalCache.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/GenerationalCache.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,162 @@ +/* + * 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.jackrabbit.conversion; + +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; + +/** + * Generational cache. The cache implemented by this class consists of three + * parts: a long term cache and two generations of recent entries. The two + * generations are used to collect recent new entries, and those entries that + * are used within two successive generations get promoted to the long term + * cache. The entries within the long term cache are discarded only when the + * size of the cache exceeds the given maximum cache size. + */ +class GenerationalCache { + + /** + * Default maximum cache size. + */ + private static final int DEFAULT_CACHE_SIZE = 1000; + + /** + * Divisor used to determine the default generation age from the + * maximum cache size. + */ + private static final int DEFAULT_SIZE_AGE_RATIO = 10; + + /** + * Maximum size of the name cache. + */ + private final int maxSize; + + /** + * Maximum age of a cache generation. + */ + private final int maxAge; + + /** + * Long term cache. Read only. + */ + private Map cache = new HashMap(); + + /** + * Old cache generation. + */ + private Map old = new HashMap(); + + /** + * Young cache generation. + */ + private Map young = new HashMap(); + + /** + * Age of the young cache generation. + */ + private int age = 0; + + /** + * Creates a caching resolver. + * + * @param maxSize maximum size of the long term cache + * @param maxAge maximum age of a cache generation + */ + public GenerationalCache(int maxSize, int maxAge) { + this.maxSize = maxSize; + this.maxAge = maxAge; + } + + /** + * Creates a caching resolver using the default generation age for + * the given cache size. + * + * @param maxSize maximum size of the long term cache + */ + public GenerationalCache(int maxSize) { + this(maxSize, maxSize / DEFAULT_SIZE_AGE_RATIO); + } + + /** + * Creates a caching resolver using the default size and generation age. + */ + public GenerationalCache() { + this(DEFAULT_CACHE_SIZE); + } + + /** + * Returns the cached value (if any) for the given key. The value is + * looked up both from the long term cache and the old cache generation. + * If the value is only found in the old cache generation, it gets added + * to the young generation via a call to {@link #put(Object, Object)}. + * + * @param key key of the cache entry + * @return value of the cache entry, or null + */ + public Object get(Object key) { + Object value = cache.get(key); + if (value == null) { + value = old.get(key); + if (value != null) { + put(key, value); + } + } + return value; + } + + /** + * Caches the given key-value pair and increases the age of the current + * cache generation. When the maximum age of a generation is reached, + * the following steps are taken: + *
    + *
  1. The union of the two cache generations is calculated
  2. + *
  3. The union is added to the long term name cache
  4. + *
  5. If the cache size exceeds the maximum, only the union is kept
  6. + *
  7. A new cache generation is started
  8. + *
+ * + * @param key key of the cache entry + * @param value value of the cache entry + */ + public synchronized void put(Object key, Object value) { + young.put(key, value); + + if (++age == maxAge) { + Map union = new HashMap(); + Iterator iterator = old.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry entry = (Map.Entry) iterator.next(); + if (young.containsKey(entry.getKey())) { + union.put(entry.getKey(), entry.getValue()); + } + } + + if (!union.isEmpty()) { + if (cache.size() + union.size() <= maxSize) { + union.putAll(cache); + } + cache = union; + } + + old = young; + young = new HashMap(); + age = 0; + } + } + +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/GenerationalCache.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/GenerationalCache.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/IllegalNameException.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/IllegalNameException.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/IllegalNameException.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/IllegalNameException.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,51 @@ +/* + * 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.jackrabbit.conversion; + +/** + * Thrown when an illegal JCR name string is encountered. This exception is + * thrown when attempting to parse a JCR name string that does not match the + * JCR name syntax, or is otherwise not a legal name. Note that an + * {@link javax.jcr.NamespaceException} is thrown if the prefix of the JCR name + * string is syntactically valid but not bound to any namespace. + *

+ * See the section 4.6 of the JCR 1.0 specification for details of the + * JCR name syntax. + */ +public class IllegalNameException extends NameException { + + /** + * Creates an IllegalNameException with the given error message. + * + * @param message error message + */ + public IllegalNameException(String message) { + super(message); + } + + /** + * Creates an IllegalNameException with the given error message and + * root cause exception. + * + * @param message error message + * @param rootCause root cause exception + */ + public IllegalNameException(String message, Throwable rootCause) { + super(message, rootCause); + } + +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/IllegalNameException.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/IllegalNameException.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/MalformedPathException.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/MalformedPathException.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/MalformedPathException.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/MalformedPathException.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,49 @@ +/* + * 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.jackrabbit.conversion; + +/** + * Thrown when a malformed JCR path string is encountered. This exception is + * thrown when attempting to parse a JCR path string that does not match the + * JCR patch syntax, contains an invalid path elements, or is otherwise not + * well formed. + *

+ * See the section 4.6 of the JCR 1.0 specification for details of the + * JCR path syntax. + */ +public class MalformedPathException extends NameException { + + /** + * Creates a MalformedPathException with the given error message. + * + * @param message error message + */ + public MalformedPathException(String message) { + super(message); + } + + /** + * Creates a MalformedPathException with the given error message + * and root cause exception. + * + * @param message error message + * @param rootCause root cause exception + */ + public MalformedPathException(String message, Throwable rootCause) { + super(message, rootCause); + } +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/MalformedPathException.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/MalformedPathException.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameException.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameException.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameException.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameException.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,47 @@ +/* + * 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.jackrabbit.conversion; + +import javax.jcr.RepositoryException; + +/** + * Base class for exceptions about malformed or otherwise + * invalid JCR names and paths. + */ +public class NameException extends RepositoryException { + + /** + * Creates a NameException with the given error message. + * + * @param message error message + */ + public NameException(String message) { + super(message); + } + + /** + * Creates a NameException with the given error message and + * root cause exception. + * + * @param message error message + * @param rootCause root cause exception + */ + public NameException(String message, Throwable rootCause) { + super(message, rootCause); + } + +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameException.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameException.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameParser.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameParser.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameParser.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/NameParser.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,157 @@ +/* + * 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.jackrabbit.conversion; + +import org.apache.jackrabbit.spi.NameFactory; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.namespace.NamespaceResolver; +import org.apache.jackrabbit.util.XMLChar; + +import javax.jcr.NamespaceException; + +/** + * NameParser parses a {@link String jcrName} using a + * {@link NamespaceResolver} and a {@link NameFactory}. + */ +public class NameParser { + + // constants for parser + private static final int STATE_PREFIX_START = 0; + private static final int STATE_PREFIX = 1; + private static final int STATE_NAME_START = 2; + private static final int STATE_NAME = 3; + + /** + * Parses the jcrName and returns a new Name. + * + * @param jcrName the name to be parsed + * @param resolver NamespaceResolver use to retrieve the + * namespace URI from the prefix contained in the given JCR name. + * @return qName the new Name + * @throws IllegalNameException If jcrName is not a valid + * JCR-style name. + * @throws NamespaceException If the jcr name contains an unknown prefix. + */ + public static Name parse(String jcrName, NamespaceResolver resolver, NameFactory factory) + throws IllegalNameException, NamespaceException { + // trivial check + int len = jcrName == null ? 0 : jcrName.length(); + if (len == 0) { + throw new IllegalNameException("empty name"); + } + if (".".equals(jcrName) || "..".equals(jcrName)) { + throw new IllegalNameException(jcrName); + } + + // parse the name + String prefix = ""; + int nameStart = 0; + int state = STATE_PREFIX_START; + boolean trailingSpaces = false; + + for (int i = 0; i < len; i++) { + char c = jcrName.charAt(i); + if (c == ':') { + if (state == STATE_PREFIX_START) { + throw new IllegalNameException("Prefix must not be empty"); + } else if (state == STATE_PREFIX) { + if (trailingSpaces) { + throw new IllegalNameException("Trailing spaces not allowed"); + } + prefix = jcrName.substring(0, i); + if (!XMLChar.isValidNCName(prefix)) { + throw new IllegalNameException("Invalid name prefix: "+ prefix); + } + state = STATE_NAME_START; + } else { + throw new IllegalNameException("'" + c + "' not allowed in name"); + } + trailingSpaces = false; + } else if (c == ' ') { + if (state == STATE_PREFIX_START || state == STATE_NAME_START) { + throw new IllegalNameException("'" + c + "' not valid name start"); + } + trailingSpaces = true; + } else if (Character.isWhitespace(c) || c == '/' || c == '[' || c == ']' || c == '*' || c == '\'' || c == '\"') { + throw new IllegalNameException("'" + c + "' not allowed in name"); + } else { + if (state == STATE_PREFIX_START) { + state = STATE_PREFIX; // prefix start + } else if (state == STATE_NAME_START) { + state = STATE_NAME; + nameStart = i; + } + trailingSpaces = false; + } + } + + if (nameStart == len || state == STATE_NAME_START) { + throw new IllegalNameException("Local name must not be empty"); + } + if (trailingSpaces) { + throw new IllegalNameException("Trailing spaces not allowed"); + } + + // if namespace is null, this is just a check for format. this can only + // happen if invoked internally + if (resolver == null) { + return null; + } + + // resolve prefix to uri + String uri = resolver.getURI(prefix); + return factory.create(uri, nameStart == 0 ? jcrName : jcrName.substring(nameStart, len)); + } + + /** + * Parses an array of jcrName and returns the respective + * array of Name. + * + * @param jcrNames the array of names to be parsed + * @param resolver NamespaceResolver use to retrieve the + * namespace URI from the prefix contained in the given JCR name. + * @param factory + * @return the new array of Name + * @throws IllegalNameException If jcrName is not a valid + * JCR-style name. + * @throws NamespaceException If the jcr name contains an unknown prefix. + */ + public static Name[] parse(String jcrNames[], NamespaceResolver resolver, NameFactory factory) + throws NameException, NamespaceException { + + Name[] ret = new Name[jcrNames.length]; + for (int i=0; i + + /** + * Parses the prefixed JCR name and returns the resolved qualified name. + * + * @param name prefixed JCR name + * @return qualified name + * @throws IllegalNameException if the JCR name format is invalid + * @throws NamespaceException if the namespace prefix can not be resolved + */ + public Name getQName(String name) throws IllegalNameException, NamespaceException { + return NameParser.parse(name, resolver, nameFactory); + } + + /** + * Returns the prefixed JCR name for the given qualified name. + * If the name is in the default namespace, then the local name + * is returned without a prefix. Otherwise the prefix for the + * namespace is resolved and used to construct returned the JCR name. + * + * @param name qualified name + * @return prefixed JCR name + * @throws NamespaceException if the namespace URI can not be resolved + */ + public String getJCRName(Name name) throws NamespaceException { + String uri = name.getNamespaceURI(); + if (uri.length() == 0) { + return name.getLocalName(); + } else { + return resolver.getPrefix(uri) + ":" + name.getLocalName(); + } + } +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingNameResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingNameResolver.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingPathResolver.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingPathResolver.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingPathResolver.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingPathResolver.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,100 @@ +/* + * 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.jackrabbit.conversion; + +import org.apache.jackrabbit.spi.Path; +import org.apache.jackrabbit.spi.PathFactory; + +import javax.jcr.NamespaceException; + +/** + * Path resolver that parsers and formats prefixed JCR paths. + * A {@link NameResolver} is used for resolving the path element names. + */ +public class ParsingPathResolver implements PathResolver { + + /** + * Path factory. + */ + private final PathFactory pathFactory; + + /** + * Name resolver. + */ + private final NameResolver resolver; + + /** + * Creates a parsing path resolver. + * + * @param resolver name resolver + */ + public ParsingPathResolver(PathFactory pathFactory, NameResolver resolver) { + this.pathFactory = pathFactory; + this.resolver = resolver; + } + + /** + * Parses the prefixed JCR path and returns the resolved qualified path. + * + * @param path prefixed JCR path + * @return qualified path + * @throws MalformedPathException if the JCR path format is invalid. + * @throws IllegalNameException if any of the JCR names contained in the path are invalid. + * @throws NamespaceException if a namespace prefix can not be resolved + */ + public Path getQPath(String path) throws MalformedPathException, IllegalNameException, NamespaceException { + return PathParser.parse(path, resolver, pathFactory); + } + + + /** + * Returns the prefixed JCR path for the given qualified path. + * + * @param path qualified path + * @return prefixed JCR path + * @throws NamespaceException if a namespace URI can not be resolved + */ + public String getJCRPath(Path path) throws NamespaceException { + StringBuffer buffer = new StringBuffer(); + + Path.Element[] elements = path.getElements(); + for (int i = 0; i < elements.length; i++) { + if (i > 0) { + buffer.append('/'); + } + if (i == 0 && elements.length == 1 && elements[i].denotesRoot()) { + buffer.append('/'); + } else if (elements[i].denotesCurrent()) { + buffer.append('.'); + } else if (elements[i].denotesParent()) { + buffer.append(".."); + } else { + buffer.append(resolver.getJCRName(elements[i].getName())); + /** + * FIXME the [1] subscript should only be suppressed if the + * item in question can't have same-name siblings. + */ + if (elements[i].getIndex() > Path.INDEX_DEFAULT) { + buffer.append('['); + buffer.append(elements[i].getIndex()); + buffer.append(']'); + } + } + } + return buffer.toString(); + } +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingPathResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/ParsingPathResolver.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathParser.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathParser.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathParser.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathParser.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,279 @@ +/* + * 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.jackrabbit.conversion; + +import org.apache.jackrabbit.spi.Path; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.PathFactory; +import org.apache.jackrabbit.name.PathBuilder; +import org.apache.jackrabbit.name.PathFactoryImpl; + +import javax.jcr.NamespaceException; + +/** + * PathParser formats a {@link Path} using a + * {@link NameResolver} and a {@link PathFactory}. + */ +public class PathParser { + + // constants for parser + private static final int STATE_PREFIX_START = 0; + private static final int STATE_PREFIX = 1; + private static final int STATE_NAME_START = 2; + private static final int STATE_NAME = 3; + private static final int STATE_INDEX = 4; + private static final int STATE_INDEX_END = 5; + private static final int STATE_DOT = 6; + private static final int STATE_DOTDOT = 7; + + /** + * Parses jcrPath into a qualified path using + * resolver to convert prefixes into namespace URI's. + * + * @param jcrPath the jcr path. + * @param resolver the namespace resolver. + * @param factory + * @return qualified path. + * @throws MalformedPathException If the jcrPath is malformed. + * @throws IllegalNameException if any of the jcrNames is malformed. + * @throws NamespaceException If an unresolvable prefix is encountered. + */ + public static Path parse(String jcrPath, NameResolver resolver, PathFactory factory) + throws MalformedPathException, IllegalNameException, NamespaceException { + return parse(null, jcrPath, resolver, factory); + } + + /** + * Parses the give jcrPath and returns a Path. If + * parent is not null, it is prepended to the + * returned list. If resolver is null, this method + * only checks the format of the string and returns null. + * + * @param parent the parent path + * @param jcrPath the JCR path + * @param resolver the namespace resolver to get prefixes for namespace + * URI's. + * @param factory + * @return the fully qualified Path. + * @throws MalformedPathException If the jcrPath is malformed. + * @throws IllegalNameException if any of the jcrNames is malformed. + * @throws NamespaceException If an unresolvable prefix is encountered. + */ + public static Path parse(Path parent, String jcrPath, + NameResolver resolver, + PathFactory factory) throws MalformedPathException, IllegalNameException, NamespaceException { + final char EOF = (char) -1; + + // check for length + int len = jcrPath == null ? 0 : jcrPath.length(); + + // shortcut + if (len == 1 && jcrPath.charAt(0) == '/') { + return factory.getRootPath(); + } + + if (len == 0) { + throw new MalformedPathException("empty path"); + } + + // check if absolute path + PathBuilder builder = new PathBuilder(factory); + int pos = 0; + if (jcrPath.charAt(0) == '/') { + if (parent != null) { + throw new MalformedPathException("'" + jcrPath + "' is not a relative path"); + } + builder.addRoot(); + pos++; + } + + // add master if present + if (parent != null) { + builder.addAll(parent.getElements()); + } + + // parse the path + int state = STATE_PREFIX_START; + int lastPos = pos; + String name = null; + int index = Path.INDEX_UNDEFINED; + boolean wasSlash = false; + + while (pos <= len) { + char c = pos == len ? EOF : jcrPath.charAt(pos); + pos++; + // special check for whitespace + if (c != ' ' && Character.isWhitespace(c)) { + c = '\t'; + } + switch (c) { + case '/': + case EOF: + if (state == STATE_PREFIX_START && c != EOF) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. double slash '//' not allowed."); + } + if (state == STATE_PREFIX + || state == STATE_NAME + || state == STATE_INDEX_END) { + + // eof pathelement + if (name == null) { + if (wasSlash) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Trailing slashes not allowed in prefixes and names."); + } + name = jcrPath.substring(lastPos, pos - 1); + } + + // only add element if resolver not null. otherwise this + // is just a check for valid format. + if (resolver != null) { + Name qName = resolver.getQName(name); + builder.addLast(qName, index); + } + state = STATE_PREFIX_START; + lastPos = pos; + name = null; + index = Path.INDEX_UNDEFINED; + } else if (state == STATE_DOT) { + builder.addLast(factory.getCurrentElement()); + lastPos = pos; + state = STATE_PREFIX_START; + } else if (state == STATE_DOTDOT) { + builder.addLast(factory.getParentElement()); + lastPos = pos; + state = STATE_PREFIX_START; + } else if (state == STATE_PREFIX_START && c == EOF) { + // ignore trailing slash + } else { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character."); + } + break; + + case '.': + if (state == STATE_PREFIX_START) { + state = STATE_DOT; + } else if (state == STATE_DOT) { + state = STATE_DOTDOT; + } else if (state == STATE_DOTDOT) { + state = STATE_PREFIX; + } else if (state == STATE_INDEX_END) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected."); + } + break; + + case ':': + if (state == STATE_PREFIX_START) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. Prefix must not be empty"); + } else if (state == STATE_PREFIX) { + if (wasSlash) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Trailing slashes not allowed in prefixes and names."); + } + state = STATE_NAME_START; + // don't reset the lastPos/pos since prefix+name are passed together to the NameResolver + } else { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid name character"); + } + break; + + case '[': + if (state == STATE_PREFIX || state == STATE_NAME) { + if (wasSlash) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Trailing slashes not allowed in prefixes and names."); + } + state = STATE_INDEX; + name = jcrPath.substring(lastPos, pos - 1); + lastPos = pos; + } else { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character."); + } + break; + + case ']': + if (state == STATE_INDEX) { + try { + index = Integer.parseInt(jcrPath.substring(lastPos, pos - 1)); + } catch (NumberFormatException e) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. NumberFormatException in index: " + jcrPath.substring(lastPos, pos - 1)); + } + if (index < Path.INDEX_DEFAULT) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. Index number invalid: " + index); + } + state = STATE_INDEX_END; + } else { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character."); + } + break; + + case ' ': + if (state == STATE_PREFIX_START || state == STATE_NAME_START) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid name start"); + } else if (state == STATE_INDEX_END) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected."); + } else if (state == STATE_DOT || state == STATE_DOTDOT) { + state = STATE_PREFIX; + } else if (state == STATE_INDEX_END) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected."); + } + break; + + case '\t': + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. Whitespace not a allowed in name."); + + case '*': + case '\'': + case '\"': + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character."); + + default: + if (state == STATE_PREFIX_START || state == STATE_DOT || state == STATE_DOTDOT) { + state = STATE_PREFIX; + } else if (state == STATE_NAME_START) { + state = STATE_NAME; + } else if (state == STATE_INDEX_END) { + throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected."); + } + } + wasSlash = c == ' '; + } + + if (resolver == null) { + // this was only for checking the format + return null; + } else { + return builder.getPath(); + } + } + + /** + * Check the format of the given jcr path. Note, the neither name nor + * namespace validation (resolution of prefix to URI) is performed and + * therefore will not be detected. + * + * @param jcrPath + * @throws MalformedPathException If the jcrPath is malformed. + */ + public static void checkFormat(String jcrPath) throws MalformedPathException { + try { + // since no path is created -> use default factory + parse(jcrPath, null, PathFactoryImpl.getInstance()); + } catch (NamespaceException e) { + // will never occur + } catch (IllegalNameException e) { + // will never occur + } + } +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathParser.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathParser.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathResolver.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathResolver.java?rev=586058&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathResolver.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathResolver.java Thu Oct 18 11:34:57 2007 @@ -0,0 +1,48 @@ +/* + * 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.jackrabbit.conversion; + +import org.apache.jackrabbit.spi.Path; + +import javax.jcr.NamespaceException; + +/** + * Resolver for JCR paths. + */ +public interface PathResolver { + + /** + * Returns the qualified path for the given prefixed JCR path. + * + * @param path prefixed JCR path + * @return qualified path + * @throws MalformedPathException if the JCR path format is invalid. + * @throws IllegalNameException if any of the JCR names contained in the path are invalid. + * @throws NamespaceException if a namespace prefix can not be resolved. + */ + Path getQPath(String path) throws MalformedPathException, IllegalNameException, NamespaceException; + + /** + * Returns the prefixed JCR path for the given qualified path. + * + * @param path qualified path + * @return prefixed JCR path + * @throws NamespaceException if a namespace URI can not be resolved + */ + String getJCRPath(Path path) throws NamespaceException; + +} Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/conversion/PathResolver.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/AbstractIdFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/AbstractIdFactory.java?rev=586058&r1=586057&r2=586058&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/AbstractIdFactory.java (original) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/AbstractIdFactory.java Thu Oct 18 11:34:57 2007 @@ -20,10 +20,11 @@ import org.apache.jackrabbit.spi.PropertyId; import org.apache.jackrabbit.spi.NodeId; import org.apache.jackrabbit.spi.ItemId; -import org.apache.jackrabbit.name.Path; -import org.apache.jackrabbit.name.MalformedPathException; -import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.Path; +import org.apache.jackrabbit.spi.PathFactory; +import javax.jcr.RepositoryException; import java.io.Serializable; /** @@ -32,13 +33,20 @@ public abstract class AbstractIdFactory implements IdFactory { /** + * Subclassed need to define a PathFactory used to create IDs + * + * @return a implementation of PathFactory. + */ + protected abstract PathFactory getPathFactory(); + + /** * {@inheritDoc} * @see IdFactory#createNodeId(NodeId, Path) */ public NodeId createNodeId(NodeId parentId, Path path) { try { return new NodeIdImpl(parentId, path); - } catch (MalformedPathException e) { + } catch (RepositoryException e) { throw new IllegalArgumentException(e.getMessage()); } } @@ -61,18 +69,18 @@ /** * {@inheritDoc} - * @see IdFactory#createPropertyId(NodeId, QName) + * @see IdFactory#createPropertyId(NodeId,Name) */ - public PropertyId createPropertyId(NodeId parentId, QName propertyName) { + public PropertyId createPropertyId(NodeId parentId, Name propertyName) { try { return new PropertyIdImpl(parentId, propertyName); - } catch (MalformedPathException e) { + } catch (RepositoryException e) { throw new IllegalArgumentException(e.getMessage()); } } //------------------------------------------------------< Inner classes >--- - private static abstract class ItemIdImpl implements ItemId, Serializable { + private abstract class ItemIdImpl implements ItemId, Serializable { private final String uniqueID; private final Path path; @@ -87,16 +95,16 @@ this.path = path; } - private ItemIdImpl(NodeId parentId, QName name) throws MalformedPathException { + private ItemIdImpl(NodeId parentId, Name name) throws RepositoryException { if (parentId == null || name == null) { throw new IllegalArgumentException("Invalid ItemIdImpl: parentId and name must not be null."); } this.uniqueID = parentId.getUniqueID(); Path parentPath = parentId.getPath(); if (parentPath != null) { - this.path = Path.create(parentPath, name, true); + this.path = getPathFactory().create(parentPath, name, true); } else { - this.path = Path.create(name, Path.INDEX_UNDEFINED); + this.path = getPathFactory().create(name); } } @@ -164,7 +172,7 @@ } } - private static class NodeIdImpl extends ItemIdImpl implements NodeId { + private class NodeIdImpl extends ItemIdImpl implements NodeId { public NodeIdImpl(String uniqueID) { super(uniqueID, null); @@ -174,8 +182,8 @@ super(uniqueID, path); } - public NodeIdImpl(NodeId parentId, Path path) throws MalformedPathException { - super(parentId.getUniqueID(), (parentId.getPath() != null) ? Path.create(parentId.getPath(), path, true) : path); + public NodeIdImpl(NodeId parentId, Path path) throws RepositoryException { + super(parentId.getUniqueID(), (parentId.getPath() != null) ? getPathFactory().create(parentId.getPath(), path, true) : path); } public boolean denotesNode() { @@ -193,11 +201,11 @@ } } - private static class PropertyIdImpl extends ItemIdImpl implements PropertyId { + private class PropertyIdImpl extends ItemIdImpl implements PropertyId { private final NodeId parentId; - private PropertyIdImpl(NodeId parentId, QName name) throws MalformedPathException { + private PropertyIdImpl(NodeId parentId, Name name) throws RepositoryException { super(parentId, name); this.parentId = parentId; } @@ -210,7 +218,7 @@ return parentId; } - public QName getQName() { + public Name getName() { return getPath().getNameElement().getName(); } Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/IdFactoryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/IdFactoryImpl.java?rev=586058&r1=586057&r2=586058&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/IdFactoryImpl.java (original) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/identifier/IdFactoryImpl.java Thu Oct 18 11:34:57 2007 @@ -17,17 +17,27 @@ package org.apache.jackrabbit.identifier; import org.apache.jackrabbit.spi.IdFactory; +import org.apache.jackrabbit.spi.PathFactory; +import org.apache.jackrabbit.name.PathFactoryImpl; /** * IdFactoryImpl... */ public final class IdFactoryImpl extends AbstractIdFactory { - private static final IdFactory INSTANCE = new IdFactoryImpl(); + private static IdFactory INSTANCE; - private IdFactoryImpl() {} + private IdFactoryImpl() { + } public static IdFactory getInstance() { + if (INSTANCE == null) { + INSTANCE = new IdFactoryImpl(); + } return IdFactoryImpl.INSTANCE; + } + + protected PathFactory getPathFactory() { + return PathFactoryImpl.getInstance(); } }