use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.
the class PathParser method parse.
/**
* Parses the given <code>jcrPath</code> and returns a <code>Path</code>. If
* <code>parent</code> is not <code>null</code>, it is prepended to the
* built path before it is returned. If the specified <code>jcrPath</code>
* is an identifier based absolute path beginning with an identifier segment
* the given <code>identifierResolver</code> will be used to resolve it to an
* absolute path.<p/>
* If <code>nameResolver</code> is <code>null</code> or if <code>identifierResolver</code>
* is <code>null</code> and the path starts with an identifier segment, this
* method only checks the format of the string and returns <code>null</code>.
*
* @param parent the parent path.
* @param jcrPath the jcr path.
* @param nameResolver the namespace resolver.
* @param identifierResolver the resolver to validate any trailing identifier
* segment and resolve it to an absolute path.
* @param factory The path factory.
* @param normalizeIdentifier
* @return the <code>Path</code> object.
* @throws MalformedPathException
* @throws IllegalNameException
* @throws NamespaceException
*/
private static Path parse(Path parent, String jcrPath, NameResolver nameResolver, IdentifierResolver identifierResolver, PathFactory factory, boolean normalizeIdentifier) throws MalformedPathException, IllegalNameException, NamespaceException {
// check for length
int len = jcrPath == null ? 0 : jcrPath.length();
// shortcut
if (len == 1 && jcrPath.charAt(0) == '/') {
return factory.getRootPath();
}
if (len == 0) {
throw new MalformedPathException("empty path");
}
// check if absolute path
PathBuilder builder = new PathBuilder(factory);
int pos = 0;
if (jcrPath.charAt(0) == '/') {
if (parent != null) {
throw new MalformedPathException("'" + jcrPath + "' is not a relative path.");
}
builder.addRoot();
pos++;
}
// add master if present
if (parent != null) {
builder.addAll(parent.getElements());
}
// parse the path
int state;
if (jcrPath.charAt(0) == '[') {
if (parent != null) {
throw new MalformedPathException("'" + jcrPath + "' is not a relative path.");
}
state = STATE_IDENTIFIER;
pos++;
} else {
state = STATE_PREFIX_START;
}
int lastPos = pos;
String name = null;
int index = Path.INDEX_UNDEFINED;
boolean wasSlash = false;
boolean checkFormat = (nameResolver == null);
while (pos <= len) {
char c = pos == len ? EOF : jcrPath.charAt(pos);
char rawCharacter = c;
pos++;
// special check for whitespace
if (c != ' ' && Character.isWhitespace(c)) {
c = '\t';
}
switch(c) {
case '/':
case EOF:
if (state == STATE_PREFIX_START && c != EOF) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. double slash '//' not allowed.");
}
if (state == STATE_URI && c == EOF) {
// this handles the case where URI state was entered but the end of the segment was reached (JCR-3562)
state = STATE_URI_END;
}
if (state == STATE_PREFIX || state == STATE_NAME || state == STATE_INDEX_END || state == STATE_URI_END) {
// eof pathelement
if (name == null) {
if (wasSlash) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Trailing slashes not allowed in prefixes and names.");
}
name = jcrPath.substring(lastPos, pos - 1);
}
// is just a check for valid format.
if (checkFormat) {
NameParser.checkFormat(name);
} else {
Name qName = nameResolver.getQName(name);
builder.addLast(qName, index);
}
state = STATE_PREFIX_START;
lastPos = pos;
name = null;
index = Path.INDEX_UNDEFINED;
} else if (state == STATE_IDENTIFIER) {
if (c == EOF) {
// eof identifier reached
if (jcrPath.charAt(pos - 2) != ']') {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Unterminated identifier segment.");
}
String identifier = jcrPath.substring(lastPos, pos - 2);
if (checkFormat) {
if (identifierResolver != null) {
identifierResolver.checkFormat(identifier);
}
// else ignore. TODO: rather throw?
} else if (identifierResolver == null) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Identifier segments are not supported.");
} else if (normalizeIdentifier) {
builder.addAll(identifierResolver.getPath(identifier).getElements());
} else {
identifierResolver.checkFormat(identifier);
builder.addLast(factory.createElement(identifier));
}
state = STATE_PREFIX_START;
lastPos = pos;
}
} else if (state == STATE_DOT) {
builder.addLast(factory.getCurrentElement());
lastPos = pos;
state = STATE_PREFIX_START;
} else if (state == STATE_DOTDOT) {
builder.addLast(factory.getParentElement());
lastPos = pos;
state = STATE_PREFIX_START;
} else if (state != STATE_URI && !(state == STATE_PREFIX_START && c == EOF)) {
// ignore trailing slash
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
}
break;
case '.':
if (state == STATE_PREFIX_START) {
state = STATE_DOT;
} else if (state == STATE_DOT) {
state = STATE_DOTDOT;
} else if (state == STATE_DOTDOT) {
state = STATE_PREFIX;
} else if (state == STATE_INDEX_END) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected.");
}
break;
case ':':
if (state == STATE_PREFIX_START) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. Prefix must not be empty");
} else if (state == STATE_PREFIX) {
if (wasSlash) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Trailing slashes not allowed in prefixes and names.");
}
state = STATE_NAME_START;
// don't reset the lastPos/pos since prefix+name are passed together to the NameResolver
} else if (state != STATE_IDENTIFIER && state != STATE_URI) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid name character");
}
break;
case '[':
if (state == STATE_PREFIX || state == STATE_NAME) {
if (wasSlash) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path: Trailing slashes not allowed in prefixes and names.");
}
state = STATE_INDEX;
name = jcrPath.substring(lastPos, pos - 1);
lastPos = pos;
} else if (state != STATE_IDENTIFIER) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
}
break;
case ']':
if (state == STATE_INDEX) {
try {
index = Integer.parseInt(jcrPath.substring(lastPos, pos - 1));
} catch (NumberFormatException e) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. NumberFormatException in index: " + jcrPath.substring(lastPos, pos - 1));
}
if (index < Path.INDEX_DEFAULT) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. Index number invalid: " + index);
}
state = STATE_INDEX_END;
} else if (state != STATE_IDENTIFIER) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
}
break;
case ' ':
if (state == STATE_PREFIX_START || state == STATE_NAME_START) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid name start");
} else if (state == STATE_INDEX_END) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected.");
} else if (state == STATE_DOT || state == STATE_DOTDOT) {
state = STATE_PREFIX;
}
break;
case '\t':
if (state != STATE_IDENTIFIER) {
String message = String.format("'%s' is not a valid path. Whitespace other than SP (U+0020) not a allowed in a name, but U+%04x was found at position %d.", jcrPath, (long) rawCharacter, pos - 1);
throw new MalformedPathException(message);
}
case '*':
case '|':
if (state != STATE_IDENTIFIER) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not a valid name character.");
}
case '{':
if (state == STATE_PREFIX_START && lastPos == pos - 1) {
// '{' marks the start of a uri enclosed in an expanded name
// instead of the usual namespace prefix, if it is
// located at the beginning of a new segment.
state = STATE_URI;
} else if (state == STATE_NAME_START || state == STATE_DOT || state == STATE_DOTDOT) {
// otherwise it's part of the local name
state = STATE_NAME;
}
break;
case '}':
if (state == STATE_URI) {
state = STATE_URI_END;
}
break;
default:
if (state == STATE_PREFIX_START || state == STATE_DOT || state == STATE_DOTDOT) {
state = STATE_PREFIX;
} else if (state == STATE_NAME_START) {
state = STATE_NAME;
} else if (state == STATE_INDEX_END) {
throw new MalformedPathException("'" + jcrPath + "' is not a valid path. '" + c + "' not valid after index. '/' expected.");
}
}
wasSlash = c == ' ';
}
if (checkFormat) {
// this was only for checking the format
return null;
} else {
return builder.getPath();
}
}
use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.
the class QNodeTypeDefinitionImpl method createQPropertyDefinitions.
private static QPropertyDefinition[] createQPropertyDefinitions(Name declName, PropertyDefinition[] pds, NamePathResolver resolver, QValueFactory qValueFactory) throws RepositoryException {
if (pds == null || pds.length == 0) {
return QPropertyDefinition.EMPTY_ARRAY;
}
QPropertyDefinition[] declaredPropDefs = new QPropertyDefinition[pds.length];
for (int i = 0; i < pds.length; i++) {
PropertyDefinition propDef = pds[i];
Name name = propDef.getName().equals(NameConstants.ANY_NAME.getLocalName()) ? NameConstants.ANY_NAME : resolver.getQName(propDef.getName());
// check if propDef provides declaring node type and if it matches 'this' one.
if (propDef.getDeclaringNodeType() != null) {
if (!declName.equals(resolver.getQName(propDef.getDeclaringNodeType().getName()))) {
throw new RepositoryException("Property definition specified invalid declaring nodetype: " + propDef.getDeclaringNodeType().getName() + ", but should be " + declName);
}
}
QValue[] defVls = propDef.getDefaultValues() == null ? QValue.EMPTY_ARRAY : ValueFormat.getQValues(propDef.getDefaultValues(), resolver, qValueFactory);
String[] jcrConstraints = propDef.getValueConstraints();
QValueConstraint[] constraints = QValueConstraint.EMPTY_ARRAY;
if (jcrConstraints != null && jcrConstraints.length > 0) {
constraints = new QValueConstraint[jcrConstraints.length];
for (int j = 0; j < constraints.length; j++) {
constraints[j] = ValueConstraint.create(propDef.getRequiredType(), jcrConstraints[j], resolver);
}
}
declaredPropDefs[i] = new QPropertyDefinitionImpl(name, declName, propDef.isAutoCreated(), propDef.isMandatory(), propDef.getOnParentVersion(), propDef.isProtected(), defVls, propDef.isMultiple(), propDef.getRequiredType(), constraints, propDef.getAvailableQueryOperators(), propDef.isFullTextSearchable(), propDef.isQueryOrderable());
}
return declaredPropDefs;
}
use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.
the class BundleReader method readBundleOld.
private void readBundleOld(NodePropBundle bundle) throws IOException {
// read primary type...special handling
int a = in.readUnsignedByte();
int b = in.readUnsignedByte();
int c = in.readUnsignedByte();
String uri = binding.nsIndex.indexToString(a << 16 | b << 8 | c);
String local = binding.nameIndex.indexToString(in.readInt());
bundle.setNodeTypeName(NameFactoryImpl.getInstance().create(uri, local));
// parentUUID
bundle.setParentId(readNodeId());
// definitionId
in.readUTF();
// mixin types
Name name = readIndexedQName();
if (name != null) {
Set<Name> mixinTypeNames = new HashSet<Name>();
do {
mixinTypeNames.add(name);
name = readIndexedQName();
} while (name != null);
bundle.setMixinTypeNames(mixinTypeNames);
} else {
bundle.setMixinTypeNames(Collections.<Name>emptySet());
}
// properties
name = readIndexedQName();
while (name != null) {
PropertyId pId = new PropertyId(bundle.getId(), name);
NodePropBundle.PropertyEntry pState = readPropertyEntry(pId);
// skip redundant primaryType, mixinTypes and uuid properties
if (!name.equals(NameConstants.JCR_PRIMARYTYPE) && !name.equals(NameConstants.JCR_UUID)) {
bundle.addProperty(pState);
}
name = readIndexedQName();
}
// set referenceable flag
bundle.setReferenceable(in.readBoolean());
// child nodes (list of uuid/name pairs)
NodeId childId = readNodeId();
while (childId != null) {
bundle.addChildNodeEntry(readQName(), childId);
childId = readNodeId();
}
// read modcount, since version 1.0
if (version >= BundleBinding.VERSION_1) {
bundle.setModCount(in.readShort());
}
// read shared set, since version 2.0
if (version >= BundleBinding.VERSION_2) {
// shared set (list of parent uuids)
NodeId parentId = readNodeId();
if (parentId != null) {
Set<NodeId> shared = new HashSet<NodeId>();
do {
shared.add(parentId);
parentId = readNodeId();
} while (parentId != null);
bundle.setSharedSet(shared);
} else {
bundle.setSharedSet(Collections.<NodeId>emptySet());
}
} else {
bundle.setSharedSet(Collections.<NodeId>emptySet());
}
}
use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.
the class BundleWriter method writeBundle.
/**
* Serializes a <code>NodePropBundle</code> to a data output stream
*
* @param bundle the bundle to serialize
* @throws IOException if an I/O error occurs.
*/
public void writeBundle(NodePropBundle bundle) throws IOException {
long size = out.size();
// primaryType
writeName(bundle.getNodeTypeName());
// parentUUID
NodeId parentId = bundle.getParentId();
if (parentId == null) {
parentId = BundleBinding.NULL_PARENT_ID;
}
writeNodeId(parentId);
// write mod count
writeVarInt(bundle.getModCount());
Collection<Name> mixins = bundle.getMixinTypeNames();
Collection<PropertyEntry> properties = bundle.getPropertyEntries();
Collection<ChildNodeEntry> nodes = bundle.getChildNodeEntries();
Collection<NodeId> shared = bundle.getSharedSet();
int mn = mixins.size();
int pn = properties.size();
int nn = nodes.size();
int sn = shared.size();
int referenceable = 0;
if (bundle.isReferenceable()) {
referenceable = 1;
}
out.writeByte(Math.min(mn, 1) << 7 | Math.min(pn, 7) << 4 | Math.min(nn, 3) << 2 | Math.min(sn, 1) << 1 | referenceable);
// mixin types
writeVarInt(mn, 1);
for (Name name : mixins) {
writeName(name);
}
// properties
writeVarInt(pn, 7);
for (PropertyEntry property : properties) {
writeState(property);
}
// child nodes (list of name/uuid pairs)
writeVarInt(nn, 3);
for (ChildNodeEntry child : nodes) {
// name
writeName(child.getName());
// uuid
writeNodeId(child.getId());
}
// write shared set
writeVarInt(sn, 1);
for (NodeId nodeId : shared) {
writeNodeId(nodeId);
}
// set size of bundle
bundle.setSize(out.size() - size);
}
use of org.apache.jackrabbit.spi.Name in project jackrabbit by apache.
the class Serializer method deserialize.
/**
* Deserializes a <code>NodeState</code> object from the given binary
* <code>stream</code>.
*
* @param state <code>state</code> to deserialize
* @param stream the stream where the <code>state</code> should be deserialized from
* @throws Exception if an error occurs during the deserialization
* @see #serialize(NodeState, OutputStream)
*/
public static void deserialize(NodeState state, InputStream stream) throws Exception {
DataInputStream in = new DataInputStream(stream);
// primaryType
String s = in.readUTF();
state.setNodeTypeName(NameFactoryImpl.getInstance().create(s));
// parentUUID (may be null)
byte[] uuidBytes = new byte[NodeId.UUID_BYTE_LENGTH];
in.readFully(uuidBytes);
if (!Arrays.equals(uuidBytes, NULL_UUID_PLACEHOLDER_BYTES)) {
state.setParentId(new NodeId(uuidBytes));
}
// definitionId
in.readUTF();
// mixin types
// count
int count = in.readInt();
Set<Name> set = new HashSet<Name>(count);
for (int i = 0; i < count; i++) {
set.add(NameFactoryImpl.getInstance().create(in.readUTF()));
}
if (set.size() > 0) {
state.setMixinTypeNames(set);
}
// modCount
short modCount = in.readShort();
state.setModCount(modCount);
// properties (names)
// count
count = in.readInt();
for (int i = 0; i < count; i++) {
// name
state.addPropertyName(NameFactoryImpl.getInstance().create(in.readUTF()));
}
// child nodes (list of name/uuid pairs)
// count
count = in.readInt();
for (int i = 0; i < count; i++) {
// name
Name name = NameFactoryImpl.getInstance().create(in.readUTF());
// uuid
in.readFully(uuidBytes);
state.addChildNodeEntry(name, new NodeId(uuidBytes));
}
}
Aggregations