use of org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType in project jackrabbit by apache.
the class SessionImporter method checkIncludesMixReferenceable.
/**
* Validate the given <code>NodeInfo</code>: make sure, that if a uuid is
* defined, the primary or the mixin types include mix:referenceable.
*
* @param nodeInfo
* @throws RepositoryException
*/
private void checkIncludesMixReferenceable(Importer.NodeInfo nodeInfo) throws RepositoryException {
List<Name> l = new ArrayList<Name>();
l.add(nodeInfo.getNodeTypeName());
Name[] mixinNames = nodeInfo.getMixinNames();
if (mixinNames != null && mixinNames.length > 0) {
l.addAll(Arrays.asList(nodeInfo.getMixinNames()));
}
if (l.contains(NameConstants.MIX_REFERENCEABLE)) {
// shortcut
return;
}
Name[] ntNames = l.toArray(new Name[l.size()]);
EffectiveNodeType ent = session.getEffectiveNodeTypeProvider().getEffectiveNodeType(ntNames);
if (!ent.includesNodeType(NameConstants.MIX_REFERENCEABLE)) {
throw new ConstraintViolationException("XML defines jcr:uuid without defining import node to be referenceable.");
}
}
use of org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType in project jackrabbit by apache.
the class SessionItemStateManager method addNodeState.
private List<ItemState> addNodeState(NodeState parent, Name nodeName, Name nodeTypeName, String uuid, QNodeDefinition definition, int options) throws RepositoryException, ConstraintViolationException, AccessDeniedException, UnsupportedRepositoryOperationException, NoSuchNodeTypeException, ItemExistsException, VersionException {
// check if add node is possible. note, that the options differ if
// the 'addNode' is called from inside a regular add-node to create
// autocreated child nodes that may be 'protected'.
validator.checkAddNode(parent, nodeName, nodeTypeName, options);
// a new NodeState doesn't have mixins defined yet -> ent is ent of primarytype
EffectiveNodeType ent = mgrProvider.getEffectiveNodeTypeProvider().getEffectiveNodeType(nodeTypeName);
if (nodeTypeName == null) {
// no primary node type specified,
// try default primary type from definition
nodeTypeName = definition.getDefaultPrimaryType();
if (nodeTypeName == null) {
String msg = "No applicable node type could be determined for " + nodeName;
log.debug(msg);
throw new ConstraintViolationException(msg);
}
}
List<ItemState> addedStates = new ArrayList<ItemState>();
// create new nodeState. NOTE, that the uniqueID is not added to the
// state for consistency between 'addNode' and importXML
NodeState nodeState = transientStateMgr.createNewNodeState(nodeName, null, nodeTypeName, definition, parent);
addedStates.add(nodeState);
if (uuid != null) {
QValue[] value = getQValues(uuid, qValueFactory);
ItemDefinitionProvider defProvider = mgrProvider.getItemDefinitionProvider();
QPropertyDefinition pDef = defProvider.getQPropertyDefinition(NameConstants.MIX_REFERENCEABLE, NameConstants.JCR_UUID, PropertyType.STRING, false);
addedStates.add(addPropertyState(nodeState, NameConstants.JCR_UUID, PropertyType.STRING, value, pDef, 0));
}
// add 'auto-create' properties defined in node type
for (QPropertyDefinition pd : ent.getAutoCreateQPropertyDefinitions()) {
if (!nodeState.hasPropertyName(pd.getName())) {
QValue[] autoValue = computeSystemGeneratedPropertyValues(nodeState, pd);
if (autoValue != null) {
int propOptions = ItemStateValidator.CHECK_NONE;
// execute 'addProperty' without adding operation.
addedStates.add(addPropertyState(nodeState, pd.getName(), pd.getRequiredType(), autoValue, pd, propOptions));
}
}
}
// recursively add 'auto-create' child nodes defined in node type
for (QNodeDefinition nd : ent.getAutoCreateQNodeDefinitions()) {
// execute 'addNode' without adding the operation.
int opt = ItemStateValidator.CHECK_LOCK | ItemStateValidator.CHECK_COLLISION;
addedStates.addAll(addNodeState(nodeState, nd.getName(), nd.getDefaultPrimaryType(), null, nd, opt));
}
return addedStates;
}
use of org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType in project jackrabbit by apache.
the class NodeImpl method canAddMixin.
/**
* @param mixinName
* @return
* @throws NoSuchNodeTypeException
* @throws ConstraintViolationException
*/
private boolean canAddMixin(Name mixinName) throws NoSuchNodeTypeException, ConstraintViolationException {
NodeTypeManagerImpl ntMgr = session.getNodeTypeManager();
// first check characteristics of each mixin
NodeType mixin = ntMgr.getNodeType(mixinName);
if (!mixin.isMixin()) {
log.error(mixin.getName() + ": not a mixin node type");
return false;
}
// get list of existing nodetypes
Name[] existingNts = getNodeState().getNodeTypeNames();
// build effective node type representing primary type including existing mixins
EffectiveNodeType entExisting = session.getEffectiveNodeTypeProvider().getEffectiveNodeType(existingNts);
// check if the base type supports adding this mixin
if (!entExisting.supportsMixin(mixinName)) {
log.debug(mixin.getName() + ": not supported on node type " + getPrimaryNodeTypeName());
return false;
}
// second, build new effective node type for nts including the new mixin
// types, detecting eventual incompatibilities
Name[] resultingNts = new Name[existingNts.length + 1];
System.arraycopy(existingNts, 0, resultingNts, 0, existingNts.length);
resultingNts[existingNts.length] = mixinName;
session.getEffectiveNodeTypeProvider().getEffectiveNodeType(resultingNts);
// all validations succeeded: return true
return true;
}
use of org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType in project jackrabbit by apache.
the class NodeImpl method removeMixin.
/**
* @see Node#removeMixin(String)
*/
public void removeMixin(String mixinName) throws NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException, RepositoryException {
checkIsWritable();
Name ntName = getQName(mixinName);
List<Name> mixinValue = getMixinTypes();
// remove name of target mixin
if (!mixinValue.remove(ntName)) {
throw new NoSuchNodeTypeException("Cannot remove mixin '" + mixinName + "': Nodetype is not present on this node.");
}
// mix:referenceable needs additional assertion: the mixin cannot be
// removed, if any references are left to this node.
NodeTypeImpl mixin = session.getNodeTypeManager().getNodeType(ntName);
if (mixin.isNodeType(NameConstants.MIX_REFERENCEABLE)) {
EffectiveNodeType entRemaining = getRemainingENT(mixinValue);
if (!entRemaining.includesNodeType(NameConstants.MIX_REFERENCEABLE)) {
PropertyIterator iter = getReferences();
if (iter.hasNext()) {
throw new ConstraintViolationException("Mixin type " + mixinName + " can not be removed: the node is being referenced through at least one property of type REFERENCE");
}
}
}
/*
* mix:lockable: the mixin cannot be removed if the node is currently
* locked even if the editing session is the lock holder.
*/
if (mixin.isNodeType((NameConstants.MIX_LOCKABLE))) {
EffectiveNodeType entRemaining = getRemainingENT(mixinValue);
if (!entRemaining.includesNodeType(NameConstants.MIX_LOCKABLE) && isLocked()) {
throw new ConstraintViolationException(mixinName + " can not be removed: the node is locked.");
}
}
// delegate to operation
Name[] mixins = mixinValue.toArray(new Name[mixinValue.size()]);
Operation op = SetMixin.create(getNodeState(), mixins);
session.getSessionItemStateManager().execute(op);
}
use of org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeType in project jackrabbit by apache.
the class SessionImporter method startNode.
/**
* {@inheritDoc}
*/
public void startNode(NodeInfo nodeInfo, List<PropInfo> propInfos, NamePathResolver resolver) throws RepositoryException {
if (isClosed()) {
// workspace-importer only: ignore if import has been aborted before.
return;
}
checkSession();
NodeState parent = parents.peek();
if (parent == null) {
// parent node was skipped, skip this child node also
// push null onto stack for skipped node
parents.push(null);
log.debug("Skipping node '" + nodeInfo.getName() + "'.");
return;
}
NodeEntry parentEntry = (NodeEntry) parent.getHierarchyEntry();
NodeState nodeState = null;
if (parentEntry.hasNodeEntry(nodeInfo.getName())) {
try {
// a valid child node with that name already exists
NodeEntry entry = parentEntry.getNodeEntry(nodeInfo.getName(), Path.INDEX_DEFAULT);
NodeState existing = entry.getNodeState();
QNodeDefinition def = existing.getDefinition();
if (!def.allowsSameNameSiblings()) {
// existing doesn't allow same-name siblings, check for conflicts
EffectiveNodeTypeProvider provider = session.getEffectiveNodeTypeProvider();
Name[] ntNames = existing.getAllNodeTypeNames();
EffectiveNodeType entExisting = provider.getEffectiveNodeType(ntNames);
if (def.isProtected() && entExisting.includesNodeType(nodeInfo.getNodeTypeName())) {
// skip protected node
// push null onto stack for skipped node
parents.push(null);
log.debug("skipping protected node " + LogUtil.safeGetJCRPath(existing, session.getPathResolver()));
return;
}
if (def.isAutoCreated() && entExisting.includesNodeType(nodeInfo.getNodeTypeName())) {
// this node has already been auto-created, no need to create it
nodeState = existing;
} else {
throw new ItemExistsException(LogUtil.safeGetJCRPath(existing, session.getPathResolver()));
}
}
} catch (ItemNotFoundException e) {
// 'existing' doesn't exist any more -> ignore
}
}
if (nodeState == null) {
// node does not exist -> create new one
if (nodeInfo.getUUID() == null) {
// no potential uuid conflict, add new node from given info
nodeState = importNode(nodeInfo, parent);
} else {
// make sure the import does not define a uuid without having
// a primaryType or mixin that makes the new node referenceable
checkIncludesMixReferenceable(nodeInfo);
// potential uuid conflict
try {
NodeId conflictingId = session.getIdFactory().createNodeId(nodeInfo.getUUID());
NodeEntry conflicting = session.getHierarchyManager().getNodeEntry(conflictingId);
// assert that the entry is available
conflicting.getItemState();
nodeState = resolveUUIDConflict(parent, conflicting, nodeInfo);
} catch (ItemNotFoundException e) {
// no conflict: create new with given uuid
nodeState = importNode(nodeInfo, parent);
}
}
}
// node state may be 'null' if applicable def is protected
if (nodeState != null) {
// process properties
for (PropInfo pi : propInfos) {
importProperty(pi, nodeState, resolver);
}
}
// push current nodeState onto stack of parents
parents.push(nodeState);
}
Aggregations