Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 762 invoked from network); 8 Sep 2009 16:10:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 8 Sep 2009 16:10:26 -0000 Received: (qmail 64897 invoked by uid 500); 8 Sep 2009 16:10:26 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 64854 invoked by uid 500); 8 Sep 2009 16:10: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 64845 invoked by uid 99); 8 Sep 2009 16:10:26 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Sep 2009 16:10:26 +0000 X-ASF-Spam-Status: No, hits=-1998.9 required=10.0 tests=ALL_TRUSTED,FB_GET_MEDS 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; Tue, 08 Sep 2009 16:10:14 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 1936F2388965; Tue, 8 Sep 2009 16:09:54 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r812570 [5/24] - in /jackrabbit/sandbox/JCR-1456: ./ jackrabbit-api/ jackrabbit-api/src/main/appended-resources/ jackrabbit-api/src/main/appended-resources/META-INF/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbi... Date: Tue, 08 Sep 2009 16:09:45 -0000 To: commits@jackrabbit.apache.org From: jukka@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090908160954.1936F2388965@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyData.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyData.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyData.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyData.java Tue Sep 8 16:09:28 2009 @@ -17,6 +17,8 @@ package org.apache.jackrabbit.core; import javax.jcr.nodetype.PropertyDefinition; +import javax.jcr.RepositoryException; + import org.apache.jackrabbit.core.state.PropertyState; /** @@ -28,10 +30,10 @@ * Create a new instance of this class. * * @param state associated property state - * @param definition associated property definition + * @param itemMgr item manager */ - PropertyData(PropertyState state, PropertyDefinition definition) { - super(state, definition); + PropertyData(PropertyState state, ItemManager itemMgr) { + super(state, itemMgr); } /** @@ -47,8 +49,9 @@ * Return the associated property definition. * * @return property definition + * @throws RepositoryException if the definition cannot be retrieved. */ - public PropertyDefinition getPropertyDefinition() { + public PropertyDefinition getPropertyDefinition() throws RepositoryException { return (PropertyDefinition) getDefinition(); } } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/PropertyImpl.java Tue Sep 8 16:09:28 2009 @@ -17,6 +17,7 @@ package org.apache.jackrabbit.core; import java.io.InputStream; +import java.io.IOException; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Calendar; @@ -49,6 +50,7 @@ import org.apache.jackrabbit.spi.commons.name.NameConstants; import org.apache.jackrabbit.spi.commons.value.ValueFormat; import org.apache.jackrabbit.value.ValueHelper; +import org.apache.commons.io.input.AutoCloseInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -226,12 +228,11 @@ LockException, ConstraintViolationException, RepositoryException { NodeImpl parent = (NodeImpl) getParent(); - PropertyDefinition definition = data.getPropertyDefinition(); // check multi-value flag - if (multipleValues != definition.isMultiple()) { + if (multipleValues != isMultiple()) { String msg = (multipleValues) ? "Single-valued property can not be set to an array of values:" : - "Multivalued property can not be set to a single value (an array of lenght one is OK): "; + "Multivalued property can not be set to a single value (an array of length one is OK): "; throw new ValueFormatException(msg + this); } @@ -240,7 +241,7 @@ session.getValidator().checkModify(this, options, Permission.NONE); // make sure the parent is checked-out and neither locked nor under retention - options = ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_LOCK | + options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION; session.getValidator().checkModify(parent, options, Permission.NONE); } @@ -259,14 +260,14 @@ ((NodeImpl) getParent()).removeChildProperty(((PropertyId) id).getName()); return; } - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList(); // compact array (purge null entries) - for (int i = 0; i < values.length; i++) { - if (values[i] != null) { - list.add(values[i]); + for (InternalValue v : values) { + if (v != null) { + list.add(v); } } - values = (InternalValue[]) list.toArray(new InternalValue[list.size()]); + values = list.toArray(new InternalValue[list.size()]); // modify the state of this property PropertyState thisState = (PropertyState) getOrCreateTransientItemState(); @@ -414,7 +415,7 @@ */ public InternalValue[] internalGetValues() throws RepositoryException { final PropertyDefinition definition = data.getPropertyDefinition(); - if (definition.isMultiple()) { + if (isMultiple()) { return getPropertyState().getValues(); } else { throw new ValueFormatException( @@ -433,7 +434,7 @@ */ public InternalValue internalGetValue() throws RepositoryException { final PropertyDefinition definition = data.getPropertyDefinition(); - if (definition.isMultiple()) { + if (isMultiple()) { throw new ValueFormatException( this + " is a multi-valued property," + " so it's values can only be retrieved as an array"); @@ -474,7 +475,14 @@ } public InputStream getStream() throws RepositoryException { - return getValue().getStream(); + final Binary bin = getValue().getBinary(); + // make sure binary is disposed after stream had been consumed + return new AutoCloseInputStream(bin.getStream()) { + public void close() throws IOException { + super.close(); + bin.dispose(); + } + }; } public long getLong() throws RepositoryException { @@ -780,7 +788,7 @@ // check state of this instance sanityCheck(); - return data.getPropertyDefinition().isMultiple(); + return getPropertyState().isMultiValued(); } //-----------------------------------------------------------------< Item > Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ProtectedItemModifier.java Tue Sep 8 16:09:28 2009 @@ -37,12 +37,12 @@ import org.apache.jackrabbit.spi.Path; /** - * SecurityItemModifier: An abstract helper class to allow classes - * of the security API residing outside of the core package to modify and remove - * protected items for security. The protected item definitions are required in - * order not to have security relevant content being changed through common - * item operations but forcing the usage of the security API. The latter asserts - * that implementation specific constraints are not violated. + * ProtectedItemModifier: An abstract helper class to allow classes + * residing outside of the core package to modify and remove protected items. + * The protected item definitions are required in order not to have security + * relevant content being changed through common item operations but forcing + * the usage of the corresponding APIs, which assert that implementation + * specific constraints are not violated. */ public abstract class ProtectedItemModifier { @@ -74,7 +74,7 @@ // check for name collisions // TODO: improve. copied from NodeImpl - NodeState thisState = (NodeState) parentImpl.getItemState(); + NodeState thisState = parentImpl.getNodeState(); ChildNodeEntry cne = thisState.getChildNodeEntry(name, 1); if (cne != null) { // there's already a child node entry with that name; @@ -118,6 +118,17 @@ return parentImpl.internalSetProperty(name, intVs); } + protected Property setProperty(NodeImpl parentImpl, Name name, Value[] values, int type) throws RepositoryException { + checkPermission(parentImpl, name, getPermission(false, false)); + // validation: make sure Node is not locked or checked-in. + parentImpl.checkSetProperty(); + InternalValue[] intVs = new InternalValue[values.length]; + for (int i = 0; i < values.length; i++) { + intVs[i] = InternalValue.create(values[i], parentImpl.session); + } + return parentImpl.internalSetProperty(name, intVs, type); + } + protected void removeItem(ItemImpl itemImpl) throws RepositoryException { NodeImpl n; if (itemImpl.isNode()) { Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryCopier.java Tue Sep 8 16:09:28 2009 @@ -31,8 +31,6 @@ import org.apache.jackrabbit.core.nodetype.NodeTypeDef; import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; import org.apache.jackrabbit.core.persistence.PersistenceCopier; -import org.apache.jackrabbit.core.state.ItemStateException; -import org.apache.jackrabbit.core.version.VersionManagerImpl; import org.apache.jackrabbit.spi.Name; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,6 +39,14 @@ * Tool for backing up or migrating the entire contents (workspaces, * version histories, namespaces, node types, etc.) of a repository to * a new repository. The target repository (if it exists) is overwritten. + *

+ * No cluster journal records are written in the target repository. If the + * target repository is clustered, it should be the only node in the cluster. + *

+ * The target repository needs to be fully reindexed after the copy operation. + * The static copy() methods will remove the target search index folders from + * their default locations to trigger automatic reindexing when the repository + * is next started. * * @since Apache Jackrabbit 1.6 */ @@ -53,30 +59,110 @@ LoggerFactory.getLogger(RepositoryCopier.class); /** - * Source repository configuration + * Source repository. */ - private final RepositoryConfig sourceConfig; + private final RepositoryImpl source; /** - * Target repository configuration + * Target repository. */ - private final RepositoryConfig targetConfig; + private final RepositoryImpl target; /** - * Creates a tool for copying the full contents of the source repository. - * The given source repository directory is expected to contain the - * repository configuration as a repository.xml file. - * The target repository directory should not already exist. It will be - * automatically created with default repository configuration. + * Copies the contents of the repository in the given source directory + * to a repository in the given target directory. * * @param source source repository directory * @param target target repository directory - * @throws RepositoryException if the repositories can not be accessed + * @throws RepositoryException if the copy operation fails + * @throws IOException if the target repository can not be initialized + */ + public static void copy(File source, File target) + throws RepositoryException, IOException { + copy(RepositoryConfig.create(source), RepositoryConfig.install(target)); + } + + /** + * Copies the contents of the repository with the given configuration + * to a repository in the given target directory. + * + * @param source source repository configuration + * @param target target repository directory + * @throws RepositoryException if the copy operation fails + * @throws IOException if the target repository can not be initialized + */ + public static void copy(RepositoryConfig source, File target) + throws RepositoryException, IOException { + copy(source, RepositoryConfig.install(target)); + } + + /** + * Copies the contents of the source repository with the given + * configuration to a target repository with the given configuration. + * + * @param source source repository configuration + * @param target target repository directory + * @throws RepositoryException if the copy operation fails + */ + public static void copy(RepositoryConfig source, RepositoryConfig target) + throws RepositoryException { + RepositoryImpl repository = RepositoryImpl.create(source); + try { + copy(repository, target); + } finally { + repository.shutdown(); + } + } + + /** + * Copies the contents of the given source repository to a repository in + * the given target directory. + *

+ * The source repository must not be modified while + * the copy operation is running to avoid an inconsistent copy. + * + * @param source source repository directory + * @param target target repository directory + * @throws RepositoryException if the copy operation fails * @throws IOException if the target repository can not be initialized */ - public RepositoryCopier(File source, File target) + public static void copy(RepositoryImpl source, File target) throws RepositoryException, IOException { - this(RepositoryConfig.create(source), RepositoryConfig.install(target)); + copy(source, RepositoryConfig.install(target)); + } + + /** + * Copies the contents of the given source repository to a target + * repository with the given configuration. + *

+ * The source repository must not be modified while + * the copy operation is running to avoid an inconsistent copy. + * + * @param source source repository directory + * @param target target repository directory + * @throws RepositoryException if the copy operation fails + * @throws IOException if the target repository can not be initialized + */ + public static void copy(RepositoryImpl source, RepositoryConfig target) + throws RepositoryException { + RepositoryImpl repository = RepositoryImpl.create(target); + try { + new RepositoryCopier(source, repository).copy(); + } finally { + repository.shutdown(); + } + + // Remove index directories to force re-indexing on next startup + // TODO: There should be a cleaner way to do this + File targetDir = new File(target.getHomeDir()); + File repoDir = new File(targetDir, "repository"); + FileUtils.deleteQuietly(new File(repoDir, "index")); + File[] workspaces = new File(targetDir, "workspaces").listFiles(); + if (workspaces != null) { + for (File workspace : workspaces) { + FileUtils.deleteQuietly(new File(workspace, "index")); + } + } } /** @@ -84,18 +170,22 @@ * to the given target repository. Any existing content in the target * repository will be overwritten. * - * @param source source repository configuration - * @param target target repository configuration - * @throws RepositoryException if the repositories can not be accessed + * @param source source repository + * @param target target repository */ - public RepositoryCopier(RepositoryConfig source, RepositoryConfig target) - throws RepositoryException { - sourceConfig = source; - targetConfig = target; + public RepositoryCopier(RepositoryImpl source, RepositoryImpl target) { + this.source = source; + this.target = target; } /** * Copies the full content from the source to the target repository. + *

+ * The source repository must not be modified while + * the copy operation is running to avoid an inconsistent copy. + *

+ * This method leaves the search indexes of the target repository in + * an * Note that both the source and the target repository must be closed * during the copy operation as this method requires exclusive access * to the repositories. @@ -105,89 +195,65 @@ public void copy() throws RepositoryException { logger.info( "Copying repository content from {} to {}", - sourceConfig.getHomeDir(), targetConfig.getHomeDir()); - - RepositoryImpl source = RepositoryImpl.create(sourceConfig); + source.repConfig.getHomeDir(), + target.repConfig.getHomeDir()); try { - RepositoryImpl target = RepositoryImpl.create(targetConfig); - try { - copyNamespaces( - source.getNamespaceRegistry(), - target.getNamespaceRegistry()); - copyNodeTypes( - source.getNodeTypeRegistry(), - target.getNodeTypeRegistry()); - copyVersionStore( - source.getVersionManagerImpl(), - target.getVersionManagerImpl()); - copyWorkspaces(source, target); - } catch (InvalidNodeTypeDefException e) { - throw new RepositoryException("Failed to copy node types", e); - } catch (ItemStateException e) { - throw new RepositoryException("Failed to copy item states", e); - } finally { - target.shutdown(); - } - - // Remove index directories to force re-indexing on next startup - // TODO: There should be a cleaner way to do this - File targetDir = new File(targetConfig.getHomeDir()); - File repoDir = new File(targetDir, "repository"); - FileUtils.deleteQuietly(new File(repoDir, "index")); - File[] workspaces = new File(targetDir, "workspaces").listFiles(); - if (workspaces != null) { - for (File workspace : workspaces) { - FileUtils.deleteQuietly(new File(workspace, "index")); - } - } - } finally { - source.shutdown(); + copyNamespaces(); + copyNodeTypes(); + copyVersionStore(); + copyWorkspaces(); + } catch (Exception e) { + throw new RepositoryException("Failed to copy content", e); } } - private void copyNamespaces( - NamespaceRegistry source, NamespaceRegistry target) - throws RepositoryException { - logger.info("Copying registered namespaces"); + private void copyNamespaces() throws RepositoryException { + NamespaceRegistry sourceRegistry = source.getNamespaceRegistry(); + NamespaceRegistry targetRegistry = target.getNamespaceRegistry(); - Collection existing = Arrays.asList(target.getURIs()); - for (String uri : source.getURIs()) { + logger.info("Copying registered namespaces"); + Collection existing = Arrays.asList(targetRegistry.getURIs()); + for (String uri : sourceRegistry.getURIs()) { if (!existing.contains(uri)) { // TODO: what if the prefix is already taken? - target.registerNamespace(source.getPrefix(uri), uri); + targetRegistry.registerNamespace( + sourceRegistry.getPrefix(uri), uri); } } } - private void copyNodeTypes(NodeTypeRegistry source, NodeTypeRegistry target) - throws RepositoryException, InvalidNodeTypeDefException { - logger.info("Copying registered node types"); + private void copyNodeTypes() throws RepositoryException { + NodeTypeRegistry sourceRegistry = source.getNodeTypeRegistry(); + NodeTypeRegistry targetRegistry = target.getNodeTypeRegistry(); + logger.info("Copying registered node types"); Collection existing = - Arrays.asList(target.getRegisteredNodeTypes()); + Arrays.asList(targetRegistry.getRegisteredNodeTypes()); Collection register = new ArrayList(); - for (Name name : source.getRegisteredNodeTypes()) { + for (Name name : sourceRegistry.getRegisteredNodeTypes()) { // TODO: what about modified node types? if (!existing.contains(name)) { - register.add(source.getNodeTypeDef(name)); + register.add(sourceRegistry.getNodeTypeDef(name)); } } - target.registerNodeTypes(register); + try { + targetRegistry.registerNodeTypes(register); + } catch (InvalidNodeTypeDefException e) { + throw new RepositoryException("Unable to copy node types", e); + } } - private void copyVersionStore( - VersionManagerImpl source, VersionManagerImpl target) - throws RepositoryException, ItemStateException { + private void copyVersionStore() throws RepositoryException { logger.info("Copying version histories"); - PersistenceCopier copier = new PersistenceCopier( - source.getPersistenceManager(), - target.getPersistenceManager()); + source.getVersionManagerImpl().getPersistenceManager(), + target.getVersionManagerImpl().getPersistenceManager(), + target.getDataStore()); copier.copy(RepositoryImpl.VERSION_STORAGE_NODE_ID); + copier.copy(RepositoryImpl.ACTIVITIES_NODE_ID); } - private void copyWorkspaces(RepositoryImpl source, RepositoryImpl target) - throws RepositoryException, ItemStateException { + private void copyWorkspaces() throws RepositoryException { Collection existing = Arrays.asList(target.getWorkspaceNames()); for (String name : source.getWorkspaceNames()) { logger.info("Copying workspace {}" , name); @@ -198,7 +264,8 @@ PersistenceCopier copier = new PersistenceCopier( source.getWorkspaceInfo(name).getPersistenceManager(), - target.getWorkspaceInfo(name).getPersistenceManager()); + target.getWorkspaceInfo(name).getPersistenceManager(), + target.getDataStore()); copier.excludeNode(RepositoryImpl.SYSTEM_ROOT_NODE_ID); copier.copy(RepositoryImpl.ROOT_NODE_ID); } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Tue Sep 8 16:09:28 2009 @@ -25,13 +25,21 @@ import java.io.StringReader; import java.security.AccessControlContext; import java.security.AccessController; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.Iterator; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import javax.jcr.AccessDeniedException; import javax.jcr.Credentials; @@ -42,9 +50,10 @@ import javax.jcr.Session; import javax.jcr.SimpleCredentials; import javax.jcr.Value; +import javax.jcr.ValueFactory; +import javax.jcr.Repository; +import javax.jcr.PropertyType; import javax.jcr.observation.Event; -import javax.jcr.observation.EventIterator; -import javax.jcr.observation.EventListener; import javax.jcr.observation.ObservationManager; import javax.security.auth.Subject; @@ -97,9 +106,10 @@ import org.apache.jackrabbit.core.state.SharedItemStateManager; import org.apache.jackrabbit.core.util.RepositoryLockMechanism; import org.apache.jackrabbit.core.util.db.ConnectionFactory; -import org.apache.jackrabbit.core.version.VersionManager; -import org.apache.jackrabbit.core.version.VersionManagerImpl; +import org.apache.jackrabbit.core.version.InternalVersionManager; +import org.apache.jackrabbit.core.version.InternalVersionManagerImpl; import org.apache.jackrabbit.core.xml.ClonedInputSource; +import org.apache.jackrabbit.value.ValueFactoryImpl; import org.apache.jackrabbit.spi.commons.name.NameConstants; import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver; import org.apache.jackrabbit.spi.commons.namespace.RegistryNamespaceResolver; @@ -116,7 +126,7 @@ * A RepositoryImpl ... */ public class RepositoryImpl extends AbstractRepository - implements javax.jcr.Repository, JackrabbitRepository, SessionListener, EventListener, WorkspaceListener { + implements javax.jcr.Repository, JackrabbitRepository, SessionListener, WorkspaceListener { private static Logger log = LoggerFactory.getLogger(RepositoryImpl.class); @@ -136,35 +146,35 @@ public static final NodeId VERSION_STORAGE_NODE_ID = NodeId.valueOf("deadbeef-face-babe-cafe-babecafebabe"); /** - * hardcoded id of the "/jcr:system/jcr:versionStorage/jcr:activities" node + * hardcoded id of the "/jcr:system/jcr:activities" node */ public static final NodeId ACTIVITIES_NODE_ID = NodeId.valueOf("deadbeef-face-babe-ac71-babecafebabe"); /** + * hardcoded id of the "/jcr:system/jcr:configurations" node + */ + public static final NodeId CONFIGURATIONS_NODE_ID = NodeId.valueOf("deadbeef-face-babe-c04f-babecafebabe"); + + /** * hardcoded id of the "/jcr:system/jcr:nodeTypes" node */ public static final NodeId NODETYPES_NODE_ID = NodeId.valueOf("deadbeef-cafe-cafe-cafe-babecafebabe"); /** - * the name of the file system resource containing the properties of the - * repository. + * the name of the resource containing customized descriptors of the repository. */ - private static final String PROPERTIES_RESOURCE = "rep.properties"; + private static final String PROPERTIES_RESOURCE = "repository.properties"; /** - * the repository properties. + * the repository descriptors, maps String keys to Value/Value[] objects */ - private final Properties repProps; - - // names of well-known repository properties - public static final String STATS_NODE_COUNT_PROPERTY = "jcr.repository.stats.nodes.count"; - public static final String STATS_PROP_COUNT_PROPERTY = "jcr.repository.stats.properties.count"; + private final Map repDescriptors = new HashMap(); private NodeId rootNodeId; private final NamespaceRegistryImpl nsReg; private final NodeTypeRegistry ntReg; - private final VersionManagerImpl vMgr; + private final InternalVersionManagerImpl vMgr; private final VirtualNodeTypeStateManager virtNTMgr; /** @@ -206,13 +216,9 @@ /** * active sessions (weak references) */ - private final ReferenceMap activeSessions = + private final Map activeSessions = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK); - // misc. statistics - private long nodesCount; - private long propsCount; - // flag indicating if repository has been shut down private boolean disposed; @@ -253,6 +259,11 @@ private WorkspaceEventChannel createWorkspaceEventChannel; /** + * Scheduled executor service. + */ + protected final ScheduledExecutorService executor; + + /** * Protected constructor. * * @param repConfig the repository configuration. @@ -261,6 +272,10 @@ * or another error occurs. */ protected RepositoryImpl(RepositoryConfig repConfig) throws RepositoryException { + ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( + Runtime.getRuntime().availableProcessors() * 2, + new ThreadPoolExecutor.CallerRunsPolicy()); + this.executor = executor; // Acquire a lock on the repository home repLock = repConfig.getRepositoryLockMechanism(); @@ -293,10 +308,8 @@ // init root node uuid rootNodeId = loadRootNodeId(metaDataStore); - // load repository properties - repProps = loadRepProps(); - nodesCount = Long.parseLong(repProps.getProperty(STATS_NODE_COUNT_PROPERTY, "0")); - propsCount = Long.parseLong(repProps.getProperty(STATS_PROP_COUNT_PROPERTY, "0")); + // initialize repository descriptors + initRepositoryDescriptors(); // create registries nsReg = createNamespaceRegistry(new BasedFileSystem(repStore, "/namespaces")); @@ -457,7 +470,7 @@ * @return the newly created version manager * @throws RepositoryException if an error occurs */ - protected VersionManagerImpl createVersionManager(VersioningConfig vConfig, + protected InternalVersionManagerImpl createVersionManager(VersioningConfig vConfig, DelegatingObservationDispatcher delegatingDispatcher) throws RepositoryException { @@ -473,7 +486,7 @@ ISMLocking ismLocking = vConfig.getISMLocking(); - return new VersionManagerImpl(pm, fs, ntReg, delegatingDispatcher, + return new InternalVersionManagerImpl(pm, fs, ntReg, delegatingDispatcher, SYSTEM_ROOT_NODE_ID, VERSION_STORAGE_NODE_ID, ACTIVITIES_NODE_ID, @@ -698,7 +711,7 @@ return ntReg; } - protected VersionManager getVersionManager() { + protected InternalVersionManager getVersionManager() { return vMgr; } @@ -1113,17 +1126,16 @@ // (copy sessions to array to avoid ConcurrentModificationException; // manually copy entries rather than calling ReferenceMap#toArray() in // order to work around http://issues.apache.org/bugzilla/show_bug.cgi?id=25551) - SessionImpl[] sa; + List sa; synchronized (activeSessions) { - int cnt = 0; - sa = new SessionImpl[activeSessions.size()]; - for (Iterator it = activeSessions.values().iterator(); it.hasNext(); cnt++) { - sa[cnt] = it.next(); + sa = new ArrayList(activeSessions.size()); + for (SessionImpl session : activeSessions.values()) { + sa.add(session); } } - for (int i = 0; i < sa.length; i++) { - if (sa[i] != null) { - sa[i].logout(); + for (SessionImpl session : sa) { + if (session != null) { + session.logout(); } } @@ -1147,14 +1159,7 @@ } } - if (repProps != null) { - // persist repository properties - try { - storeRepProps(repProps); - } catch (RepositoryException e) { - log.error("failed to persist repository properties", e); - } - } + repDescriptors.clear(); if (dataStore != null) { try { @@ -1180,6 +1185,18 @@ // wake up threads waiting on this instance's monitor (e.g. workspace janitor) notifyAll(); + // Shut down the executor service + executor.shutdown(); + try { + // Wait for all remaining background threads to terminate + if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { + log.warn("Attempting to forcibly shutdown runaway threads"); + executor.shutdownNow(); + } + } catch (InterruptedException e) { + log.warn("Interrupted while waiting for background threads", e); + } + // finally release repository lock if (repLock != null) { try { @@ -1200,6 +1217,10 @@ return repConfig; } + InternalVersionManagerImpl getVersionManagerImpl() { + return vMgr; + } + /** * Returns the repository file system. * @return repository file system @@ -1209,104 +1230,154 @@ } /** - * Sets the default properties of the repository. - *

- * This method loads the Properties from the - * org/apache/jackrabbit/core/repository.properties resource - * found in the class path and (re)sets the statistics properties, if not - * present. - * - * @param props the properties object to load - * - * @throws RepositoryException if the properties can not be loaded - */ - protected void setDefaultRepositoryProperties(Properties props) - throws RepositoryException { - InputStream in = RepositoryImpl.class.getResourceAsStream("repository.properties"); - try { - props.load(in); - in.close(); - - // set counts - if (!props.containsKey(STATS_NODE_COUNT_PROPERTY)) { - props.setProperty(STATS_NODE_COUNT_PROPERTY, Long.toString(nodesCount)); - } - if (!props.containsKey(STATS_PROP_COUNT_PROPERTY)) { - props.setProperty(STATS_PROP_COUNT_PROPERTY, Long.toString(propsCount)); - } - } catch (IOException e) { - String msg = "Failed to load repository properties: " + e.toString(); - log.error(msg); - throw new RepositoryException(msg, e); - } - } - - /** - * Loads the repository properties by executing the following steps: + * Initializes the repository descriptors by executing the following steps: *

    - *
  • if the {@link #PROPERTIES_RESOURCE} exists in the meta data store, - * the properties are loaded from that resource.
  • - *
  • {@link #setDefaultRepositoryProperties(Properties)} is called - * afterwards in order to initialize/update the repository properties - * since some default properties might have changed and need updating.
  • - *
  • finally {@link #storeRepProps(Properties)} is called in order to - * persist the newly generated properties.
  • + *
  • Sets standard descriptors
  • + *
  • {@link #getCustomRepositoryDescriptors()} is called + * afterwards in order to add custom/overwrite standard repository decriptors.
  • *
* - * @return the newly loaded/initialized repository properties - * * @throws RepositoryException */ - protected Properties loadRepProps() throws RepositoryException { - FileSystemResource propFile = new FileSystemResource(metaDataStore, PROPERTIES_RESOURCE); - try { - Properties props = new Properties(); - if (propFile.exists()) { - InputStream in = propFile.getInputStream(); - try { - props.load(in); - } finally { - in.close(); - } - } - // now set the default props - setDefaultRepositoryProperties(props); - - // and store - storeRepProps(props); + protected void initRepositoryDescriptors() throws RepositoryException { - return props; - - } catch (Exception e) { - String msg = "failed to load repository properties"; - log.debug(msg); - throw new RepositoryException(msg, e); + ValueFactory valFactory = ValueFactoryImpl.getInstance(); + Value valTrue = valFactory.createValue(true); + Value valFalse = valFactory.createValue(false); + + setDescriptor(Repository.REP_NAME_DESC, "Jackrabbit"); + setDescriptor(Repository.REP_VENDOR_DESC, "Apache Software Foundation"); + setDescriptor(Repository.REP_VENDOR_URL_DESC, "http://jackrabbit.apache.org/"); + setDescriptor(Repository.SPEC_NAME_DESC, "Content Repository API for Java(TM) Technology Specification"); + setDescriptor(Repository.SPEC_VERSION_DESC, "2.0"); + + setDescriptor(Repository.IDENTIFIER_STABILITY, Repository.IDENTIFIER_STABILITY_INDEFINITE_DURATION); + setDescriptor(Repository.LEVEL_1_SUPPORTED, valTrue); + setDescriptor(Repository.LEVEL_2_SUPPORTED, valTrue); + setDescriptor(Repository.WRITE_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_NODE_TYPE_MANAGEMENT_SUPPORTED, valTrue); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_AUTOCREATED_DEFINITIONS_SUPPORTED, valTrue); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_INHERITANCE, Repository.NODE_TYPE_MANAGEMENT_INHERITANCE_MULTIPLE); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_MULTIPLE_BINARY_PROPERTIES_SUPPORTED, valTrue); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_MULTIVALUED_PROPERTIES_SUPPORTED, valTrue); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_ORDERABLE_CHILD_NODES_SUPPORTED, valTrue); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_OVERRIDES_SUPPORTED, valFalse); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_PRIMARY_ITEM_NAME_SUPPORTED, valTrue); + + Value[] types = new Value[] { + valFactory.createValue(PropertyType.BINARY), + valFactory.createValue(PropertyType.BOOLEAN), + valFactory.createValue(PropertyType.DATE), + valFactory.createValue(PropertyType.DECIMAL), + valFactory.createValue(PropertyType.DOUBLE), + valFactory.createValue(PropertyType.LONG), + valFactory.createValue(PropertyType.NAME), + valFactory.createValue(PropertyType.PATH), + valFactory.createValue(PropertyType.REFERENCE), + valFactory.createValue(PropertyType.STRING), + valFactory.createValue(PropertyType.URI), + valFactory.createValue(PropertyType.WEAKREFERENCE), + valFactory.createValue(PropertyType.UNDEFINED) + }; + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_PROPERTY_TYPES, types); + + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_RESIDUAL_DEFINITIONS_SUPPORTED, valTrue); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_SAME_NAME_SIBLINGS_SUPPORTED, valTrue); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_VALUE_CONSTRAINTS_SUPPORTED, valTrue); + setDescriptor(Repository.NODE_TYPE_MANAGEMENT_UPDATE_IN_USE_SUPORTED, valFalse); + setDescriptor(Repository.OPTION_ACCESS_CONTROL_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_JOURNALED_OBSERVATION_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_LIFECYCLE_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_LOCKING_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_OBSERVATION_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_QUERY_SQL_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_RETENTION_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_SHAREABLE_NODES_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_SIMPLE_VERSIONING_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_TRANSACTIONS_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_UNFILED_CONTENT_SUPPORTED, valFalse); + setDescriptor(Repository.OPTION_UPDATE_MIXIN_NODE_TYPES_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_UPDATE_PRIMARY_NODE_TYPE_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_VERSIONING_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_XML_EXPORT_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_XML_IMPORT_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_ACTIVITIES_SUPPORTED, valTrue); + setDescriptor(Repository.OPTION_BASELINES_SUPPORTED, valTrue); + + setDescriptor(Repository.QUERY_FULL_TEXT_SEARCH_SUPPORTED, valTrue); + setDescriptor(Repository.QUERY_JOINS, Repository.QUERY_JOINS_INNER_OUTER); + + Value[] languages = new Value[] { + valFactory.createValue("javax.jcr.query.JCR-JQOM"), + valFactory.createValue("javax.jcr.query.JCR-SQL2") + }; + setDescriptor(Repository.QUERY_LANGUAGES, languages); + + setDescriptor(Repository.QUERY_STORED_QUERIES_SUPPORTED, valTrue); + setDescriptor(Repository.QUERY_XPATH_POS_INDEX, valTrue); + // Disabled since in default configuration document order is not supported. + // See https://issues.apache.org/jira/browse/JCR-1237 for details + setDescriptor(Repository.QUERY_XPATH_DOC_ORDER, valFalse); + + // now set customized repository descriptor values (if any exist) + Properties props = getCustomRepositoryDescriptors(); + if (props != null) { + for (Iterator it = props.keySet().iterator(); it.hasNext();) { + String key = (String) it.next(); + setDescriptor(key, props.getProperty(key)); + } } } /** - * Stores the properties to a persistent resource in the meta filesytem. + * Returns a Properties object containing custom repository + * descriptors or null if none exist. + *

+ * Overridable to allow subclasses to add custom descriptors or to + * override standard descriptor values. + *

+ * Note that the properties entries will be set as single-valued STRING + * descriptor values. + *

+ * This method tries to load the Properties from the + * org/apache/jackrabbit/core/repository.properties resource + * found in the class path. * - * @throws RepositoryException + * @throws RepositoryException if the properties can not be loaded */ - protected void storeRepProps(Properties props) throws RepositoryException { - FileSystemResource propFile = new FileSystemResource(metaDataStore, PROPERTIES_RESOURCE); - try { - propFile.makeParentDirs(); - OutputStream os = propFile.getOutputStream(); - try { - props.store(os, null); + protected Properties getCustomRepositoryDescriptors() throws RepositoryException { + InputStream in = RepositoryImpl.class.getResourceAsStream(PROPERTIES_RESOURCE); + if (in != null) { + try { + Properties props = new Properties(); + props.load(in); + return props; + } catch (IOException e) { + String msg = "Failed to load customized repository properties: " + e.toString(); + log.error(msg); + throw new RepositoryException(msg, e); } finally { - // make sure stream is closed - os.close(); + IOUtils.closeQuietly(in); } - } catch (Exception e) { - String msg = "failed to persist repository properties"; - log.debug(msg); - throw new RepositoryException(msg, e); + } else { + return null; } } + protected void setDescriptor(String desc, String value) { + setDescriptor(desc, ValueFactoryImpl.getInstance().createValue(value)); + } + + protected void setDescriptor(String desc, Value value) { + repDescriptors.put(desc, new DescriptorValue(value)); + } + + protected void setDescriptor(String desc, Value[] values) { + repDescriptors.put(desc, new DescriptorValue(values)); + } + /** * Creates a workspace persistence manager based on the given * configuration. The persistence manager is instantiated using @@ -1424,31 +1495,46 @@ * {@inheritDoc} */ public String getDescriptor(String key) { - return repProps.getProperty(key); + Value v = getDescriptorValue(key); + try { + return (v == null) ? null : v.getString(); + } catch (RepositoryException e) { + log.error("corrupt descriptor value: " + key, e); + return null; + } } /** * {@inheritDoc} */ public String[] getDescriptorKeys() { - String[] keys = repProps.keySet().toArray(new String[repProps.keySet().size()]); + String[] keys = repDescriptors.keySet().toArray(new String[repDescriptors.keySet().size()]); Arrays.sort(keys); return keys; } + /** + * {@inheritDoc} + */ public Value getDescriptorValue(String key) { - throw new UnsupportedOperationException( - "not implemented yet - see JCR-2062"); + DescriptorValue descVal = repDescriptors.get(key); + return (descVal != null) ? descVal.getValue() : null; } + /** + * {@inheritDoc} + */ public Value[] getDescriptorValues(String key) { - throw new UnsupportedOperationException( - "not implemented yet - see JCR-2062"); + DescriptorValue descVal = repDescriptors.get(key); + return (descVal != null) ? descVal.getValues() : null; } + /** + * {@inheritDoc} + */ public boolean isSingleValueDescriptor(String key) { - throw new UnsupportedOperationException( - "not implemented yet - see JCR-2062"); + DescriptorValue descVal = repDescriptors.get(key); + return (descVal != null && descVal.getValue() != null); } //------------------------------------------------------< SessionListener > @@ -1468,41 +1554,6 @@ } } - //--------------------------------------------------------< EventListener > - /** - * {@inheritDoc} - */ - public void onEvent(EventIterator events) { - // check status of this instance - if (disposed) { - // ignore, repository instance has been shut down - return; - } - - synchronized (repProps) { - while (events.hasNext()) { - Event event = events.nextEvent(); - long type = event.getType(); - if ((type & Event.NODE_ADDED) == Event.NODE_ADDED) { - nodesCount++; - repProps.setProperty(STATS_NODE_COUNT_PROPERTY, Long.toString(nodesCount)); - } - if ((type & Event.NODE_REMOVED) == Event.NODE_REMOVED) { - nodesCount--; - repProps.setProperty(STATS_NODE_COUNT_PROPERTY, Long.toString(nodesCount)); - } - if ((type & Event.PROPERTY_ADDED) == Event.PROPERTY_ADDED) { - propsCount++; - repProps.setProperty(STATS_PROP_COUNT_PROPERTY, Long.toString(propsCount)); - } - if ((type & Event.PROPERTY_REMOVED) == Event.PROPERTY_REMOVED) { - propsCount--; - repProps.setProperty(STATS_PROP_COUNT_PROPERTY, Long.toString(propsCount)); - } - } - } - } - //------------------------------------------< overridable factory methods > /** * Creates an instance of the {@link SessionImpl} class representing a @@ -1821,7 +1872,8 @@ // lock manager is lazily instantiated in order to avoid // 'chicken & egg' bootstrap problems if (lockMgr == null) { - lockMgr = new LockManagerImpl(getSystemSession(), fs); + lockMgr = + new LockManagerImpl(getSystemSession(), fs, executor); if (clusterNode != null && config.isClustered()) { lockChannel = clusterNode.createLockChannel(getName()); lockMgr.setEventChannel(lockChannel); @@ -2003,12 +2055,6 @@ * {@link org.apache.jackrabbit.core.state.SharedItemStateManager#createRootNodeState} */ - // register the repository as event listener for keeping repository statistics - wsp.getObservationManager().addEventListener(RepositoryImpl.this, - Event.NODE_ADDED | Event.NODE_REMOVED - | Event.PROPERTY_ADDED | Event.PROPERTY_REMOVED, - "/", true, null, null, false); - // register SearchManager as event listener SearchManager searchMgr = getSearchManager(); if (searchMgr != null) { @@ -2268,8 +2314,7 @@ synchronized (activeSessions) { // remove workspaces with active sessions - for (Iterator it = activeSessions.values().iterator(); it.hasNext();) { - SessionImpl ses = (SessionImpl) it.next(); + for (SessionImpl ses : activeSessions.values()) { wspNames.remove(ses.getWorkspace().getName()); } } @@ -2337,8 +2382,28 @@ } } - VersionManagerImpl getVersionManagerImpl() { - return vMgr; - } + /** + * Represents a Repository Descriptor Value (either Value or Value[]) + */ + protected final class DescriptorValue { + + private Value val; + private Value[] vals; + + protected DescriptorValue(Value val) { + this.val = val; + } + protected DescriptorValue(Value[] vals) { + this.vals = vals; + } + + protected Value getValue() { + return val; + } + + protected Value[] getValues() { + return vals != null ? vals : new Value[] {val}; + } + } } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Tue Sep 8 16:09:28 2009 @@ -16,48 +16,6 @@ */ package org.apache.jackrabbit.core; -import java.io.File; -import java.io.PrintStream; -import java.security.AccessControlException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.jcr.AccessDeniedException; -import javax.jcr.Credentials; -import javax.jcr.InvalidItemStateException; -import javax.jcr.Item; -import javax.jcr.ItemExistsException; -import javax.jcr.ItemNotFoundException; -import javax.jcr.LoginException; -import javax.jcr.NamespaceException; -import javax.jcr.NoSuchWorkspaceException; -import javax.jcr.Node; -import javax.jcr.PathNotFoundException; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.SimpleCredentials; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.ValueFactory; -import javax.jcr.Workspace; -import javax.jcr.lock.Lock; -import javax.jcr.lock.LockException; -import javax.jcr.nodetype.ConstraintViolationException; -import javax.jcr.nodetype.NoSuchNodeTypeException; -import javax.jcr.observation.EventListener; -import javax.jcr.observation.ObservationManager; -import javax.jcr.retention.RetentionManager; -import javax.jcr.security.AccessControlManager; -import javax.jcr.version.VersionException; -import javax.security.auth.Subject; - import org.apache.commons.collections.IteratorUtils; import org.apache.commons.collections.map.ReferenceMap; import org.apache.jackrabbit.api.JackrabbitSession; @@ -89,10 +47,12 @@ import org.apache.jackrabbit.core.state.SharedItemStateManager; import org.apache.jackrabbit.core.util.Dumpable; import org.apache.jackrabbit.core.value.ValueFactoryImpl; -import org.apache.jackrabbit.core.version.VersionManager; -import org.apache.jackrabbit.core.version.VersionManagerImpl; +import org.apache.jackrabbit.core.version.InternalVersionManager; +import org.apache.jackrabbit.core.version.InternalVersionManagerImpl; import org.apache.jackrabbit.core.xml.ImportHandler; import org.apache.jackrabbit.core.xml.SessionImporter; +import org.apache.jackrabbit.core.xml.AccessControlImporter; +import org.apache.jackrabbit.core.xml.ProtectedNodeImporter; import org.apache.jackrabbit.spi.Name; import org.apache.jackrabbit.spi.Path; import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver; @@ -107,6 +67,48 @@ import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; +import javax.jcr.AccessDeniedException; +import javax.jcr.Credentials; +import javax.jcr.InvalidItemStateException; +import javax.jcr.Item; +import javax.jcr.ItemExistsException; +import javax.jcr.ItemNotFoundException; +import javax.jcr.LoginException; +import javax.jcr.NamespaceException; +import javax.jcr.NoSuchWorkspaceException; +import javax.jcr.Node; +import javax.jcr.PathNotFoundException; +import javax.jcr.Property; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.ValueFactory; +import javax.jcr.Workspace; +import javax.jcr.ImportUUIDBehavior; +import javax.jcr.lock.Lock; +import javax.jcr.lock.LockException; +import javax.jcr.nodetype.ConstraintViolationException; +import javax.jcr.nodetype.NoSuchNodeTypeException; +import javax.jcr.observation.EventListener; +import javax.jcr.observation.ObservationManager; +import javax.jcr.retention.RetentionManager; +import javax.jcr.security.AccessControlManager; +import javax.jcr.version.VersionException; +import javax.security.auth.Subject; +import java.io.File; +import java.io.PrintStream; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * A SessionImpl ... */ @@ -198,7 +200,12 @@ /** * The version manager for this session */ - protected final VersionManager versionMgr; + protected final InternalVersionManager versionMgr; + + /** + * node type instance handler + */ + protected final NodeTypeInstanceHandler ntInstanceHandler; /** * Listeners (weak references) @@ -285,6 +292,7 @@ itemMgr = createItemManager(itemStateMgr, hierMgr); accessMgr = createAccessManager(subject, itemStateMgr.getHierarchyMgr()); versionMgr = createVersionManager(rep); + ntInstanceHandler = new NodeTypeInstanceHandler(userId); } /** @@ -302,7 +310,7 @@ * @return session item state manager */ protected SessionItemStateManager createSessionItemStateManager(LocalItemStateManager manager) { - return new SessionItemStateManager( + return SessionItemStateManager.createInstance( rep.getRootNodeId(), manager, rep.getNodeTypeRegistry()); } @@ -329,7 +337,7 @@ */ protected ItemManager createItemManager(SessionItemStateManager itemStateMgr, HierarchyManager hierMgr) { - return new ItemManager(itemStateMgr, hierMgr, this, + return ItemManager.createInstance(itemStateMgr, hierMgr, this, ntMgr.getRootNodeDefinition(), rep.getRootNodeId()); } @@ -338,7 +346,7 @@ * the repository version manager. * @return version manager */ - protected VersionManager createVersionManager(RepositoryImpl rep) + protected InternalVersionManager createVersionManager(RepositoryImpl rep) throws RepositoryException { return rep.getVersionManager(); @@ -476,11 +484,11 @@ } /** - * Returns the VersionManager associated with this session. + * Returns the InternalVersionManager associated with this session. * - * @return the VersionManager associated with this session + * @return the InternalVersionManager associated with this session */ - public VersionManager getVersionManager() { + public InternalVersionManager getInternalVersionManager() { return versionMgr; } @@ -497,6 +505,14 @@ } /** + * Returns the node type instance handler for this session + * @return the node type instance handler. + */ + public NodeTypeInstanceHandler getNodeTypeInstanceHandler() { + return ntInstanceHandler; + } + + /** * Sets the named attribute. If the value is null, then * the named attribute is removed. * @@ -643,7 +659,7 @@ */ public GarbageCollector createDataStoreGarbageCollector() throws RepositoryException { ArrayList pmList = new ArrayList(); - VersionManagerImpl vm = (VersionManagerImpl) rep.getVersionManager(); + InternalVersionManagerImpl vm = (InternalVersionManagerImpl) rep.getVersionManager(); PersistenceManager pm = vm.getPersistenceManager(); pmList.add(pm); String[] wspNames = rep.getWorkspaceNames(); @@ -781,6 +797,10 @@ * {@inheritDoc} */ public Workspace getWorkspace() { + return getWorkspaceImpl(); + } + + WorkspaceImpl getWorkspaceImpl() { return wsp; } @@ -1053,7 +1073,7 @@ // verify for both source and destination parent nodes that // - they are checked-out // - are not protected neither by node type constraints nor by retention/hold - int options = ItemValidator.CHECK_VERSIONING | ItemValidator.CHECK_LOCK | + int options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION; getValidator().checkRemove(srcParentNode, options, Permission.NONE); getValidator().checkModify(destParentNode, options, Permission.NONE); @@ -1098,7 +1118,7 @@ destParentNode.renameChildNode(srcName.getName(), index, targetId, destName.getName()); } else { // check shareable case - if (((NodeState) targetNode.getItemState()).isShareable()) { + if (targetNode.getNodeState().isShareable()) { String msg = "Moving a shareable node is not supported."; log.debug(msg); throw new UnsupportedRepositoryOperationException(msg); @@ -1150,11 +1170,12 @@ // verify that parent node is checked-out, not locked and not protected // by either node type constraints nor by some retention or hold. - int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_VERSIONING | + int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION; getValidator().checkModify(parent, options, Permission.NONE); - SessionImporter importer = new SessionImporter(parent, this, uuidBehavior); + ProtectedNodeImporter pi = new AccessControlImporter(this, this, false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW); + SessionImporter importer = new SessionImporter(parent, this, uuidBehavior, pi, null); return new ImportHandler(importer, this); } @@ -1528,13 +1549,69 @@ } /** - * @see javax.jcr.Session#hasCapability(String, Object, Map) + * @see javax.jcr.Session#hasCapability(String, Object, Object[]) * @since JCR 2.0 */ - public boolean hasCapability(String methodType, Object target, Map arguments) + public boolean hasCapability(String methodName, Object target, Object[] arguments) throws RepositoryException { - //TODO - throw new UnsupportedRepositoryOperationException("Not yet implemented"); + // value of this method (as currently spec'ed) to jcr api clients + // is rather limited... + + // here's therefore a minimal rather than best effort implementation; + // returning true is always fine according to the spec... + int options = ItemValidator.CHECK_CHECKED_OUT | ItemValidator.CHECK_LOCK | + ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION; + if (target instanceof Node) { + if (methodName.equals("addNode") + || methodName.equals("addMixin") + || methodName.equals("orderBefore") + || methodName.equals("removeMixin") + || methodName.equals("removeShare") + || methodName.equals("removeSharedSet") + || methodName.equals("setPrimaryType") + || methodName.equals("setProperty") + || methodName.equals("update")) { + return getValidator().canModify((ItemImpl) target, options, Permission.NONE); + } else if (methodName.equals("remove")) { + try { + getValidator().checkRemove((ItemImpl) target, options, Permission.NONE); + } catch (RepositoryException e) { + return false; + } + } + } else if (target instanceof Property) { + if (methodName.equals("setValue") + || methodName.equals("save")) { + return getValidator().canModify((ItemImpl) target, options, Permission.NONE); + } else if (methodName.equals("remove")) { + try { + getValidator().checkRemove((ItemImpl) target, options, Permission.NONE); + } catch (RepositoryException e) { + return false; + } + } + } else if (target instanceof Workspace) { + if (methodName.equals("clone") + || methodName.equals("copy") + || methodName.equals("createWorkspace") + || methodName.equals("deleteWorkspace") + || methodName.equals("getImportContentHandler") + || methodName.equals("importXML") + || methodName.equals("move")) { + // todo minimal, best effort checks (e.g. permissions for write methods etc) + } + } else if (target instanceof Session) { + if (methodName.equals("clone") + || methodName.equals("removeItem") + || methodName.equals("getImportContentHandler") + || methodName.equals("importXML") + || methodName.equals("save")) { + // todo minimal, best effort checks (e.g. permissions for write methods etc) + } + } + + // we're unable to evaluate capability, return true (staying on the safe side) + return true; } /** Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SystemSession.java Tue Sep 8 16:09:28 2009 @@ -19,6 +19,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; +import java.security.Principal; import javax.jcr.AccessDeniedException; import javax.jcr.PathNotFoundException; @@ -274,5 +275,19 @@ // cannot determine the effective policies for the system session. return new AccessControlPolicy[0]; } + + /** + * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#hasPrivileges(String, Set, Privilege[]) + */ + public boolean hasPrivileges(String absPath, Set principals, Privilege[] privileges) throws PathNotFoundException, RepositoryException { + throw new UnsupportedOperationException("not implemented"); + } + + /** + * @see org.apache.jackrabbit.api.security.JackrabbitAccessControlManager#getPrivileges(String, Set) + */ + public Privilege[] getPrivileges(String absPath, Set principals) throws PathNotFoundException, RepositoryException { + throw new UnsupportedOperationException("not implemented"); + } } } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java Tue Sep 8 16:09:28 2009 @@ -16,18 +16,17 @@ */ package org.apache.jackrabbit.core; -import java.util.HashMap; - import javax.jcr.AccessDeniedException; import javax.jcr.InvalidItemStateException; import javax.jcr.ItemExistsException; -import javax.jcr.ItemNotFoundException; import javax.jcr.NamespaceRegistry; import javax.jcr.NoSuchWorkspaceException; import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.Node; +import javax.jcr.NodeIterator; import javax.jcr.lock.LockException; import javax.jcr.nodetype.ConstraintViolationException; import javax.jcr.nodetype.NodeTypeManager; @@ -35,7 +34,6 @@ import javax.jcr.query.QueryManager; import javax.jcr.version.Version; import javax.jcr.version.VersionException; -import javax.jcr.version.VersionHistory; import javax.jcr.version.VersionManager; import org.apache.jackrabbit.api.JackrabbitWorkspace; @@ -52,10 +50,6 @@ import org.apache.jackrabbit.core.retention.RetentionRegistry; import org.apache.jackrabbit.core.state.LocalItemStateManager; import org.apache.jackrabbit.core.state.SharedItemStateManager; -import org.apache.jackrabbit.core.version.DateVersionSelector; -import org.apache.jackrabbit.core.version.JcrVersionManagerImpl; -import org.apache.jackrabbit.core.version.VersionImpl; -import org.apache.jackrabbit.core.version.VersionSelector; import org.apache.jackrabbit.core.xml.ImportHandler; import org.apache.jackrabbit.core.xml.Importer; import org.apache.jackrabbit.core.xml.WorkspaceImporter; @@ -127,7 +121,7 @@ /** * The API Version manager for this workspace */ - protected JcrVersionManagerImpl versionMgr; + protected VersionManagerImpl versionMgr; /** * The internal manager used to evaluate effective retention policies and @@ -216,7 +210,17 @@ tmpSession = rep.createSession(session.getSubject(), name); WorkspaceImpl newWsp = (WorkspaceImpl) tmpSession.getWorkspace(); - newWsp.clone(srcWorkspace, "/", "/", false); + // Workspace#clone(String, String, String, booelan) doesn't + // allow to clone to "/"... + //newWsp.clone(srcWorkspace, "/", "/", false); + Node root = session.getRootNode(); + for (NodeIterator it = root.getNodes(); it.hasNext(); ) { + Node child = it.nextNode(); + // skip nodes that already exist in newly created workspace + if (!tmpSession.nodeExists(child.getPath())) { + newWsp.clone(srcWorkspace, child.getPath(), child.getPath(), false); + } + } } finally { if (tmpSession != null) { // we don't need the temporary session anymore, logout @@ -253,10 +257,13 @@ /** * @see javax.jcr.Workspace#getVersionManager() */ - public VersionManager getVersionManager() - throws UnsupportedRepositoryOperationException, RepositoryException { + public VersionManager getVersionManager() { + return getVersionManagerImpl(); + } + + VersionManagerImpl getVersionManagerImpl() { if (versionMgr == null) { - versionMgr = new JcrVersionManagerImpl(session); + versionMgr = new VersionManagerImpl(session, stateMgr, hierMgr); } return versionMgr; } @@ -784,90 +791,14 @@ /** * {@inheritDoc} */ + @Deprecated public void restore(Version[] versions, boolean removeExisting) throws ItemExistsException, UnsupportedRepositoryOperationException, VersionException, LockException, InvalidItemStateException, RepositoryException { - - // todo: perform restore operations direct on the node states - // check state of this instance sanityCheck(); - - // add all versions to map of versions to restore - final HashMap toRestore = new HashMap(); - for (Version v : versions) { - VersionHistory vh = v.getContainingHistory(); - // check for collision - if (toRestore.containsKey(vh.getUUID())) { - throw new VersionException("Unable to restore. Two or more versions have same version history."); - } - toRestore.put(vh.getUUID(), (VersionImpl) v); - } - - // create a version selector to the set of versions - VersionSelector vsel = new VersionSelector() { - public Version select(VersionHistory versionHistory) throws RepositoryException { - // try to select version as specified - Version v = toRestore.get(versionHistory.getUUID()); - if (v == null) { - // select latest one - v = DateVersionSelector.selectByDate(versionHistory, null); - } - return v; - } - }; - - // check for pending changes - if (session.hasPendingChanges()) { - String msg = "Unable to restore version. Session has pending changes."; - log.debug(msg); - throw new InvalidItemStateException(msg); - } - // TODO: add checks for lock/hold... - boolean success = false; - try { - // now restore all versions that have a node in the ws - int numRestored = 0; - while (toRestore.size() > 0) { - Version[] restored = null; - for (VersionImpl v : toRestore.values()) { - try { - NodeImpl node = (NodeImpl) session.getNodeById(v.getInternalFrozenNode().getFrozenId()); - restored = node.internalRestore(v, vsel, removeExisting); - // remove restored versions from set - for (Version r : restored) { - toRestore.remove(r.getContainingHistory().getUUID()); - } - numRestored += restored.length; - break; - } catch (ItemNotFoundException e) { - // ignore - } - } - if (restored == null) { - if (numRestored == 0) { - throw new VersionException("Unable to restore. At least one version needs" - + " existing versionable node in workspace."); - } else { - throw new VersionException("Unable to restore. All versions with non" - + " existing versionable nodes need parent."); - } - } - } - session.save(); - success = true; - } finally { - if (!success) { - // revert session - try { - log.debug("reverting changes applied during restore..."); - session.refresh(false); - } catch (RepositoryException e) { - log.error("Error while reverting changes applied during restore.", e); - } - } - } + getVersionManager().restore(versions, removeExisting); } /** Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java Tue Sep 8 16:09:28 2009 @@ -24,9 +24,9 @@ import org.apache.jackrabbit.core.security.authentication.AuthContext; import org.apache.jackrabbit.core.state.SharedItemStateManager; import org.apache.jackrabbit.core.state.XAItemStateManager; -import org.apache.jackrabbit.core.version.VersionManager; -import org.apache.jackrabbit.core.version.VersionManagerImpl; -import org.apache.jackrabbit.core.version.XAVersionManager; +import org.apache.jackrabbit.core.version.InternalVersionManager; +import org.apache.jackrabbit.core.version.InternalVersionManagerImpl; +import org.apache.jackrabbit.core.version.InternalXAVersionManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,7 +54,8 @@ /** * Global transactions */ - private static final Map txGlobal = Collections.synchronizedMap(new HashMap()); + private static final Map txGlobal = + Collections.synchronizedMap(new HashMap()); /** * System property specifying the default Transaction Timeout @@ -133,7 +134,7 @@ private void init() throws RepositoryException { XAItemStateManager stateMgr = (XAItemStateManager) wsp.getItemStateManager(); XALockManager lockMgr = (XALockManager) getLockManager(); - XAVersionManager versionMgr = (XAVersionManager) getVersionManager(); + InternalXAVersionManager versionMgr = (InternalXAVersionManager) getInternalVersionManager(); /** * Create array that contains all resources that participate in this @@ -169,11 +170,11 @@ /** * {@inheritDoc} */ - protected VersionManager createVersionManager(RepositoryImpl rep) + protected InternalVersionManager createVersionManager(RepositoryImpl rep) throws RepositoryException { - VersionManagerImpl vMgr = (VersionManagerImpl) rep.getVersionManager(); - return new XAVersionManager(vMgr, rep.getNodeTypeRegistry(), this, rep.getItemStateCacheFactory()); + InternalVersionManagerImpl vMgr = (InternalVersionManagerImpl) rep.getVersionManager(); + return new InternalXAVersionManager(vMgr, rep.getNodeTypeRegistry(), this, rep.getItemStateCacheFactory()); } /** @@ -386,9 +387,7 @@ */ public synchronized void associate(TransactionContext tx) { this.tx = tx; - - for (int i = 0; i < txResources.length; i++) { - InternalXAResource txResource = txResources[i]; + for (InternalXAResource txResource : txResources) { txResource.associate(tx); } } @@ -411,9 +410,9 @@ super.logout(); // dispose the caches try { - ((XAVersionManager) versionMgr).close(); + ((InternalXAVersionManager) versionMgr).close(); } catch (Exception e) { - log.warn("error while closing XAVersionManager", e); + log.warn("error while closing InternalXAVersionManager", e); } } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java Tue Sep 8 16:09:28 2009 @@ -16,8 +16,6 @@ */ package org.apache.jackrabbit.core; -import java.util.Iterator; - import org.apache.jackrabbit.core.id.ItemId; import org.apache.jackrabbit.core.id.NodeId; import org.apache.jackrabbit.core.state.ChildNodeEntry; @@ -102,10 +100,7 @@ Name name, int index) { // check removed child node entries first - Iterator iter = parent.getRemovedChildNodeEntries().iterator(); - while (iter.hasNext()) { - ChildNodeEntry entry = - (ChildNodeEntry) iter.next(); + for (ChildNodeEntry entry : parent.getRemovedChildNodeEntries()) { if (entry.getName().equals(name) && entry.getIndex() == index) { return entry; @@ -124,10 +119,7 @@ protected ChildNodeEntry getChildNodeEntry(NodeState parent, NodeId id) { // check removed child node entries first - Iterator iter = parent.getRemovedChildNodeEntries().iterator(); - while (iter.hasNext()) { - ChildNodeEntry entry = - (ChildNodeEntry) iter.next(); + for (ChildNodeEntry entry : parent.getRemovedChildNodeEntries()) { if (entry.getId().equals(id)) { return entry; } Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ChangeLogRecord.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ChangeLogRecord.java?rev=812570&r1=812569&r2=812570&view=diff ============================================================================== --- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ChangeLogRecord.java (original) +++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ChangeLogRecord.java Tue Sep 8 16:09:28 2009 @@ -99,7 +99,7 @@ /** * List of EventStates. */ - private List events; + private List events; /** * The user data. @@ -114,7 +114,7 @@ /** * Last used session for event sources. */ - private Session lastSession; + private ClusterSession lastSession; /** * Create a new instance of this class. Used when serializing. @@ -126,7 +126,7 @@ * @param timestamp when the changes for this record were persisted. * @param userData the user data associated with these changes. */ - public ChangeLogRecord(ChangeLog changes, List events, + public ChangeLogRecord(ChangeLog changes, List events, Record record, String workspace, long timestamp, String userData) { super(record, workspace); @@ -149,7 +149,7 @@ this.identifier = identifier; this.changes = new ChangeLog(); - this.events = new ArrayList(); + this.events = new ArrayList(); } /** @@ -276,16 +276,16 @@ Path.Element childRelPath = record.readPathElement(); Name ntName = record.readQName(); - Set mixins = new HashSet(); + Set mixins = new HashSet(); int mixinCount = record.readInt(); for (int i = 0; i < mixinCount; i++) { mixins.add(record.readQName()); } String userId = record.readString(); - Map info = null; + Map info = null; if (type == Event.NODE_MOVED) { - info = new HashMap(); + info = new HashMap(); // read info map int infoSize = record.readInt(); for (int i = 0; i < infoSize; i++) { @@ -325,7 +325,7 @@ */ private EventState createEventState(int type, NodeId parentId, Path parentPath, NodeId childId, Path.Element childRelPath, - Name ntName, Set mixins, String userId) { + Name ntName, Set mixins, String userId) { switch (type) { case Event.NODE_ADDED: return EventState.childNodeAdded(parentId, parentPath, childId, childRelPath, @@ -358,7 +358,7 @@ * @return session */ private Session getOrCreateSession(String userId) { - if (lastSession == null || !lastSession.getUserID().equals(userId)) { + if (lastSession == null || !lastSession.isUserId(userId)) { lastSession = new ClusterSession(userId); } return lastSession; @@ -392,9 +392,7 @@ } } - Iterator iter = events.iterator(); - while (iter.hasNext()) { - EventState event = (EventState) iter.next(); + for (EventState event : events) { writeEventRecord(event); } } @@ -466,22 +464,21 @@ record.writePathElement(event.getChildRelPath()); record.writeQName(event.getNodeType()); - Set mixins = event.getMixinNames(); + Set mixins = event.getMixinNames(); record.writeInt(mixins.size()); - Iterator iter = mixins.iterator(); + Iterator iter = mixins.iterator(); while (iter.hasNext()) { - record.writeQName((Name) iter.next()); + record.writeQName(iter.next()); } record.writeString(event.getUserId()); if (event.getType() == Event.NODE_MOVED) { // write info map - Map info = event.getInfo(); + Map info = event.getInfo(); record.writeInt(info.size()); - for (Iterator it = info.entrySet().iterator(); it.hasNext(); ) { - Map.Entry entry = (Map.Entry) it.next(); - String key = (String) entry.getKey(); - InternalValue value = (InternalValue) entry.getValue(); + for (Map.Entry entry : info.entrySet()) { + String key = entry.getKey(); + InternalValue value = entry.getValue(); record.writeString(key); if (value == null) { // use undefined for null value @@ -515,7 +512,7 @@ * * @return events */ - public List getEvents() { + public List getEvents() { return Collections.unmodifiableList(events); }