You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2006/07/12 15:33:27 UTC
svn commit: r421270 [17/23] - in /jackrabbit/trunk/contrib/spi: ./ commons/
commons/src/ commons/src/main/ commons/src/main/java/
commons/src/main/java/org/ commons/src/main/java/org/apache/
commons/src/main/java/org/apache/jackrabbit/ commons/src/main...
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientChangeLog.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientChangeLog.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateListener.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateListener.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateListener.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,46 @@
+/*
+ * 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.jcr2spi.state;
+
+/**
+ * <code>TransientItemStateListener</code> extends {@link ItemStateListener}
+ * and adds to callbacks: {@link #stateOverlaid(ItemState)} and
+ * {@link #stateUncovering(ItemState)}.
+ */
+public interface TransientItemStateListener extends ItemStateListener {
+
+ /**
+ * Called when an <code>ItemState</code> has been overlaid by some
+ * other state that now takes its identity. This notification is sent
+ * on the state being overlaid.
+ *
+ * @param overlayer the <code>ItemState</code> that overlays this state
+ */
+ public void stateOverlaid(ItemState overlayer);
+
+ /**
+ * Called when an <code>ItemState</code> is about to no longer overlay some
+ * other item state. This notification is sent on the state overlaying
+ * another state.
+ *
+ * @param overlayer the <code>ItemState</code> that overlaid another item
+ * state. To get the overlaid state, invoke {@link
+ * ItemState#getOverlayedState()}
+ */
+ public void stateUncovering(ItemState overlayer);
+
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateListener.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,144 @@
+/*
+ * 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.jcr2spi.state;
+
+import org.apache.jackrabbit.jcr2spi.operation.Operation;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.name.QName;
+
+import java.util.Iterator;
+
+/**
+ * <code>TransientItemStateManager</code> ...
+ */
+interface TransientItemStateManager extends ItemStateManager {
+
+ /**
+ * @return the number of entries
+ */
+ public int getEntriesCount();
+
+ /**
+ * @return the number of entries in attic
+ */
+ public int getEntriesInAtticCount();
+
+ /**
+ * @return an iterator over all entries
+ */
+ public Iterator getEntries();
+
+ /**
+ * @return an iterator over all entries in attic
+ */
+ public Iterator getEntriesInAttic();
+
+ /**
+ * Adds an operation to this transient item state manager.
+ *
+ * @param operationType the operation.
+ * @throws IllegalStateException if <code>operationType</code> is not
+ * compatible with the previously executed operation (invalid sequence of
+ * operations).
+ */
+ public void addOperation(Operation operationType) throws IllegalStateException;
+
+ //----------------< methods for creating & discarding ItemState instances >
+
+ /**
+ * DIFF JACKRABBIT: does not throw ItemStateException
+ * Creates a new transient {@link NodeState} that does not overlay any other
+ * {@link NodeState}.
+ *
+ * @param id the <code>NodeId</code> of the new node state.
+ * @param nodeTypeName name of the node type of the new node state.
+ * @param parentId the parent id of the new node state.
+ * @return a new transient {@link NodeState}.
+ */
+ NodeState createNodeState(NodeId id, QName nodeTypeName,
+ NodeId parentId);
+
+ /**
+ * DIFF JACKRABBIT: does not throw ItemStateException
+ * @param overlayedState
+ * @return
+ */
+ NodeState createNodeState(NodeState overlayedState);
+
+ /**
+ * DIFF JACKRABBIT: does not throw ItemStateException
+ * @param parentId
+ * @param propName
+ * @return
+ */
+ PropertyState createPropertyState(NodeId parentId, QName propName);
+
+ /**
+ * DIFF JACKRABBIT: does not throw ItemStateException
+ * @param overlayedState
+ * @return
+ */
+ PropertyState createPropertyState(PropertyState overlayedState);
+
+ /**
+ * Disposes the specified instance, i.e. discards it and removes it from
+ * the map.
+ *
+ * @param state the <code>ItemState</code> instance that should be disposed
+ * @see ItemState#discard()
+ */
+ public void disposeItemState(ItemState state);
+
+ /**
+ * Transfers the specified instance from the 'active' map to the attic.
+ *
+ * @param state the <code>ItemState</code> instance that should be moved to
+ * the attic
+ */
+ public void moveItemStateToAttic(ItemState state);
+
+ /**
+ * Disposes the specified instance in the attic, i.e. discards it and
+ * removes it from the attic.
+ *
+ * @param state the <code>ItemState</code> instance that should be disposed
+ * @see ItemState#discard()
+ */
+ public void disposeItemStateInAttic(ItemState state);
+
+ /**
+ * Disposes all transient item states in the cache and in the attic.
+ */
+ public void disposeAllItemStates();
+
+ /**
+ * Return the attic item state provider that holds all items
+ * moved into the attic.
+ *
+ * @return attic
+ */
+ public ItemStateManager getAttic();
+
+ //-----------------------------------< methods for controlling operations >
+
+ /**
+ * Disposes a collection of {@link org.apache.jackrabbit.jcr2spi.operation.Operation}s.
+ *
+ * @param operations the operations.
+ */
+ public void disposeOperations(Iterator operations);
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/TransientItemStateManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/UpdatableItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/UpdatableItemStateManager.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/UpdatableItemStateManager.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/UpdatableItemStateManager.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,50 @@
+/*
+ * 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.jcr2spi.state;
+
+import org.apache.jackrabbit.jcr2spi.operation.Operation;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Identifies an <code>ItemStateManager</code> that allows updating
+ * items.
+ */
+public interface UpdatableItemStateManager extends ItemStateManager {
+
+ /**
+ * Executes the given operation and modifies the affected item states accordingly.
+ *
+ * @param operation
+ * @throws RepositoryException
+ */
+ public void execute(Operation operation) throws RepositoryException;
+
+ /**
+ * Executes the operations passed with the given change log and modifies the
+ * affected item states accordingly.
+ *
+ * @param changes
+ * @throws RepositoryException
+ */
+ public void execute(ChangeLog changes) throws RepositoryException;
+
+ /**
+ * Disposes this <code>UpdatableItemStateManager</code> and frees resources.
+ */
+ void dispose();
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/UpdatableItemStateManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/UpdatableItemStateManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/Dumpable.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/Dumpable.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/Dumpable.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/Dumpable.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,35 @@
+/*
+ * 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.jcr2spi.util;
+
+import java.io.PrintStream;
+
+/**
+ * Utility interface for internal use.
+ * <p/>
+ * A <code>Dumpable</code> object supports dumping its state in a human readable
+ * format for diagnostic/debug purposes.
+ */
+public interface Dumpable {
+ /**
+ * Dumps the state of this instance in a human readable format for
+ * diagnostic purposes.
+ *
+ * @param ps stream to dump state to
+ */
+ void dump(PrintStream ps);
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/Dumpable.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/Dumpable.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/ReferenceChangeTracker.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/ReferenceChangeTracker.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/ReferenceChangeTracker.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/ReferenceChangeTracker.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,117 @@
+/*
+ * 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.jcr2spi.util;
+
+import org.apache.jackrabbit.jcr2spi.state.PropertyState;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.value.QValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * Simple helper class that can be used to keep track of uuid mappings
+ * (e.g. if the uuid of an imported or copied node is mapped to a new uuid)
+ * and processed (e.g. imported or copied) reference properties that might
+ * need correcting depending on the uuid mappings.
+ */
+public class ReferenceChangeTracker {
+
+ private static Logger log = LoggerFactory.getLogger(ReferenceChangeTracker.class);
+
+ /**
+ * mapping <original uuid> to <new uuid> of mix:referenceable nodes
+ */
+ private final HashMap uuidMap = new HashMap();
+ /**
+ * list of processed reference properties that might need correcting
+ */
+ private final ArrayList references = new ArrayList();
+
+ /**
+ * Creates a new instance.
+ */
+ public ReferenceChangeTracker() {
+ }
+
+ /**
+ * Resets all internal state.
+ */
+ public void clear() {
+ uuidMap.clear();
+ references.clear();
+ }
+
+ /**
+ * Store the given uuid mapping for later lookup using
+ * <code>#adjustReferences(UpdatableItemStateManager, ItemStateValidator)</code>.
+ *
+ * @param oldNodeId old nodeId
+ * @param newNodeId new nodeId
+ */
+ public void mappedNodeIds(NodeId oldNodeId, NodeId newNodeId) {
+ if (oldNodeId.equals(newNodeId) || oldNodeId.getUUID() == null) {
+ // only remember if uuid exists and has changed
+ return;
+ }
+ uuidMap.put(oldNodeId.getUUID(), newNodeId.getUUID());
+ }
+
+ /**
+ * Returns the new UUID to which <code>oldUUID</code> has been mapped
+ * or <code>null</code> if no such mapping exists.
+ *
+ * @param oldReference old uuid represented by the given <code>QValue</code>
+ * @return mapped new QValue of the reference value or <code>null</code> if no such mapping exists
+ * @see #mappedNodeIds(NodeId,NodeId)
+ */
+ public QValue getMappedReference(QValue oldReference) {
+ QValue remapped = null;
+ if (oldReference.getType() == PropertyType.REFERENCE) {
+ try {
+ String oldValue = oldReference.getString();
+ String newValue = uuidMap.get(oldValue).toString();
+ remapped = QValue.create(newValue, PropertyType.REFERENCE);
+ } catch (RepositoryException e) {
+ log.error("Unexpected error while creating internal value.", e);
+ }
+ }
+ return remapped;
+ }
+
+ // DIFF JR: meth. signature: PropertyState instead of Object
+ /**
+ * Store the given reference property for later resolution.
+ *
+ * @param refPropertyState reference property state
+ */
+ public void processedReference(PropertyState refPropertyState) {
+ // make sure only not-null states of type Reference are remembered
+ if (refPropertyState != null && refPropertyState.getType() == PropertyType.REFERENCE) {
+ references.add(refPropertyState);
+ }
+ }
+
+ public Iterator getReferences() {
+ return references.iterator();
+ }
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/ReferenceChangeTracker.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/util/ReferenceChangeTracker.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/DefaultVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/DefaultVersionManager.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/DefaultVersionManager.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/DefaultVersionManager.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,62 @@
+/*
+ * 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.jcr2spi.version;
+
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import org.apache.jackrabbit.spi.NodeId;
+import java.util.Collection;
+
+/**
+ * <code>DefaultVersionManager</code>...
+ */
+public class DefaultVersionManager implements VersionManager {
+
+ private static Logger log = LoggerFactory.getLogger(DefaultVersionManager.class);
+
+ public void checkin(NodeId nodeId) throws RepositoryException {
+ throw new UnsupportedRepositoryOperationException("Versioning ist not supported by this repository.");
+ }
+
+ public void checkout(NodeId nodeId) throws RepositoryException {
+ throw new UnsupportedRepositoryOperationException("Versioning ist not supported by this repository.");
+ }
+
+ public boolean isCheckedOut(NodeId nodeId) throws RepositoryException {
+ log.debug("Versioning is not supported by this repository.");
+ return true;
+ }
+
+ public void restore(NodeId nodeId, NodeId versionId, boolean removeExisting) throws RepositoryException {
+ throw new UnsupportedRepositoryOperationException("Versioning ist not supported by this repository.");
+ }
+
+ public void restore(NodeId[] versionIds, boolean removeExisting) throws RepositoryException {
+ throw new UnsupportedRepositoryOperationException("Versioning ist not supported by this repository.");
+ }
+
+ public Collection merge(NodeId nodeId, String workspaceName, boolean bestEffort) throws RepositoryException {
+ throw new UnsupportedRepositoryOperationException("Versioning ist not supported by this repository.");
+ }
+
+ public void resolveMergeConflict(NodeId nodeId, NodeId versionId, boolean done) throws RepositoryException {
+ throw new UnsupportedRepositoryOperationException("Versioning ist not supported by this repository.");
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/DefaultVersionManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/DefaultVersionManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,405 @@
+/*
+ * 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.jcr2spi.version;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.jcr2spi.NodeImpl;
+import org.apache.jackrabbit.jcr2spi.ItemManager;
+import org.apache.jackrabbit.jcr2spi.SessionImpl;
+import org.apache.jackrabbit.jcr2spi.ItemLifeCycleListener;
+import org.apache.jackrabbit.jcr2spi.LazyItemIterator;
+import org.apache.jackrabbit.jcr2spi.operation.AddLabel;
+import org.apache.jackrabbit.jcr2spi.operation.Operation;
+import org.apache.jackrabbit.jcr2spi.operation.RemoveLabel;
+import org.apache.jackrabbit.jcr2spi.operation.Remove;
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateException;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.name.NameException;
+import org.apache.jackrabbit.name.NoPrefixDeclaredException;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.name.Path;
+import org.apache.jackrabbit.spi.PropertyId;
+
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionIterator;
+import javax.jcr.version.VersionException;
+import javax.jcr.RepositoryException;
+import javax.jcr.ReferentialIntegrityException;
+import javax.jcr.AccessDeniedException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.nodetype.NodeDefinition;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * <code>VersionHistoryImpl</code>...
+ */
+public class VersionHistoryImpl extends NodeImpl implements VersionHistory {
+
+ private static Logger log = LoggerFactory.getLogger(VersionHistoryImpl.class);
+
+ private final NodeState vhState;
+ private final NodeState labelNodeState;
+
+ public VersionHistoryImpl(ItemManager itemMgr, SessionImpl session,
+ NodeState state, NodeDefinition definition,
+ ItemLifeCycleListener[] listeners) throws VersionException {
+ super(itemMgr, session, state, definition, listeners);
+
+ // retrieve nodestate of the jcr:versionLabels node
+ vhState = state;
+ if (vhState.hasChildNodeEntry(QName.JCR_VERSIONLABELS)) {
+ NodeState.ChildNodeEntry lnEntry = vhState.getChildNodeEntry(QName.JCR_VERSIONLABELS, Path.INDEX_DEFAULT);
+ try {
+ labelNodeState = (NodeState) itemStateMgr.getItemState(lnEntry.getId());
+ } catch (ItemStateException e) {
+ throw new VersionException("nt:versionHistory requires a mandatory, autocreated child node jcr:versionLabels.");
+ }
+ } else {
+ throw new VersionException("nt:versionHistory requires a mandatory, autocreated child node jcr:versionLabels.");
+ }
+ }
+
+ //-----------------------------------------------------< VersionHistory >---
+ /**
+ *
+ * @return
+ * @throws RepositoryException
+ * @see VersionHistory#getVersionableUUID()
+ */
+ public String getVersionableUUID() throws RepositoryException {
+ return getProperty(QName.JCR_VERSIONABLEUUID).getString();
+ }
+
+ /**
+ *
+ * @return
+ * @throws RepositoryException
+ * @see VersionHistory#getRootVersion()
+ */
+ public Version getRootVersion() throws RepositoryException {
+ NodeId vId = vhState.getChildNodeEntry(QName.JCR_ROOTVERSION, Path.INDEX_DEFAULT).getId();
+ return (Version) itemMgr.getItem(vId);
+ }
+
+ /**
+ *
+ * @return
+ * @throws RepositoryException
+ * @see VersionHistory#getAllVersions()
+ */
+ public VersionIterator getAllVersions() throws RepositoryException {
+ Iterator childIter = vhState.getChildNodeEntries().iterator();
+ Set versionIds = new HashSet();
+
+ // all child-nodes except from jcr:versionLabels point to Versions.
+ while (childIter.hasNext()) {
+ NodeState.ChildNodeEntry entry = (NodeState.ChildNodeEntry) childIter.next();
+ if (!QName.JCR_VERSIONLABELS.equals(entry.getName())) {
+ versionIds.add(entry.getId());
+ }
+ }
+ return new LazyItemIterator(itemMgr, versionIds);
+ }
+
+ /**
+ *
+ * @param versionName
+ * @return
+ * @throws VersionException
+ * @throws RepositoryException
+ * @see VersionHistory#getVersion(String)
+ */
+ public Version getVersion(String versionName) throws VersionException, RepositoryException {
+ NodeId vId = getVersionId(versionName);
+ return (Version) itemMgr.getItem(vId);
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws RepositoryException
+ * @see VersionHistory#getVersionByLabel(String)
+ */
+ public Version getVersionByLabel(String label) throws RepositoryException {
+ NodeId vId = getVersionIdByLabel(label);
+ return (Version) itemMgr.getItem(vId);
+ }
+
+ /**
+ *
+ * @param versionName
+ * @param label
+ * @param moveLabel
+ * @throws VersionException
+ * @throws RepositoryException
+ * @see VersionHistory#addVersionLabel(String, String, boolean)
+ */
+ public void addVersionLabel(String versionName, String label, boolean moveLabel) throws VersionException, RepositoryException {
+ QName qLabel = getQLabel(label);
+ // TODO: ev. delegate to versionmanager
+ Operation op = AddLabel.create(vhState.getNodeId(), getVersionId(versionName), qLabel, moveLabel);
+ itemStateMgr.execute(op);
+ }
+
+ /**
+ *
+ * @param label
+ * @throws VersionException
+ * @throws RepositoryException
+ * @see VersionHistory#removeVersionLabel(String)
+ */
+ public void removeVersionLabel(String label) throws VersionException, RepositoryException {
+ QName qLabel = getQLabel(label);
+ // TODO: ev. delegate to versionmanager
+ Operation op = RemoveLabel.create(vhState.getNodeId(), getVersionIdByLabel(label), qLabel);
+ itemStateMgr.execute(op);
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws RepositoryException
+ * @see VersionHistory#hasVersionLabel(String)
+ */
+ public boolean hasVersionLabel(String label) throws RepositoryException {
+ QName l = getQLabel(label);
+ QName[] qLabels = getQLabels();
+ for (int i = 0; i < qLabels.length; i++) {
+ if (qLabels[i].equals(l)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ * @param version
+ * @param string
+ * @return
+ * @throws VersionException
+ * @throws RepositoryException
+ * @see VersionHistory#hasVersionLabel(Version, String)
+ */
+ public boolean hasVersionLabel(Version version, String label) throws VersionException, RepositoryException {
+ checkValidVersion(version);
+ String vUUID = version.getUUID();
+ QName l = getQLabel(label);
+
+ QName[] qLabels = getQLabels();
+ for (int i = 0; i < qLabels.length; i++) {
+ if (qLabels[i].equals(l)) {
+ NodeId vId = getVersionIdByLabel(qLabels[i]);
+ return vUUID.equals(vId.getUUID());
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ * @return
+ * @throws RepositoryException
+ * @see VersionHistory#getVersionLabels()
+ */
+ public String[] getVersionLabels() throws RepositoryException {
+ QName[] qLabels = getQLabels();
+ String[] labels = new String[qLabels.length];
+
+ for (int i = 0; i < qLabels.length; i++) {
+ try {
+ labels[i] = session.getNamespaceResolver().getJCRName(qLabels[i]);
+ } catch (NoPrefixDeclaredException e) {
+ // unexpected error. should not occur.
+ throw new RepositoryException(e);
+ }
+ }
+ return labels;
+ }
+
+ /**
+ *
+ * @param version
+ * @return
+ * @throws VersionException
+ * @throws RepositoryException
+ * @see VersionHistory#getVersionLabels(Version)
+ */
+ public String[] getVersionLabels(Version version) throws VersionException, RepositoryException {
+ checkValidVersion(version);
+ String vUUID = version.getUUID();
+
+ List vlabels = new ArrayList();
+ QName[] qLabels = getQLabels();
+ for (int i = 0; i < qLabels.length; i++) {
+ NodeId vId = getVersionIdByLabel(qLabels[i]);
+ if (vUUID.equals(vId.getUUID())) {
+ try {
+ vlabels.add(session.getNamespaceResolver().getJCRName(qLabels[i]));
+ } catch (NoPrefixDeclaredException e) {
+ // should never occur
+ throw new RepositoryException("Unexpected error while accessing version label", e);
+ }
+ }
+ }
+ return (String[]) vlabels.toArray(new String[vlabels.size()]);
+ }
+
+ /**
+ *
+ * @param versionName
+ * @throws ReferentialIntegrityException
+ * @throws AccessDeniedException
+ * @throws UnsupportedRepositoryOperationException
+ * @throws VersionException
+ * @throws RepositoryException
+ * @see VersionHistory#removeVersion(String)
+ */
+ public void removeVersion(String versionName) throws ReferentialIntegrityException, AccessDeniedException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+ try {
+ NodeId vId = getVersionId(versionName);
+ NodeState vState = (NodeState) itemStateMgr.getItemState(vId);
+
+ // TODO: ev. delegate to versionmanager
+ Operation rm = Remove.create(vState);
+ itemStateMgr.execute(rm);
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ //---------------------------------------------------------------< Item >---
+ /**
+ *
+ * @param otherItem
+ * @return
+ * @see Item#isSame(Item)
+ */
+ public boolean isSame(Item otherItem) {
+ if (otherItem instanceof VersionHistoryImpl) {
+ // since all version histories are referenceable, protected and live
+ // in the same workspace, a simple comparison of the ids is sufficient
+ VersionHistoryImpl other = ((VersionHistoryImpl) otherItem);
+ return other.getId().equals(getId());
+ }
+ return false;
+ }
+
+ //------------------------------------------------------------< private >---
+ /**
+ *
+ * @return
+ */
+ private QName[] getQLabels() {
+ Set labelQNames = labelNodeState.getPropertyNames();
+ return (QName[]) labelQNames.toArray(new QName[labelQNames.size()]);
+ }
+
+ /**
+ *
+ * @param versionName
+ * @return
+ * @throws VersionException
+ * @throws RepositoryException
+ */
+ private NodeId getVersionId(String versionName) throws VersionException, RepositoryException {
+ try {
+ QName vQName = session.getNamespaceResolver().getQName(versionName);
+ NodeState.ChildNodeEntry vEntry = vhState.getChildNodeEntry(vQName, Path.INDEX_DEFAULT);
+ if (vEntry == null) {
+ throw new VersionException("Version '" + versionName + "' does not exist in this version history.");
+ } else {
+ return vEntry.getId();
+ }
+ } catch (NameException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws VersionException
+ * @throws RepositoryException
+ */
+ private NodeId getVersionIdByLabel(String label) throws VersionException, RepositoryException {
+ QName qLabel = getQLabel(label);
+ return getVersionIdByLabel(qLabel);
+ }
+
+ /**
+ *
+ * @param qLabel
+ * @return
+ * @throws VersionException
+ * @throws RepositoryException
+ */
+ private NodeId getVersionIdByLabel(QName qLabel) throws VersionException, RepositoryException {
+ if (labelNodeState.hasPropertyName(qLabel)) {
+ // retrieve reference property value -> and convert it to a NodeId
+ PropertyId pId = labelNodeState.getPropertyId(qLabel);
+ Node version = ((Property) itemMgr.getItem(pId)).getNode();
+ return (NodeId) session.getHierarchyManager().getItemId(version);
+ } else {
+ throw new VersionException("Version with label '" + qLabel + "' does not exist.");
+ }
+ }
+
+ /**
+ *
+ * @param label
+ * @return
+ * @throws RepositoryException
+ */
+ private QName getQLabel(String label) throws RepositoryException {
+ try {
+ return session.getNamespaceResolver().getQName(label);
+ } catch (NameException e) {
+ String error = "Invalid version label: " + e.getMessage();
+ log.error(error);
+ throw new RepositoryException(error, e);
+ }
+ }
+
+ /**
+ * Checks if the specified version belongs to this <code>VersionHistory</code>.
+ * This method throws <code>VersionException</code> if {@link Version#getContainingHistory()}
+ * is not the same item than this <code>VersionHistory</code>.
+ *
+ * @param version
+ * @throws javax.jcr.version.VersionException
+ * @throws javax.jcr.RepositoryException
+ */
+ private void checkValidVersion(Version version) throws VersionException, RepositoryException {
+ if (!version.getContainingHistory().isSame(this)) {
+ throw new VersionException("Specified version '" + version.getName() + "' is not part of this history.");
+ }
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionHistoryImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,129 @@
+/*
+ * 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.jcr2spi.version;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.jcr2spi.NodeImpl;
+import org.apache.jackrabbit.jcr2spi.ItemManager;
+import org.apache.jackrabbit.jcr2spi.SessionImpl;
+import org.apache.jackrabbit.jcr2spi.ItemLifeCycleListener;
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.name.QName;
+
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.Node;
+import javax.jcr.Item;
+import javax.jcr.nodetype.NodeDefinition;
+import java.util.Calendar;
+
+/**
+ * <code>VersionImpl</code>...
+ */
+public class VersionImpl extends NodeImpl implements Version {
+
+ private static Logger log = LoggerFactory.getLogger(VersionImpl.class);
+
+ public VersionImpl(ItemManager itemMgr, SessionImpl session, NodeState state, NodeDefinition definition, ItemLifeCycleListener[] listeners) {
+ super(itemMgr, session, state, definition, listeners);
+ }
+
+ //------------------------------------------------------------< Version >---
+ /**
+ *
+ * @return
+ * @throws RepositoryException
+ * @see Version#getContainingHistory()
+ */
+ public VersionHistory getContainingHistory() throws RepositoryException {
+ return (VersionHistory) getParent();
+ }
+
+ /**
+ *
+ * @return
+ * @throws RepositoryException
+ * @see Version#getCreated()
+ */
+ public Calendar getCreated() throws RepositoryException {
+ return getProperty(QName.JCR_CREATED).getDate();
+ }
+
+ /**
+ *
+ * @return
+ * @throws RepositoryException
+ * @see Version#getSuccessors()
+ */
+ public Version[] getSuccessors() throws RepositoryException {
+ return getVersions(QName.JCR_SUCCESSORS);
+ }
+
+ /**
+ *
+ * @return
+ * @throws RepositoryException
+ * @see Version#getPredecessors()
+ */
+ public Version[] getPredecessors() throws RepositoryException {
+ return getVersions(QName.JCR_PREDECESSORS);
+ }
+
+ //---------------------------------------------------------------< Item >---
+ /**
+ *
+ * @param otherItem
+ * @return
+ * @see Item#isSame(Item)
+ */
+ public boolean isSame(Item otherItem) {
+ if (otherItem instanceof VersionImpl) {
+ // since all versions are referenceable, protected and live
+ // in the same workspace, a simple comparision of the ids is sufficient
+ VersionImpl other = ((VersionImpl) otherItem);
+ return other.getId().equals(getId());
+ }
+ return false;
+ }
+ //------------------------------------------------------------< private >---
+ /**
+ *
+ * @param propertyName
+ * @return
+ */
+ private Version[] getVersions(QName propertyName) throws RepositoryException {
+ Version[] versions;
+ Value[] values = getProperty(propertyName).getValues();
+ if (values != null) {
+ versions = new Version[values.length];
+ for (int i = 0; i < values.length; i++) {
+ Node n = session.getNodeByUUID(values[i].getString());
+ if (n instanceof Version) {
+ versions[i] = (Version) n;
+ } else {
+ throw new RepositoryException("Version property contains invalid value not pointing to a 'Version'");
+ }
+ }
+ } else {
+ versions = new Version[0];
+ }
+ return versions;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManager.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManager.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManager.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,59 @@
+/*
+ * 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.jcr2spi.version;
+
+import org.apache.jackrabbit.spi.NodeId;
+
+import javax.jcr.RepositoryException;
+import java.util.Collection;
+
+/**
+ * <code>VersionManager</code>...
+ */
+public interface VersionManager {
+
+ public void checkin(NodeId nodeId) throws RepositoryException;
+
+ public void checkout(NodeId nodeId) throws RepositoryException;
+
+ public boolean isCheckedOut(NodeId nodeId) throws RepositoryException;
+
+ public void restore(NodeId nodeId, NodeId versionId, boolean removeExisting) throws RepositoryException;
+
+ public void restore(NodeId[] versionIds, boolean removeExisting) throws RepositoryException;
+
+ /**
+ *
+ * @param nodeId
+ * @param workspaceName
+ * @param bestEffort
+ * @return A Collection of <code>ItemId</code> containing the ids of those
+ * <code>Node</code>s that failed to be merged and need manual resolution
+ * by the user of the API.
+ * @see #resolveMergeConflict(NodeId, NodeId, boolean)
+ */
+ public Collection merge(NodeId nodeId, String workspaceName, boolean bestEffort) throws RepositoryException;
+
+ /**
+ *
+ * @param nodeId
+ * @param versionId
+ * @param done
+ * @throws RepositoryException
+ */
+ public void resolveMergeConflict(NodeId nodeId, NodeId versionId, boolean done) throws RepositoryException;
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManager.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,129 @@
+/*
+ * 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.jcr2spi.version;
+
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.jcr2spi.state.UpdatableItemStateManager;
+import org.apache.jackrabbit.jcr2spi.state.PropertyState;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateException;
+import org.apache.jackrabbit.jcr2spi.observation.InternalEventListener;
+import org.apache.jackrabbit.jcr2spi.operation.Operation;
+import org.apache.jackrabbit.jcr2spi.operation.Checkout;
+import org.apache.jackrabbit.jcr2spi.operation.Checkin;
+import org.apache.jackrabbit.jcr2spi.operation.Restore;
+import org.apache.jackrabbit.jcr2spi.operation.ResolveMergeConflict;
+import org.apache.jackrabbit.jcr2spi.operation.Merge;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.spi.EventIterator;
+import org.apache.jackrabbit.spi.Event;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.PropertyId;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * <code>VersionManagerImpl</code>...
+ */
+public class VersionManagerImpl implements VersionManager {
+
+ private static Logger log = LoggerFactory.getLogger(VersionManagerImpl.class);
+
+ private final UpdatableItemStateManager stateManager;
+
+ public VersionManagerImpl(UpdatableItemStateManager stateManager) {
+ this.stateManager = stateManager;
+ }
+
+ public void checkin(NodeId nodeId) throws RepositoryException {
+ Operation ci = Checkin.create(nodeId);
+ stateManager.execute(ci);
+ }
+
+ public void checkout(NodeId nodeId) throws RepositoryException {
+ Operation co = Checkout.create(nodeId);
+ stateManager.execute(co);
+ }
+
+ public boolean isCheckedOut(NodeId nodeId) throws RepositoryException {
+ try {
+ NodeState nodeState = (NodeState) stateManager.getItemState(nodeId);
+ // search nearest ancestor that is versionable
+ /**
+ * FIXME should not only rely on existence of jcr:isCheckedOut property
+ * but also verify that node.isNodeType("mix:versionable")==true;
+ * this would have a negative impact on performance though...
+ */
+ while (!nodeState.hasPropertyName(QName.JCR_ISCHECKEDOUT)) {
+ if (nodeState.getParentId() == null) {
+ // reached root state without finding a jcr:isCheckedOut property
+ return true;
+ }
+ nodeState = (NodeState) stateManager.getItemState(nodeState.getParentId());
+ }
+ PropertyId propId = nodeState.getPropertyId(QName.JCR_ISCHECKEDOUT);
+ PropertyState propState = (PropertyState) stateManager.getItemState(propId);
+
+ Boolean b = Boolean.valueOf(propState.getValue().getString());
+ return b.booleanValue();
+ } catch (ItemStateException e) {
+ // should not occur
+ throw new RepositoryException(e);
+ }
+ }
+
+ public void restore(NodeId nodeId, NodeId versionId, boolean removeExisting) throws RepositoryException {
+ Operation op = Restore.create(nodeId, versionId, removeExisting);
+ stateManager.execute(op);
+ }
+
+ public void restore(NodeId[] versionIds, boolean removeExisting) throws RepositoryException {
+ Operation op = Restore.create(versionIds, removeExisting);
+ stateManager.execute(op);
+ }
+
+ public Collection merge(NodeId nodeId, String workspaceName, boolean bestEffort) throws RepositoryException {
+ // TODO find better solution to build the mergeFailed-collection
+ final List failedIds = new ArrayList();
+ InternalEventListener mergeFailedCollector = new InternalEventListener() {
+ public void onEvent(EventIterator events, boolean isLocal) {
+ if (isLocal) {
+ while (events.hasNext()) {
+ Event ev = events.nextEvent();
+ if (ev.getType() == Event.PROPERTY_ADDED && QName.JCR_MERGEFAILED.equals(ev.getQPath().getNameElement().getName())) {
+ failedIds.add(ev.getParentId());
+ }
+ }
+ }
+ }
+ };
+
+ Operation op = Merge.create(nodeId, workspaceName, bestEffort, mergeFailedCollector);
+ stateManager.execute(op);
+ return failedIds;
+ }
+
+ public void resolveMergeConflict(NodeId nodeId, NodeId versionId, boolean done) throws RepositoryException {
+ Operation op = ResolveMergeConflict.create(nodeId, versionId, done);
+ stateManager.execute(op);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/version/VersionManagerImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,326 @@
+/*
+ * 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.jcr2spi.xml;
+
+import org.apache.jackrabbit.name.SessionNamespaceResolver;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.NameException;
+import org.apache.jackrabbit.name.QName;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * <code>AbstractSAXEventGenerator</code> serves as the base class for
+ * <code>SysViewSAXEventGenerator</code> and <code>DocViewSAXEventGenerator</code>
+ * <p/>
+ * It traverses a tree of <code>Node</code> & <code>Property</code>
+ * instances, and calls the abstract methods
+ * <ul>
+ * <li><code>{@link #entering(Node, int)}</code></li>
+ * <li><code>{@link #enteringProperties(Node, int)}</code></li>
+ * <li><code>{@link #leavingProperties(Node, int)}</code></li>
+ * <li><code>{@link #leaving(Node, int)}</code></li>
+ * <li><code>{@link #entering(Property, int)}</code></li>
+ * <li><code>{@link #leaving(Property, int)}</code></li>
+ * </ul>
+ * for every item it encounters.
+ */
+abstract class AbstractSAXEventGenerator {
+
+ private static Logger log = LoggerFactory.getLogger(AbstractSAXEventGenerator.class);
+
+ /**
+ * the session to be used for resolving namespace mappings
+ */
+ protected final Session session;
+ /**
+ * the session's namespace resolver
+ */
+ protected final NamespaceResolver nsResolver;
+
+ /**
+ * the content handler to feed the SAX events to
+ */
+ protected final ContentHandler contentHandler;
+
+ protected final Node startNode;
+ protected final boolean skipBinary;
+ protected final boolean noRecurse;
+
+ /**
+ * The jcr:primaryType property name (allowed for session-local prefix mappings)
+ */
+ protected final String jcrPrimaryType;
+ /**
+ * The jcr:mixinTypes property name (allowed for session-local prefix mappings)
+ */
+ protected final String jcrMixinTypes;
+ /**
+ * The jcr:uuid property name (allowed for session-local prefix mappings)
+ */
+ protected final String jcrUUID;
+ /**
+ * The jcr:root node name (allowed for session-local prefix mappings)
+ */
+ protected final String jcrRoot;
+ /**
+ * The jcr:xmltext node name (allowed for session-local prefix mappings)
+ */
+ protected final String jcrXMLText;
+ /**
+ * The jcr:xmlCharacters property name (allowed for session-local prefix mappings)
+ */
+ protected final String jcrXMLCharacters;
+
+ /**
+ * Constructor
+ *
+ * @param node the node state which should be serialized
+ * @param noRecurse if true, only <code>node</code> and its properties will
+ * be serialized; otherwise the entire hierarchy starting with
+ * <code>node</code> will be serialized.
+ * @param skipBinary flag governing whether binary properties are to be serialized.
+ * @param contentHandler the content handler to feed the SAX events to
+ * @throws RepositoryException if an error occurs
+ */
+ protected AbstractSAXEventGenerator(Node node, boolean noRecurse,
+ boolean skipBinary,
+ ContentHandler contentHandler)
+ throws RepositoryException {
+ startNode = node;
+ session = node.getSession();
+ nsResolver = new SessionNamespaceResolver(session);
+
+ this.contentHandler = contentHandler;
+ this.skipBinary = skipBinary;
+ this.noRecurse = noRecurse;
+
+ // resolve the names of some wellknown properties
+ // allowing for session-local prefix mappings
+ try {
+ jcrPrimaryType = nsResolver.getJCRName(QName.JCR_PRIMARYTYPE);
+ jcrMixinTypes = nsResolver.getJCRName(QName.JCR_MIXINTYPES);
+ jcrUUID = nsResolver.getJCRName(QName.JCR_UUID);
+ jcrRoot = nsResolver.getJCRName(QName.JCR_ROOT);
+ jcrXMLText = nsResolver.getJCRName(QName.JCR_XMLTEXT);
+ jcrXMLCharacters = nsResolver.getJCRName(QName.JCR_XMLCHARACTERS);
+ } catch (NameException e) {
+ // should never get here...
+ String msg = "internal error: failed to resolve namespace mappings";
+ log.error(msg, e);
+ throw new RepositoryException(msg, e);
+ }
+ }
+
+ /**
+ * Serializes the hierarchy of nodes and properties.
+ *
+ * @throws RepositoryException if an error occurs while traversing the hierarchy
+ * @throws SAXException if an error occured while feeding the events
+ * to the content handler
+ */
+ public void serialize() throws RepositoryException, SAXException {
+ // start document and declare namespaces
+ contentHandler.startDocument();
+ startNamespaceDeclarations();
+
+ // serialize node and subtree
+ process(startNode, 0);
+
+ // clear namespace declarations and end document
+ endNamespaceDeclarations();
+ contentHandler.endDocument();
+ }
+
+ /**
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected void startNamespaceDeclarations()
+ throws RepositoryException, SAXException {
+ // start namespace declarations
+ String[] prefixes = session.getNamespacePrefixes();
+ for (int i = 0; i < prefixes.length; i++) {
+ String prefix = prefixes[i];
+ if (QName.NS_XML_PREFIX.equals(prefix)) {
+ // skip 'xml' prefix as this would be an illegal namespace declaration
+ continue;
+ }
+ String uri = session.getNamespaceURI(prefix);
+ contentHandler.startPrefixMapping(prefix, uri);
+ }
+ }
+
+ /**
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected void endNamespaceDeclarations()
+ throws RepositoryException, SAXException {
+ // end namespace declarations
+ String[] prefixes = session.getNamespacePrefixes();
+ for (int i = 0; i < prefixes.length; i++) {
+ String prefix = prefixes[i];
+ if (QName.NS_XML_PREFIX.equals(prefix)) {
+ // skip 'xml' prefix as this would be an illegal namespace declaration
+ continue;
+ }
+ contentHandler.endPrefixMapping(prefix);
+ }
+ }
+
+ /**
+ * @param node
+ * @param level
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected void process(Node node, int level)
+ throws RepositoryException, SAXException {
+ // enter node
+ entering(node, level);
+
+ // enter properties
+ enteringProperties(node, level);
+
+ // serialize jcr:primaryType, jcr:mixinTypes & jcr:uuid first:
+ // jcr:primaryType
+ if (node.hasProperty(jcrPrimaryType)) {
+ process(node.getProperty(jcrPrimaryType), level + 1);
+ } else {
+ String msg = "internal error: missing jcr:primaryType property on node "
+ + node.getPath();
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ // jcr:mixinTypes
+ if (node.hasProperty(jcrMixinTypes)) {
+ process(node.getProperty(jcrMixinTypes), level + 1);
+ }
+ // jcr:uuid
+ if (node.hasProperty(jcrUUID)) {
+ process(node.getProperty(jcrUUID), level + 1);
+ }
+
+ // serialize remaining properties
+ PropertyIterator propIter = node.getProperties();
+ while (propIter.hasNext()) {
+ Property prop = propIter.nextProperty();
+ String name = prop.getName();
+ if (jcrPrimaryType.equals(name)
+ || jcrMixinTypes.equals(name)
+ || jcrUUID.equals(name)) {
+ continue;
+ }
+ // serialize property
+ process(prop, level + 1);
+ }
+
+ // leaving properties
+ leavingProperties(node, level);
+
+ if (!noRecurse) {
+ // child nodes
+ NodeIterator nodeIter = node.getNodes();
+ while (nodeIter.hasNext()) {
+ Node childNode = nodeIter.nextNode();
+ // recurse
+ process(childNode, level + 1);
+ }
+ }
+
+ // leaving node
+ leaving(node, level);
+ }
+
+ /**
+ * @param prop
+ * @param level
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected void process(Property prop, int level)
+ throws RepositoryException, SAXException {
+ // serialize property
+ entering(prop, level);
+ leaving(prop, level);
+ }
+
+ /**
+ * @param node
+ * @param level
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected abstract void entering(Node node, int level)
+ throws RepositoryException, SAXException;
+
+ /**
+ * @param node
+ * @param level
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected abstract void enteringProperties(Node node, int level)
+ throws RepositoryException, SAXException;
+
+ /**
+ * @param node
+ * @param level
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected abstract void leavingProperties(Node node, int level)
+ throws RepositoryException, SAXException;
+
+ /**
+ * @param node
+ * @param level
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected abstract void leaving(Node node, int level)
+ throws RepositoryException, SAXException;
+
+ /**
+ * @param prop
+ * @param level
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected abstract void entering(Property prop, int level)
+ throws RepositoryException, SAXException;
+
+ /**
+ * @param prop
+ * @param level
+ * @throws RepositoryException
+ * @throws SAXException
+ */
+ protected abstract void leaving(Property prop, int level)
+ throws RepositoryException, SAXException;
+
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/AbstractSAXEventGenerator.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,281 @@
+/*
+ * 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.jcr2spi.xml;
+
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.NameException;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.util.ISO9075;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.IdFactory;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Stack;
+
+/**
+ * <code>DocViewImportHandler</code> processes Document View XML SAX events
+ * and 'translates' them into <code>{@link Importer}</code> method calls.
+ */
+class DocViewImportHandler extends TargetImportHandler {
+
+ private static Logger log = LoggerFactory.getLogger(DocViewImportHandler.class);
+
+ /**
+ * stack of NodeInfo instances; an instance is pushed onto the stack
+ * in the startElement method and is popped from the stack in the
+ * endElement method.
+ */
+ private final Stack stack = new Stack();
+ // buffer used to merge adjacent character data
+ private BufferedStringValue textHandler = new BufferedStringValue();
+
+ /**
+ * Constructs a new <code>DocViewImportHandler</code>.
+ *
+ * @param importer
+ * @param nsContext
+ */
+ DocViewImportHandler(Importer importer, NamespaceResolver nsContext, IdFactory idFactory) {
+ super(importer, nsContext, idFactory);
+ }
+
+ /**
+ * Appends the given character data to the internal buffer.
+ *
+ * @param ch the characters to be appended
+ * @param start the index of the first character to append
+ * @param length the number of characters to append
+ * @throws SAXException if an error occurs
+ * @see #characters(char[], int, int)
+ * @see #ignorableWhitespace(char[], int, int)
+ * @see #processCharacters()
+ */
+ private void appendCharacters(char[] ch, int start, int length)
+ throws SAXException {
+ if (textHandler == null) {
+ textHandler = new BufferedStringValue();
+ }
+ try {
+ textHandler.append(ch, start, length);
+ } catch (IOException ioe) {
+ String msg = "internal error while processing internal buffer data";
+ log.error(msg, ioe);
+ throw new SAXException(msg, ioe);
+ }
+ }
+
+ /**
+ * Translates character data reported by the
+ * <code>{@link #characters(char[], int, int)}</code> &
+ * <code>{@link #ignorableWhitespace(char[], int, int)}</code> SAX events
+ * into a <code>jcr:xmltext</code> child node with one
+ * <code>jcr:xmlcharacters</code> property.
+ *
+ * @throws SAXException if an error occurs
+ * @see #appendCharacters(char[], int, int)
+ */
+ private void processCharacters()
+ throws SAXException {
+ try {
+ if (textHandler != null && textHandler.length() > 0) {
+ // there is character data that needs to be added to
+ // the current node
+
+ // check for pure whitespace character data
+ Reader reader = textHandler.reader();
+ try {
+ int ch;
+ while ((ch = reader.read()) != -1) {
+ if (ch > 0x20) {
+ break;
+ }
+ }
+ if (ch == -1) {
+ // the character data consists of pure whitespace, ignore
+ log.debug("ignoring pure whitespace character data...");
+ // reset handler
+ textHandler.dispose();
+ textHandler = null;
+ return;
+ }
+ } finally {
+ reader.close();
+ }
+
+ Importer.NodeInfo node =
+ new Importer.NodeInfo(QName.JCR_XMLTEXT, null, null, null);
+ Importer.TextValue[] values =
+ new Importer.TextValue[]{textHandler};
+ ArrayList props = new ArrayList();
+ Importer.PropInfo prop =
+ new Importer.PropInfo(QName.JCR_XMLCHARACTERS, PropertyType.STRING, values);
+ props.add(prop);
+ // call Importer
+ importer.startNode(node, props, nsContext);
+ importer.endNode(node);
+
+ // reset handler
+ textHandler.dispose();
+ textHandler = null;
+ }
+ } catch (IOException ioe) {
+ String msg = "internal error while processing internal buffer data";
+ log.error(msg, ioe);
+ throw new SAXException(msg, ioe);
+ } catch (RepositoryException re) {
+ throw new SAXException(re);
+ }
+ }
+
+ //-------------------------------------------------------< ContentHandler >
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * See also {@link DocViewSAXEventGenerator#leavingProperties(javax.jcr.Node, int)}
+ * regarding special handling of multi-valued properties on export.
+ */
+ public void startElement(String namespaceURI, String localName,
+ String qName, Attributes atts)
+ throws SAXException {
+ // process buffered character data
+ processCharacters();
+
+ try {
+ QName nodeName = new QName(namespaceURI, localName);
+ // decode node name
+ nodeName = ISO9075.decode(nodeName);
+
+ // properties
+ NodeId id = null;
+ QName nodeTypeName = null;
+ QName[] mixinTypes = null;
+
+ ArrayList props = new ArrayList(atts.getLength());
+ for (int i = 0; i < atts.getLength(); i++) {
+ QName propName = new QName(atts.getURI(i), atts.getLocalName(i));
+ // decode property name
+ propName = ISO9075.decode(propName);
+
+ // value(s)
+ String attrValue = atts.getValue(i);
+ Importer.TextValue[] propValues;
+
+ // always assume single-valued property for the time being
+ // until a way of properly serializing/detecting multi-valued
+ // properties on re-import is found (see JCR-325);
+ // see also DocViewSAXEventGenerator#leavingProperties(Node, int)
+ // todo proper multi-value serialization support
+ propValues = new Importer.TextValue[1];
+ propValues[0] = new StringValue(attrValue);
+
+ if (propName.equals(QName.JCR_PRIMARYTYPE)) {
+ // jcr:primaryType
+ if (attrValue.length() > 0) {
+ try {
+ nodeTypeName = nsContext.getQName(attrValue);
+ } catch (NameException ne) {
+ throw new SAXException("illegal jcr:primaryType value: "
+ + attrValue, ne);
+ }
+ }
+ } else if (propName.equals(QName.JCR_MIXINTYPES)) {
+ // jcr:mixinTypes
+ if (propValues.length > 0) {
+ mixinTypes = new QName[propValues.length];
+ for (int j = 0; j < propValues.length; j++) {
+ String val = ((StringValue) propValues[j]).retrieve();
+ try {
+ mixinTypes[j] = nsContext.getQName(val);
+ } catch (NameException ne) {
+ throw new SAXException("illegal jcr:mixinTypes value: "
+ + val, ne);
+ }
+ }
+ }
+ } else if (propName.equals(QName.JCR_UUID)) {
+ // jcr:uuid
+ if (attrValue.length() > 0) {
+ id = idFactory.createNodeId(attrValue);
+ }
+ } else {
+ props.add(new Importer.PropInfo(propName, PropertyType.UNDEFINED, propValues));
+ }
+ }
+
+ Importer.NodeInfo node = new Importer.NodeInfo(nodeName, nodeTypeName, mixinTypes, id);
+ // all information has been collected, now delegate to importer
+ importer.startNode(node, props, nsContext);
+ // push current node data onto stack
+ stack.push(node);
+ } catch (RepositoryException re) {
+ throw new SAXException(re);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
+ /**
+ * buffer data reported by the characters event;
+ * will be processed on the next endElement or startElement event.
+ */
+ appendCharacters(ch, start, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void ignorableWhitespace(char[] ch, int start, int length)
+ throws SAXException {
+ /**
+ * buffer data reported by the ignorableWhitespace event;
+ * will be processed on the next endElement or startElement event.
+ */
+ appendCharacters(ch, start, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void endElement(String namespaceURI, String localName, String qName)
+ throws SAXException {
+ // process buffered character data
+ processCharacters();
+
+ Importer.NodeInfo node = (Importer.NodeInfo) stack.peek();
+ try {
+ // call Importer
+ importer.endNode(node);
+ } catch (RepositoryException re) {
+ throw new SAXException(re);
+ }
+ // we're done with this node, pop it from stack
+ stack.pop();
+ }
+}
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewImportHandler.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewSAXEventGenerator.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewSAXEventGenerator.java?rev=421270&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewSAXEventGenerator.java (added)
+++ jackrabbit/trunk/contrib/spi/jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/xml/DocViewSAXEventGenerator.java Wed Jul 12 06:33:19 2006
@@ -0,0 +1,222 @@
+/*
+ * 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.jcr2spi.xml;
+
+import org.apache.jackrabbit.name.NameException;
+import org.apache.jackrabbit.name.QName;
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.value.ValueHelper;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A <code>DocViewSAXEventGenerator</code> instance can be used to generate
+ * SAX events representing the serialized form of an item in Document View XML.
+ */
+public class DocViewSAXEventGenerator extends AbstractSAXEventGenerator {
+
+ private static Logger log = LoggerFactory.getLogger(DocViewSAXEventGenerator.class);
+
+ public static final String CDATA_TYPE = "CDATA";
+
+ // used to temporarily store properties of a node
+ private final List props;
+
+ /**
+ * Constructor
+ *
+ * @param node the node state which should be serialized
+ * @param noRecurse if true, only <code>node</code> and its properties
+ * will be serialized; otherwise the entire hierarchy
+ * starting with <code>node</code> will be serialized.
+ * @param skipBinary flag governing whether binary properties are to be
+ * serialized.
+ * @param contentHandler the content handler to feed the SAX events to
+ * @throws RepositoryException if an error occurs
+ */
+ public DocViewSAXEventGenerator(Node node, boolean noRecurse,
+ boolean skipBinary,
+ ContentHandler contentHandler)
+ throws RepositoryException {
+ super(node, noRecurse, skipBinary, contentHandler);
+
+ props = new ArrayList();
+ }
+
+ private QName getQName(String rawName) throws RepositoryException {
+ try {
+ return nsResolver.getQName(rawName);
+ } catch (NameException e) {
+ // should never get here...
+ String msg = "internal error: failed to resolve namespace mappings";
+ log.error(msg, e);
+ throw new RepositoryException(msg, e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void entering(Node node, int level)
+ throws RepositoryException, SAXException {
+ // nop
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void enteringProperties(Node node, int level)
+ throws RepositoryException, SAXException {
+ // reset list of properties
+ props.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * See also {@link DocViewImportHandler#startElement(String, String, String, org.xml.sax.Attributes)}
+ * regarding special handling of multi-valued properties on import.
+ */
+ protected void leavingProperties(Node node, int level)
+ throws RepositoryException, SAXException {
+ String name = node.getName();
+ if (name.equals(jcrXMLText)) {
+ // the node represents xml character data
+ Iterator iter = props.iterator();
+ while (iter.hasNext()) {
+ Property prop = (Property) iter.next();
+ String propName = prop.getName();
+ if (propName.equals(jcrXMLCharacters)) {
+ // assume jcr:xmlcharacters is single-valued
+ char[] chars = prop.getValue().getString().toCharArray();
+ contentHandler.characters(chars, 0, chars.length);
+ }
+ }
+ } else {
+ // regular node
+
+ // element name
+ String elemName;
+ if (node.getDepth() == 0) {
+ // root node needs a name
+ elemName = jcrRoot;
+ } else {
+ // encode node name to make sure it's a valid xml name
+ elemName = ISO9075.encode(name);
+ }
+
+ // attributes (properties)
+ AttributesImpl attrs = new AttributesImpl();
+ Iterator iter = props.iterator();
+ while (iter.hasNext()) {
+ Property prop = (Property) iter.next();
+ String propName = prop.getName();
+
+ if (prop.getDefinition().isMultiple()) {
+ // todo proper multi-value serialization support
+ // skip multi-valued properties for the time being
+ // until a way of properly handling/detecting multi-valued
+ // properties on re-import is found (see JCR-325);
+ // see also DocViewImportHandler#startElement()
+
+ // skipping multi-valued properties entirely is legal
+ // according to "6.4.2.5 Multi-value Properties" of the
+ // jsr-170 specification
+ continue;
+ }
+
+ // attribute name (encode property name to make sure it's a valid xml name)
+ String attrName = ISO9075.encode(propName);
+ QName qName = getQName(attrName);
+
+ // attribute value
+ if (prop.getType() == PropertyType.BINARY && skipBinary) {
+ // add empty attribute
+ attrs.addAttribute(qName.getNamespaceURI(),
+ qName.getLocalName(), attrName, CDATA_TYPE, "");
+ } else {
+ StringBuffer attrValue = new StringBuffer();
+ // serialize single-valued property
+ attrValue.append(ValueHelper.serialize(prop.getValue(), false));
+ attrs.addAttribute(qName.getNamespaceURI(),
+ qName.getLocalName(), attrName, CDATA_TYPE,
+ attrValue.toString());
+ }
+ }
+ // start element (node)
+ QName qName = getQName(elemName);
+ contentHandler.startElement(qName.getNamespaceURI(),
+ qName.getLocalName(), elemName, attrs);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void leaving(Node node, int level)
+ throws RepositoryException, SAXException {
+ String name = node.getName();
+ if (name.equals(jcrXMLText)) {
+ // the node represents xml character data
+ // (already processed in leavingProperties(NodeImpl, int)
+ return;
+ }
+ // encode node name to make sure it's a valid xml name
+ name = ISO9075.encode(name);
+ // element name
+ String elemName;
+ if (node.getDepth() == 0) {
+ // root node needs a name
+ elemName = jcrRoot;
+ } else {
+ // encode node name to make sure it's a valid xml name
+ elemName = ISO9075.encode(name);
+ }
+
+ // end element (node)
+ QName qName = getQName(elemName);
+ contentHandler.endElement(qName.getNamespaceURI(), qName.getLocalName(),
+ elemName);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void entering(Property prop, int level)
+ throws RepositoryException, SAXException {
+ props.add(prop);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void leaving(Property prop, int level)
+ throws RepositoryException, SAXException {
+ // nop
+ }
+}