use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class SessionImporter method startNode.
/**
* {@inheritDoc}
*/
public void startNode(NodeInfo nodeInfo, List<PropInfo> propInfos) throws RepositoryException {
NodeImpl parent = parents.peek();
// process node
NodeImpl node = null;
NodeId id = nodeInfo.getId();
Name nodeName = nodeInfo.getName();
Name ntName = nodeInfo.getNodeTypeName();
Name[] mixins = nodeInfo.getMixinNames();
if (parent == null) {
log.debug("Skipping node: " + nodeName);
// parent node was skipped, skip this child node too
// push null onto stack for skipped node
parents.push(null);
// notify the p-i-importer
if (pnImporter != null) {
pnImporter.startChildInfo(nodeInfo, propInfos);
}
return;
}
if (parent.getDefinition().isProtected()) {
// skip protected node
parents.push(null);
log.debug("Skipping protected node: " + nodeName);
if (pnImporter != null) {
// pnImporter was already started (current nodeInfo is a sibling)
// notify it about this child node.
pnImporter.startChildInfo(nodeInfo, propInfos);
} else {
// potentially is able to deal with it, notify it about the child node.
for (ProtectedItemImporter pni : pItemImporters) {
if (pni instanceof ProtectedNodeImporter && ((ProtectedNodeImporter) pni).start(parent)) {
log.debug("Protected node -> delegated to ProtectedNodeImporter");
pnImporter = (ProtectedNodeImporter) pni;
pnImporter.startChildInfo(nodeInfo, propInfos);
break;
}
/* else: p-i-Importer isn't able to deal with the protected tree.
try next. and if none can handle the passed parent the
tree below will be skipped */
}
}
return;
}
if (parent.hasNode(nodeName)) {
// a node with that name already exists...
NodeImpl existing = parent.getNode(nodeName);
NodeDefinition def = existing.getDefinition();
if (!def.allowsSameNameSiblings()) {
// check for potential conflicts
if (def.isProtected() && existing.isNodeType(ntName)) {
/*
use the existing node as parent for the possible subsequent
import of a protected tree, that the protected node importer
may or may not be able to deal with.
-> upon the next 'startNode' the check for the parent being
protected will notify the protected node importer.
-> if the importer is able to deal with that node it needs
to care of the complete subtree until it is notified
during the 'endNode' call.
-> if the import can't deal with that node or if that node
is the a leaf in the tree to be imported 'end' will
not have an effect on the importer, that was never started.
*/
log.debug("Skipping protected node: " + existing);
parents.push(existing);
return;
}
if (def.isAutoCreated() && existing.isNodeType(ntName)) {
// this node has already been auto-created, no need to create it
node = existing;
} else {
// (see http://issues.apache.org/jira/browse/JCR-1128)
if (!(existing.getId().equals(id) && (uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING || uuidBehavior == ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING))) {
throw new ItemExistsException("Node with the same UUID exists:" + existing);
}
// fall through
}
}
}
if (node == null) {
// create node
if (id == null) {
// no potential uuid conflict, always add new node
checkPermission(parent, nodeName);
node = createNode(parent, nodeName, ntName, mixins, null);
} else {
// potential uuid conflict
boolean isConflicting;
try {
// the following is a fail-fast test whether
// an item exists (regardless of access control)
session.getHierarchyManager().getName(id);
isConflicting = true;
} catch (ItemNotFoundException infe) {
isConflicting = false;
}
if (isConflicting) {
// resolve uuid conflict
node = resolveUUIDConflict(parent, id, nodeInfo);
if (node == null) {
// no new node has been created, so skip this node
// push null onto stack for skipped node
parents.push(null);
log.debug("Skipping existing node " + nodeInfo.getName());
return;
}
} else {
// create new with given uuid
checkPermission(parent, nodeName);
node = createNode(parent, nodeName, ntName, mixins, id);
}
}
}
for (PropInfo pi : propInfos) {
// find applicable definition
QPropertyDefinition def = pi.getApplicablePropertyDef(node.getEffectiveNodeType());
if (def.isProtected()) {
// skip protected property
log.debug("Skipping protected property " + pi.getName());
// notify the ProtectedPropertyImporter.
for (ProtectedItemImporter ppi : pItemImporters) {
if (ppi instanceof ProtectedPropertyImporter && ((ProtectedPropertyImporter) ppi).handlePropInfo(node, pi, def)) {
log.debug("Protected property -> delegated to ProtectedPropertyImporter");
break;
}
/* else: p-i-Importer isn't able to deal with this property.
try next pp-importer */
}
} else {
// regular property -> create the property
createProperty(node, pi, def);
}
}
parents.push(node);
}
use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class WorkspaceImporter method processProperty.
protected void processProperty(NodeState node, PropInfo pInfo) throws RepositoryException {
PropertyState prop;
QPropertyDefinition def;
Name name = pInfo.getName();
int type = pInfo.getType();
if (node.hasPropertyName(name)) {
// a property with that name already exists...
PropertyId idExisting = new PropertyId(node.getNodeId(), name);
prop = (PropertyState) itemOps.getItemState(idExisting);
def = itemOps.findApplicablePropertyDefinition(prop.getName(), prop.getType(), prop.isMultiValued(), node);
if (def.isProtected()) {
// skip protected property
log.debug("skipping protected property " + itemOps.safeGetJCRPath(idExisting));
return;
}
if (!def.isAutoCreated() || (prop.getType() != type && type != PropertyType.UNDEFINED) || def.isMultiple() != prop.isMultiValued()) {
throw new ItemExistsException(itemOps.safeGetJCRPath(prop.getPropertyId()));
}
} else {
// there's no property with that name,
// find applicable definition
def = pInfo.getApplicablePropertyDef(itemOps.getEffectiveNodeType(node));
if (def.isProtected()) {
// skip protected property
log.debug("skipping protected property " + name);
return;
}
// create new property
prop = itemOps.createPropertyState(node, name, type, def);
}
// check multi-valued characteristic
TextValue[] values = pInfo.getTextValues();
if (values.length != 1 && !def.isMultiple()) {
throw new ConstraintViolationException(itemOps.safeGetJCRPath(prop.getPropertyId()) + " is not multi-valued");
}
// convert serialized values to InternalValue objects
int targetType = pInfo.getTargetType(def);
InternalValue[] iva = new InternalValue[values.length];
for (int i = 0; i < values.length; i++) {
iva[i] = values[i].getInternalValue(targetType);
}
// set values
prop.setValues(iva);
// make sure property is valid according to its definition
itemOps.validate(prop);
if (prop.getType() == PropertyType.REFERENCE || prop.getType() == PropertyType.WEAKREFERENCE) {
// store reference for later resolution
refTracker.processedReference(prop);
}
// store property
itemOps.store(prop);
}
use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class ItemManager method getDefinition.
PropertyDefinitionImpl getDefinition(PropertyState state) throws RepositoryException {
// see also: JCR-2408
if (state.getStatus() == ItemState.STATUS_EXISTING_REMOVED && state.getName().equals(NameConstants.JCR_UUID)) {
NodeTypeRegistry ntReg = sessionContext.getNodeTypeRegistry();
QPropertyDefinition def = ntReg.getEffectiveNodeType(NameConstants.MIX_REFERENCEABLE).getApplicablePropertyDef(state.getName(), state.getType());
return sessionContext.getNodeTypeManager().getPropertyDefinition(def);
}
try {
// retrieve parent in 2 steps in order to avoid the check for
// read permissions on the parent which isn't required in order
// to read the property's definition. see also JCR-2418.
ItemData parentData = getItemData(state.getParentId(), null, false);
NodeImpl parent = (NodeImpl) createItemInstance(parentData);
return parent.getApplicablePropertyDefinition(state.getName(), state.getType(), state.isMultiValued(), true);
} catch (ItemNotFoundException e) {
// parent probably removed, get it from attic
}
try {
NodeState parent = (NodeState) sism.getAttic().getItemState(state.getParentId()).getOverlayedState();
NodeTypeRegistry ntReg = sessionContext.getNodeTypeRegistry();
EffectiveNodeType ent = ntReg.getEffectiveNodeType(parent.getNodeTypeName(), parent.getMixinTypeNames());
QPropertyDefinition def;
try {
def = ent.getApplicablePropertyDef(state.getName(), state.getType(), state.isMultiValued());
} catch (ConstraintViolationException e) {
ent = ntReg.getEffectiveNodeType(NameConstants.NT_UNSTRUCTURED);
def = ent.getApplicablePropertyDef(state.getName(), state.getType(), state.isMultiValued());
log.warn("Fallback to nt:unstructured due to unknown property " + "definition for '" + state.getName() + "'");
}
return sessionContext.getNodeTypeManager().getPropertyDefinition(def);
} catch (ItemStateException e) {
throw new RepositoryException(e);
} catch (NodeTypeConflictException e) {
throw new RepositoryException(e);
}
}
use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class QueryImpl method getColumns.
/**
* Returns the columns for this query.
*
* @return array of columns.
* @throws RepositoryException if an error occurs.
*/
protected ColumnImpl[] getColumns() throws RepositoryException {
SessionImpl session = sessionContext.getSessionImpl();
QueryObjectModelFactory qomFactory = session.getWorkspace().getQueryManager().getQOMFactory();
// get columns
Map<Name, ColumnImpl> columns = new LinkedHashMap<Name, ColumnImpl>();
for (Name name : root.getSelectProperties()) {
String pn = sessionContext.getJCRName(name);
ColumnImpl col = (ColumnImpl) qomFactory.column(sessionContext.getJCRName(DEFAULT_SELECTOR_NAME), pn, pn);
columns.put(name, col);
}
if (columns.size() == 0) {
// use node type constraint
LocationStepQueryNode[] steps = root.getLocationNode().getPathSteps();
final Name[] ntName = new Name[1];
steps[steps.length - 1].acceptOperands(new DefaultQueryNodeVisitor() {
public Object visit(AndQueryNode node, Object data) throws RepositoryException {
return node.acceptOperands(this, data);
}
public Object visit(NodeTypeQueryNode node, Object data) {
ntName[0] = node.getValue();
return data;
}
}, null);
if (ntName[0] == null) {
ntName[0] = NameConstants.NT_BASE;
}
NodeTypeImpl nt = session.getNodeTypeManager().getNodeType(ntName[0]);
PropertyDefinition[] propDefs = nt.getPropertyDefinitions();
for (PropertyDefinition pd : propDefs) {
QPropertyDefinition propDef = ((PropertyDefinitionImpl) pd).unwrap();
if (!propDef.definesResidual() && !propDef.isMultiple()) {
columns.put(propDef.getName(), columnForName(propDef.getName()));
}
}
}
// add jcr:path and jcr:score if not selected already
if (!columns.containsKey(NameConstants.JCR_PATH)) {
columns.put(NameConstants.JCR_PATH, columnForName(NameConstants.JCR_PATH));
}
if (!columns.containsKey(NameConstants.JCR_SCORE)) {
columns.put(NameConstants.JCR_SCORE, columnForName(NameConstants.JCR_SCORE));
}
return columns.values().toArray(new ColumnImpl[columns.size()]);
}
use of org.apache.jackrabbit.spi.QPropertyDefinition in project jackrabbit by apache.
the class NodeTypeRegistry method validateNodeTypeDef.
/**
* Validates the specified <code>NodeTypeDef</code> within the context of
* the two other given collections and returns an <code>EffectiveNodeType</code>.
*
* @param ntd node type definition
* @param entCache effective node type cache
* @param ntdCache cache of 'known' node type definitions, used to resolve dependencies
* @param nsReg namespace registry used for validatingatch names
* @param lenient flag governing whether validation can be lenient or has to be strict
* @return an effective node type representation of the specified <code>QNodeTypeDefinition</code>
* @throws InvalidNodeTypeDefException if the node type is not valid
* @throws RepositoryException if another error occurs
*/
private static EffectiveNodeType validateNodeTypeDef(QNodeTypeDefinition ntd, EffectiveNodeTypeCache entCache, Map<Name, QNodeTypeDefinition> ntdCache, NamespaceRegistry nsReg, boolean lenient) throws InvalidNodeTypeDefException, RepositoryException {
/**
* the effective (i.e. merged and resolved) node type resulting from
* the specified node type definition;
* the effective node type will finally be created after the definition
* has been verified and checked for conflicts etc.; in some cases it
* will be created already at an earlier stage during the validation
* of child node definitions
*/
EffectiveNodeType ent = null;
Name name = ntd.getName();
if (name == null) {
String msg = "no name specified";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
checkNamespace(name, nsReg);
// validate supertypes
Name[] supertypes = ntd.getSupertypes();
if (supertypes.length > 0) {
for (Name supertype : supertypes) {
checkNamespace(supertype, nsReg);
/**
* simple check for infinite recursion
* (won't trap recursion on a deeper inheritance level)
*/
if (name.equals(supertype)) {
String msg = "[" + name + "] invalid supertype: " + supertype + " (infinite recursion))";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
if (!ntdCache.containsKey(supertype)) {
String msg = "[" + name + "] invalid supertype: " + supertype;
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
}
/**
* check for circularity in inheritance chain
* ('a' extends 'b' extends 'a')
*/
Stack<Name> inheritanceChain = new Stack<Name>();
inheritanceChain.push(name);
checkForCircularInheritance(supertypes, inheritanceChain, ntdCache);
}
/**
* build effective (i.e. merged and resolved) node type from supertypes
* and check for conflicts
*/
if (supertypes.length > 0) {
try {
EffectiveNodeType est = getEffectiveNodeType(supertypes, entCache, ntdCache);
// a supertypes's primaryItem -> illegal (JCR-1947)
if (ntd.getPrimaryItemName() != null && est.getPrimaryItemName() != null) {
String msg = "[" + name + "] primaryItemName is already specified by a supertype and must therefore not be overridden.";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
} catch (NodeTypeConflictException ntce) {
String msg = "[" + name + "] failed to validate supertypes";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, ntce);
} catch (NoSuchNodeTypeException nsnte) {
String msg = "[" + name + "] failed to validate supertypes";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, nsnte);
}
}
checkNamespace(ntd.getPrimaryItemName(), nsReg);
// validate property definitions
QPropertyDefinition[] pda = ntd.getPropertyDefs();
for (QPropertyDefinition pd : pda) {
/**
* sanity check:
* make sure declaring node type matches name of node type definition
*/
if (!name.equals(pd.getDeclaringNodeType())) {
String msg = "[" + name + "#" + pd.getName() + "] invalid declaring node type specified";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
checkNamespace(pd.getName(), nsReg);
// check that auto-created properties specify a name
if (pd.definesResidual() && pd.isAutoCreated()) {
String msg = "[" + name + "#" + pd.getName() + "] auto-created properties must specify a name";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
// check that auto-created properties specify a type
if (pd.getRequiredType() == PropertyType.UNDEFINED && pd.isAutoCreated()) {
String msg = "[" + name + "#" + pd.getName() + "] auto-created properties must specify a type";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
/**
* check default values:
* make sure type of value is consistent with required property type
*/
QValue[] defVals = pd.getDefaultValues();
if (defVals != null && defVals.length != 0) {
int reqType = pd.getRequiredType();
for (QValue defVal : defVals) {
if (reqType == PropertyType.UNDEFINED) {
reqType = defVal.getType();
} else {
if (defVal.getType() != reqType) {
String msg = "[" + name + "#" + pd.getName() + "] type of default value(s) is not consistent with required property type";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
}
}
} else {
// no default values specified
if (!lenient) {
// auto-created properties must have a default value
if (pd.isAutoCreated()) {
String msg = "[" + name + "#" + pd.getName() + "] auto-created property must have a default value";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
}
}
// check that default values satisfy value constraints
QValueConstraint[] constraints = pd.getValueConstraints();
if (constraints != null && constraints.length > 0) {
if (defVals != null && defVals.length > 0) {
// check value constraints on every value
for (QValue defVal : defVals) {
// constraints are OR-ed together
boolean satisfied = false;
ConstraintViolationException cve = null;
for (QValueConstraint constraint : constraints) {
try {
constraint.check(defVal);
// at least one constraint is satisfied
satisfied = true;
break;
} catch (ConstraintViolationException e) {
cve = e;
}
}
if (!satisfied) {
// report last exception we encountered
String msg = "[" + name + "#" + pd.getName() + "] default value does not satisfy value constraint";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, cve);
}
}
}
/**
* ReferenceConstraint:
* the specified node type must be registered, with one notable
* exception: the node type just being registered
*/
if (pd.getRequiredType() == PropertyType.REFERENCE || pd.getRequiredType() == PropertyType.WEAKREFERENCE) {
for (QValueConstraint constraint : constraints) {
Name ntName = NameFactoryImpl.getInstance().create(constraint.getString());
if (!name.equals(ntName) && !ntdCache.containsKey(ntName)) {
String msg = "[" + name + "#" + pd.getName() + "] invalid " + (pd.getRequiredType() == PropertyType.REFERENCE ? "REFERENCE" : "WEAKREFERENCE") + " value constraint '" + ntName + "' (unknown node type)";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
}
}
}
}
// validate child-node definitions
QNodeDefinition[] cnda = ntd.getChildNodeDefs();
for (QNodeDefinition cnd : cnda) {
/**
* sanity check:
* make sure declaring node type matches name of node type definition
*/
if (!name.equals(cnd.getDeclaringNodeType())) {
String msg = "[" + name + "#" + cnd.getName() + "] invalid declaring node type specified";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
checkNamespace(cnd.getName(), nsReg);
// check that auto-created child-nodes specify a name
if (cnd.definesResidual() && cnd.isAutoCreated()) {
String msg = "[" + name + "#" + cnd.getName() + "] auto-created child-nodes must specify a name";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
// check that auto-created child-nodes specify a default primary type
if (cnd.getDefaultPrimaryType() == null && cnd.isAutoCreated()) {
String msg = "[" + name + "#" + cnd.getName() + "] auto-created child-nodes must specify a default primary type";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
// check default primary type
Name dpt = cnd.getDefaultPrimaryType();
checkNamespace(dpt, nsReg);
boolean referenceToSelf = false;
EffectiveNodeType defaultENT = null;
if (dpt != null) {
// check if this node type specifies itself as default primary type
if (name.equals(dpt)) {
referenceToSelf = true;
}
/**
* the default primary type must be registered, with one notable
* exception: the node type just being registered
*/
if (!name.equals(dpt) && !ntdCache.containsKey(dpt)) {
String msg = "[" + name + "#" + cnd.getName() + "] invalid default primary type '" + dpt + "'";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
/**
* build effective (i.e. merged and resolved) node type from
* default primary type and check for conflicts
*/
try {
if (!referenceToSelf) {
defaultENT = getEffectiveNodeType(dpt, entCache, ntdCache);
} else {
/**
* the default primary type is identical with the node
* type just being registered; we have to instantiate it
* 'manually'
*/
ent = EffectiveNodeType.create(ntd, entCache, ntdCache);
defaultENT = ent;
}
if (cnd.isAutoCreated()) {
/**
* check for circularity through default primary types
* of auto-created child nodes (node type 'a' defines
* auto-created child node with default primary type 'a')
*/
Stack<Name> definingNTs = new Stack<Name>();
definingNTs.push(name);
checkForCircularNodeAutoCreation(defaultENT, definingNTs, entCache, ntdCache);
}
} catch (NodeTypeConflictException ntce) {
String msg = "[" + name + "#" + cnd.getName() + "] failed to validate default primary type";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, ntce);
} catch (NoSuchNodeTypeException nsnte) {
String msg = "[" + name + "#" + cnd.getName() + "] failed to validate default primary type";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, nsnte);
}
}
// check required primary types
Name[] reqTypes = cnd.getRequiredPrimaryTypes();
if (reqTypes != null && reqTypes.length > 0) {
for (Name rpt : reqTypes) {
// skip nt:base required types
if (NameConstants.NT_BASE.equals(rpt)) {
continue;
}
checkNamespace(rpt, nsReg);
referenceToSelf = false;
/**
* check if this node type specifies itself as required
* primary type
*/
if (name.equals(rpt)) {
referenceToSelf = true;
}
/**
* the required primary type must be registered, with one
* notable exception: the node type just being registered
*/
if (!name.equals(rpt) && !ntdCache.containsKey(rpt)) {
String msg = "[" + name + "#" + cnd.getName() + "] invalid required primary type: " + rpt;
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
/**
* check if default primary type satisfies the required
* primary type constraint
*/
if (defaultENT != null && !defaultENT.includesNodeType(rpt)) {
String msg = "[" + name + "#" + cnd.getName() + "] default primary type does not satisfy required primary type constraint " + rpt;
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
/**
* build effective (i.e. merged and resolved) node type from
* required primary type constraint and check for conflicts
*/
try {
if (!referenceToSelf) {
getEffectiveNodeType(rpt, entCache, ntdCache);
} else {
/**
* the required primary type is identical with the
* node type just being registered; we have to
* instantiate it 'manually'
*/
if (ent == null) {
ent = EffectiveNodeType.create(ntd, entCache, ntdCache);
}
}
} catch (NodeTypeConflictException ntce) {
String msg = "[" + name + "#" + cnd.getName() + "] failed to validate required primary type constraint";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, ntce);
} catch (NoSuchNodeTypeException nsnte) {
String msg = "[" + name + "#" + cnd.getName() + "] failed to validate required primary type constraint";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, nsnte);
}
}
}
}
/**
* now build effective (i.e. merged and resolved) node type from
* this node type definition; this will potentially detect more
* conflicts or problems
*/
if (ent == null) {
try {
ent = EffectiveNodeType.create(ntd, entCache, ntdCache);
} catch (NodeTypeConflictException ntce) {
String msg = "[" + name + "] failed to resolve node type definition";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, ntce);
} catch (NoSuchNodeTypeException nsnte) {
String msg = "[" + name + "] failed to resolve node type definition";
log.debug(msg);
throw new InvalidNodeTypeDefException(msg, nsnte);
}
}
return ent;
}
Aggregations