Skip to content
Commits on Source (2)
Release Notes -- Apache Jackrabbit -- Version 2.14.4
Release Notes -- Apache Jackrabbit -- Version 2.14.6
Introduction
------------
This is Apache Jackrabbit(TM) 2.14.4, a fully compliant implementation of the
This is Apache Jackrabbit(TM) 2.14.6, a fully compliant implementation of the
Content Repository for Java(TM) Technology API, version 2.0 (JCR 2.0) as
specified in the Java Specification Request 283 (JSR 283).
Apache Jackrabbit 2.14.4 is a patch release that contains fixes and
Apache Jackrabbit 2.14.6 is a patch release that contains fixes and
improvements over Jackrabbit 2.14. Jackrabbit 2.14.x releases are
considered stable and targeted for production use.
Changes in Jackrabbit 2.14.4
Changes in Jackrabbit 2.14.6
----------------------------
Bug
[JCR-3929] - ConsistencyCheck may fail on empty repository
[JCR-4183] - Jackrabbit standalone jar isn't working under JDK 8
[JCR-4185] - spi2dav URIResolverImpl should check status code before attempting to parse multistatus
[JCR-4188] - avoid use of sun.security.acl.GroupImpl in PrincipalManagerTest
[JCR-4093] - IndexRule are meant to be applied based on both primaryType and minin type based inheritance. Currently it appears that only primaryType based inheritance is working
[JCR-4291] - FileInputStream for workspace.xml not closed in RepositoryConfig.loadWorkspaceConfig(File)
[JCR-4317] - davex remoting fails for non-ASCII characters in node names
[JCR-4324] - NPE on Version.getLinearPredecessor() implementation
Improvement
[JCR-3211] - Support HTTP proxy in SPI2DAV
[JCR-4253] - RepositoryConfig: add some handling for mkdir failure
[JCR-4292] - davex: preserve cause in exceptions and log affected URI
Task
[JCR-4184] - migrate from org.mortbay.jetty to org.eclipse.jetty
[JCR-4186] - Use current Derby version
[JCR-4254] - Update Logback version to >= 1.2.0, SLF4J accordingly
[JCR-4256] - create announcement mail template for releases
[JCR-4261] - webapp: align jsons-simple dependencies internally and with oak
[JCR-4262] - jcr-server: align org.apache.felix.scr.annotations with oak
[JCR-4263] - jcr-server, jackrabbit-bundle: align org.osgi dependencies with oak
[JCR-4264] - jackrabbit-standalone: align commons-cli dependency with oak
[JCR-4272] - Upgrade surefire and failsafe plugins to 2.21.0
[JCR-4288] - Upgrade tika-parsers dependency to 1.18
[JCR-4290] - remove unused commons-codec dependency
[JCR-4293] - jackrabbit-core: observation tests should not rely on mix:lockable mixin type
[JCR-4294] - TCK tests should pass on repositories without locking support
[JCR-4296] - Upgrade httpmime dependency to 4.5.5
[JCR-4302] - BTreeManager: fix Eclipse compiler error
[JCR-4304] - update Jetty to supported version 9.2.*
[JCR-4307] - Update animal-sniffer-maven-plugin to 1.16
[JCR-4318] - Update failsafe and surefire plugin versions to 2.22.0
[JCR-4320] - Update spotbugs plugin to 3.1.5
[JCR-4321] - Update maven plugins from org.apache.maven.plugins
[JCR-4322] - Consistent use of log4j versions
[JCR-4323] - webapp: update Tomcat dependency to 8.5.32
[JCR-4326] - Update aws java sdk version to 1.11.330 (consistent with Oak)
[JCR-4327] - Update httpcore dependency to 4.4.10
[JCR-4331] - Update httpclient dependency to 4.5.6
[JCR-4332] - Update httpmime dependency to 4.5.6
[JCR-4333] - Update javax.transaction dependency to 1.3
Sub-task
[JCR-4190] - maven-assembly-plugin:2.6:single failing with Java 9
[JCR-4196] - update surefire and failsafe plugins for use with java 9
[JCR-4200] - javax.transaction.UserTransaction hidden by surefire plugin in with Java 9
[JCR-4280] - code coverage checks fail on Java 10
[JCR-4306] - switch to findbugs replacement that is still maintained (spotbugs)
[JCR-4338] - avoid use of javax.rmi.PortableRemoteObject (removed in Java 11)
For more detailed information about all the changes in this and other
......@@ -45,10 +74,10 @@ This release consists of a single source archive packaged as a zip file.
The archive can be unpacked with the jar tool from your JDK installation.
See the README.txt file for instructions on how to build this release.
The source archive is accompanied by SHA1 and MD5 checksums and a PGP
signature that you can use to verify the authenticity of your download.
The public key used for the PGP signature can be found at
https://svn.apache.org/repos/asf/jackrabbit/dist/KEYS.
The source archive is accompanied by SHA1 and SHA512 checksums and a
PGP signature that you can use to verify the authenticity of your
download. The public key used for the PGP signature can be found at
https://www.apache.org/dist/jackrabbit/KEYS.
About Apache Jackrabbit
-----------------------
......
......@@ -60,7 +60,6 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
</dependencies>
......
......@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-parent</artifactId>
<version>2.14.4</version>
<version>2.14.6</version>
<relativePath>../jackrabbit-parent/pom.xml</relativePath>
</parent>
<artifactId>jackrabbit-api</artifactId>
......
......@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-parent</artifactId>
<version>2.14.4</version>
<version>2.14.6</version>
<relativePath>../jackrabbit-parent/pom.xml</relativePath>
</parent>
<artifactId>jackrabbit-aws-ext</artifactId>
......@@ -49,7 +49,7 @@
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.10.27</version>
<version>1.11.330</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
......@@ -75,7 +75,6 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
<scope>test</scope>
</dependency>
</dependencies>
......
......@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-parent</artifactId>
<version>2.14.4</version>
<version>2.14.6</version>
<relativePath>../jackrabbit-parent/pom.xml</relativePath>
</parent>
<artifactId>jackrabbit-bundle</artifactId>
......@@ -75,13 +75,13 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.0.0</version>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>4.0.0</version>
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
......
......@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-parent</artifactId>
<version>2.14.4</version>
<version>2.14.6</version>
<relativePath>../jackrabbit-parent/pom.xml</relativePath>
</parent>
<artifactId>jackrabbit-core</artifactId>
......@@ -115,6 +115,7 @@ org.apache.jackrabbit.test.api.lock.SessionScopedLockTest#testLockExpiration
org.apache.jackrabbit.test.api.observation.NodeReorderTest#testNodeReorderMove
org.apache.jackrabbit.core.data.ConcurrentGcTest#testDatabases
org.apache.jackrabbit.core.data.GarbageCollectorTest#testCloseSessionWhileRunningGc
org.apache.jackrabbit.core.data.GarbageCollectorTest#testSimultaneousRunGC <!-- JCR-4078 -->
org.apache.jackrabbit.core.ReplacePropertyWhileOthersReadTest <!-- JCR-3835 -->
org.apache.jackrabbit.core.security.user.MembershipCachePerfTest <!-- don't run expensive test -->
org.apache.jackrabbit.test.api.query.qom.NodeLocalNameTest#testStringLiteralInvalidName <!-- OAK-3265 -->
......@@ -164,7 +165,6 @@ org.apache.jackrabbit.test.api.query.qom.NodeLocalNameTest#testURILiteral
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<excludes>
<exclude>logback-test.xml</exclude>
......@@ -334,14 +334,14 @@ org.apache.jackrabbit.test.api.query.qom.NodeLocalNameTest#testURILiteral
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.0.1B_spec</artifactId>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.149</version>
<version>1.4.195</version>
<scope>test</scope>
</dependency>
<dependency>
......
......@@ -408,10 +408,9 @@ public class ItemManager implements ItemStateListener {
* in which case the itemId present with the specified <code>data</code> is used.
* @return true if the item with the given <code>data</code> can be read;
* <code>false</code> otherwise.
* @throws AccessDeniedException
* @throws RepositoryException
*/
private boolean canRead(ItemData data, Path path) throws AccessDeniedException, RepositoryException {
private boolean canRead(ItemData data, Path path) throws RepositoryException {
// JCR-1601: cached item may just have been invalidated
ItemState state = data.getState();
if (state == null) {
......
......@@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.util.ArrayList;
......@@ -587,7 +588,7 @@ public class RepositoryImpl extends AbstractRepository
uuidFile.makeParentDirs();
OutputStream out = uuidFile.getOutputStream();
try {
out.write(ROOT_NODE_ID.toString().getBytes("US-ASCII"));
out.write(ROOT_NODE_ID.toString().getBytes(StandardCharsets.US_ASCII));
return ROOT_NODE_ID;
} finally {
IOUtils.closeQuietly(out);
......
......@@ -22,6 +22,8 @@ import java.io.InputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
......@@ -46,7 +48,7 @@ public class TestContentLoader {
/**
* The encoding of the test resources.
*/
private static final String ENCODING = "UTF-8";
private static final Charset ENCODING = StandardCharsets.UTF_8;
public void loadTestContent(Session session) throws RepositoryException, IOException {
JackrabbitWorkspace workspace =
......@@ -151,7 +153,7 @@ public class TestContentLoader {
Node resource = node.addNode("myResource", "nt:resource");
// nt:resource not longer referenceable since JCR 2.0
resource.addMixin("mix:referenceable");
resource.setProperty("jcr:encoding", ENCODING);
resource.setProperty("jcr:encoding", ENCODING.name());
resource.setProperty("jcr:mimeType", "text/plain");
resource.setProperty(
"jcr:data",
......@@ -173,7 +175,7 @@ public class TestContentLoader {
// NodeDefTest requires a test node with a mandatory child node
JcrUtils.putFile(
node, "testFile", "text/plain",
new ByteArrayInputStream("Hello, World!".getBytes("UTF-8")));
new ByteArrayInputStream("Hello, World!".getBytes(StandardCharsets.UTF_8)));
}
/**
......@@ -243,7 +245,7 @@ public class TestContentLoader {
getOrAddNode(node, prefix + "MultiNoBin").setProperty(name, texts);
Node resource = getOrAddNode(node, prefix + "MultiBin");
resource.setProperty("jcr:encoding", ENCODING);
resource.setProperty("jcr:encoding", ENCODING.name());
resource.setProperty("jcr:mimeType", "text/plain");
String[] values =
new String[] { "SGVsbG8gd8O2cmxkLg==", "SGVsbG8gd8O2cmxkLg==" };
......@@ -253,7 +255,7 @@ public class TestContentLoader {
getOrAddNode(node, prefix + "NoBin").setProperty(name, "text 1");
resource = getOrAddNode(node, "invalidBin");
resource.setProperty("jcr:encoding", ENCODING);
resource.setProperty("jcr:encoding", ENCODING.name());
resource.setProperty("jcr:mimeType", "text/plain");
byte[] bytes = "Hello w\u00F6rld.".getBytes(ENCODING);
resource.setProperty(name, new ByteArrayInputStream(bytes));
......
......@@ -192,10 +192,13 @@ public class RepositoryConfig
private static void installRepositorySkeleton(
File dir, File xml, URL resource)
throws IOException {
throws IOException, ConfigurationException {
if (!dir.exists()) {
log.info("Creating repository directory {}", dir);
dir.mkdirs();
boolean dirCreated = dir.mkdirs();
if (!dirCreated) {
throw new ConfigurationException("Cannot create repository directory " + dir);
}
}
if (!xml.exists()) {
......@@ -541,7 +544,10 @@ public class RepositoryConfig
// Get the physical workspace root directory (create it if not found)
File directory = new File(workspaceDirectory);
if (!directory.exists()) {
directory.mkdirs();
boolean directoryCreated = directory.mkdirs();
if (!directoryCreated) {
throw new ConfigurationException("Cannot create workspace root directory " + directory);
}
}
// Get all workspace subdirectories
......@@ -618,9 +624,11 @@ public class RepositoryConfig
*/
private WorkspaceConfig loadWorkspaceConfig(File directory)
throws ConfigurationException {
FileInputStream fin = null;
try {
File file = new File(directory, WORKSPACE_XML);
InputSource xml = new InputSource(new FileInputStream(file));
fin = new FileInputStream(file);
InputSource xml = new InputSource(fin);
xml.setSystemId(file.toURI().toString());
Properties variables = new Properties();
......@@ -632,6 +640,8 @@ public class RepositoryConfig
return localParser.parseWorkspaceConfig(xml);
} catch (FileNotFoundException e) {
return null;
} finally {
IOUtils.closeQuietly(fin);
}
}
......
......@@ -644,11 +644,10 @@ public class NodeTypeManagerImpl extends AbstractNodeTypeManager
*
* @param definition the definition
* @return a <code>NodeTypeDef</code>
* @throws InvalidNodeTypeDefinitionException if the definition is invalid
* @throws RepositoryException if a repository error occurs
*/
private QNodeTypeDefinition toNodeTypeDef(NodeTypeDefinition definition)
throws InvalidNodeTypeDefinitionException, RepositoryException {
throws RepositoryException {
return new QNodeTypeDefinitionImpl(definition, context, QValueFactoryImpl.getInstance());
}
......
......@@ -21,6 +21,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
......@@ -790,7 +791,7 @@ public class NodeTypeRegistry implements NodeTypeEventListener {
try {
in = getClass().getClassLoader().getResourceAsStream(BUILTIN_NODETYPES_RESOURCE_PATH);
if (in != null) {
Reader r = new InputStreamReader(in, "utf-8");
Reader r = new InputStreamReader(in, StandardCharsets.UTF_8);
store.loadCND(r, BUILTIN_NODETYPES_RESOURCE_PATH);
}
} catch (IOException ioe) {
......
......@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.nodetype.virtual;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
......@@ -251,12 +252,10 @@ public class VirtualNodeTypeStateProvider extends AbstractVISProvider {
private static NodeId calculateStableId(String name) throws RepositoryException {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(name.getBytes("utf-8"));
byte[] digest = md.digest(name.getBytes(StandardCharsets.UTF_8));
return new NodeId(digest);
} catch (NoSuchAlgorithmException e) {
throw new RepositoryException(e);
} catch (UnsupportedEncodingException e) {
throw new RepositoryException(e);
}
}
......
......@@ -21,6 +21,7 @@ import java.io.DataInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
......@@ -368,7 +369,7 @@ public class BundleDumper {
int len = in.readInt();
byte[] bytes = new byte[len];
in.readFully(bytes);
buffer.append(" value: string: ").append(new String(bytes, "UTF-8")).append("\n");
buffer.append(" value: string: ").append(new String(bytes, StandardCharsets.UTF_8)).append("\n");
}
}
}
......@@ -463,7 +464,7 @@ public class BundleDumper {
namespaces[ns] = uri;
}
}
String local = new String(readBytes((b & 0x0f) + 1, 0x10), "UTF-8");
String local = new String(readBytes((b & 0x0f) + 1, 0x10), StandardCharsets.UTF_8);
return uri + ":" + local;
}
}
......@@ -603,7 +604,7 @@ public class BundleDumper {
private String readString() throws IOException {
if (version >= VERSION_3) {
return new String(readBytes(0, 0), "UTF-8");
return new String(readBytes(0, 0), StandardCharsets.UTF_8);
} else {
return in.readUTF();
}
......
......@@ -30,6 +30,7 @@ import org.apache.jackrabbit.spi.commons.name.NameConstants;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Collections;
import java.util.GregorianCalendar;
......@@ -410,7 +411,7 @@ class BundleReader {
int len = in.readInt();
byte[] bytes = new byte[len];
in.readFully(bytes);
String stringVal = new String(bytes, "UTF-8");
String stringVal = new String(bytes, StandardCharsets.UTF_8);
// https://issues.apache.org/jira/browse/JCR-3083
if (PropertyType.DATE == entry.getType()) {
......@@ -518,7 +519,7 @@ class BundleReader {
}
}
String local = new String(readBytes((b & 0x0f) + 1, 0x10), "UTF-8");
String local = new String(readBytes((b & 0x0f) + 1, 0x10), StandardCharsets.UTF_8);
return NameFactoryImpl.getInstance().create(uri, local);
}
......@@ -659,7 +660,7 @@ class BundleReader {
private String readString() throws IOException {
if (version >= BundleBinding.VERSION_3) {
return new String(readBytes(0, 0), "UTF-8");
return new String(readBytes(0, 0), StandardCharsets.UTF_8);
} else {
return in.readUTF();
}
......
......@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
......@@ -464,7 +465,7 @@ class BundleWriter {
if (local.length() == 0) {
throw new IOException("Attempt to write an empty local name: " + name);
}
byte[] bytes = local.getBytes("UTF-8");
byte[] bytes = local.getBytes(StandardCharsets.UTF_8);
int len = Math.min(bytes.length - 1, 0x0f);
out.writeByte(0x80 | ns << 4 | len);
......@@ -707,7 +708,7 @@ class BundleWriter {
* @throws IOException if an I/O error occurs
*/
private void writeString(String value) throws IOException {
writeBytes(value.getBytes("UTF-8"), 0);
writeBytes(value.getBytes(StandardCharsets.UTF_8), 0);
}
/**
......
......@@ -34,6 +34,8 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
......@@ -55,7 +57,7 @@ public final class Serializer {
/**
* encoding used for serializing String values
*/
private static final String ENCODING = "UTF-8";
private static final Charset ENCODING = StandardCharsets.UTF_8;
/**
* Serializes the specified <code>NodeState</code> object to the given
......
......@@ -53,6 +53,8 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
......@@ -80,7 +82,7 @@ public class XMLPersistenceManager extends AbstractPersistenceManager {
/**
* The default encoding used in serialization
*/
public static final String DEFAULT_ENCODING = "UTF-8";
public static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
/**
* The XML elements and attributes used in serialization
......@@ -544,19 +546,11 @@ public class XMLPersistenceManager extends AbstractPersistenceManager {
OutputStream os = nodeFile.getOutputStream();
Writer writer = null;
try {
String encoding = DEFAULT_ENCODING;
try {
writer = new BufferedWriter(new OutputStreamWriter(os, encoding));
} catch (UnsupportedEncodingException e) {
// should never get here!
OutputStreamWriter osw = new OutputStreamWriter(os);
encoding = osw.getEncoding();
writer = new BufferedWriter(osw);
}
writer = new BufferedWriter(new OutputStreamWriter(os, DEFAULT_ENCODING));
String parentId = (state.getParentId() == null) ? "" : state.getParentId().toString();
String encodedNodeType = Text.encodeIllegalXMLCharacters(state.getNodeTypeName().toString());
writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");
writer.write("<?xml version=\"1.0\" encoding=\"" + DEFAULT_ENCODING.name() + "\"?>\n");
writer.write("<" + NODE_ELEMENT + " "
+ UUID_ATTRIBUTE + "=\"" + id + "\" "
+ PARENTUUID_ATTRIBUTE + "=\"" + parentId + "\" "
......@@ -618,15 +612,7 @@ public class XMLPersistenceManager extends AbstractPersistenceManager {
// write property state to xml file
Writer writer = null;
try {
String encoding = DEFAULT_ENCODING;
try {
writer = new BufferedWriter(new OutputStreamWriter(os, encoding));
} catch (UnsupportedEncodingException e) {
// should never get here!
OutputStreamWriter osw = new OutputStreamWriter(os);
encoding = osw.getEncoding();
writer = new BufferedWriter(osw);
}
writer = new BufferedWriter(new OutputStreamWriter(os, DEFAULT_ENCODING));
String typeName;
int type = state.getType();
......@@ -637,7 +623,7 @@ public class XMLPersistenceManager extends AbstractPersistenceManager {
throw new ItemStateException("unexpected property-type ordinal: " + type, iae);
}
writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");
writer.write("<?xml version=\"1.0\" encoding=\"" + DEFAULT_ENCODING.name() + "\"?>\n");
writer.write("<" + PROPERTY_ELEMENT + " "
+ NAME_ATTRIBUTE + "=\"" + Text.encodeIllegalXMLCharacters(state.getName().toString()) + "\" "
+ PARENTUUID_ATTRIBUTE + "=\"" + state.getParentId() + "\" "
......@@ -815,16 +801,9 @@ public class XMLPersistenceManager extends AbstractPersistenceManager {
OutputStream os = refsFile.getOutputStream();
BufferedWriter writer = null;
try {
String encoding = DEFAULT_ENCODING;
try {
writer = new BufferedWriter(new OutputStreamWriter(os, encoding));
} catch (UnsupportedEncodingException e) {
// should never get here!
OutputStreamWriter osw = new OutputStreamWriter(os);
encoding = osw.getEncoding();
writer = new BufferedWriter(osw);
}
writer.write("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");
writer = new BufferedWriter(new OutputStreamWriter(os, DEFAULT_ENCODING));
writer.write("<?xml version=\"1.0\" encoding=\"" + DEFAULT_ENCODING.name() + "\"?>\n");
writer.write("<" + NODEREFERENCES_ELEMENT + " "
+ TARGETID_ATTRIBUTE + "=\"" + refs.getTargetId() + "\">\n");
// write references (i.e. the id's of the REFERENCE properties)
......
......@@ -28,6 +28,7 @@ import java.util.Properties;
import javax.jcr.NamespaceException;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
import org.apache.jackrabbit.core.HierarchyManager;
......@@ -46,6 +47,8 @@ import org.apache.jackrabbit.core.value.InternalValue;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.spi.Path;
import org.apache.jackrabbit.spi.PathFactory;
import org.apache.jackrabbit.spi.QNodeTypeDefinition;
import org.apache.jackrabbit.spi.QPropertyDefinition;
import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
......@@ -212,7 +215,7 @@ public class IndexingConfigurationImpl
* <code>false</code> otherwise.
*/
public boolean isIndexed(NodeState state, Name propertyName) {
IndexingRule rule = getApplicableIndexingRule(state);
IndexingRule rule = getApplicableIndexingRule(state, propertyName);
if (rule != null) {
return rule.isIndexed(propertyName);
}
......@@ -230,7 +233,7 @@ public class IndexingConfigurationImpl
* @return the boost value for the property.
*/
public float getPropertyBoost(NodeState state, Name propertyName) {
IndexingRule rule = getApplicableIndexingRule(state);
IndexingRule rule = getApplicableIndexingRule(state, propertyName);
if (rule != null) {
return rule.getBoost(propertyName);
}
......@@ -244,7 +247,7 @@ public class IndexingConfigurationImpl
* @return the boost for the node scope fulltext index field.
*/
public float getNodeBoost(NodeState state) {
IndexingRule rule = getApplicableIndexingRule(state);
IndexingRule rule = getApplicableIndexingRule(state, null);
if (rule != null) {
return rule.getNodeBoost();
}
......@@ -263,7 +266,7 @@ public class IndexingConfigurationImpl
*/
public boolean isIncludedInNodeScopeIndex(NodeState state,
Name propertyName) {
IndexingRule rule = getApplicableIndexingRule(state);
IndexingRule rule = getApplicableIndexingRule(state, propertyName);
if (rule != null) {
return rule.isIncludedInNodeScopeIndex(propertyName);
}
......@@ -282,7 +285,7 @@ public class IndexingConfigurationImpl
* included in an excerpt; <code>false</code> otherwise.
*/
public boolean useInExcerpt(NodeState state, Name propertyName) {
IndexingRule rule = getApplicableIndexingRule(state);
IndexingRule rule = getApplicableIndexingRule(state, propertyName);
if (rule != null) {
return rule.useInExcerpt(propertyName);
}
......@@ -353,7 +356,7 @@ public class IndexingConfigurationImpl
nt2rules.put(ntName, perNtConfig);
}
log.debug("Registering it for name '{}'", ntName);
perNtConfig.add(new IndexingRule(element, ntName));
perNtConfig.add(new IndexingRule(element, ntReg.getNodeTypeDef(ntName)));
}
}
}
......@@ -367,9 +370,10 @@ public class IndexingConfigurationImpl
* <code>state</code>.
*
* @param state a node state.
* @param propertyName the property name to check.
* @return the indexing rule or <code>null</code> if none applies.
*/
private IndexingRule getApplicableIndexingRule(NodeState state) {
private IndexingRule getApplicableIndexingRule(NodeState state, Name propertyName) {
List<IndexingRule> rules = null;
List<IndexingRule> r = configElements.get(state.getNodeTypeName());
if (r != null) {
......@@ -389,7 +393,7 @@ public class IndexingConfigurationImpl
if (rules != null) {
for (IndexingRule rule : rules) {
if (rule.appliesTo(state)) {
if (rule.appliesTo(state, propertyName)) {
return rule;
}
}
......@@ -654,9 +658,9 @@ public class IndexingConfigurationImpl
private class IndexingRule {
/**
* The node type of this fulltext indexing rule.
* The NodeTypeDefinition of this fulltext indexing rule.
*/
private final Name nodeTypeName;
private final QNodeTypeDefinition nodeTypeDefinition;
/**
* Map of {@link PropertyConfig}. Key=Name of property.
......@@ -683,10 +687,10 @@ public class IndexingConfigurationImpl
* different node type name.
*
* @param original the existing rule.
* @param nodeTypeName the node type name for the rule.
* @param qNodeTypeDefinition the node type for the rule.
*/
IndexingRule(IndexingRule original, Name nodeTypeName) {
this.nodeTypeName = nodeTypeName;
IndexingRule(IndexingRule original, QNodeTypeDefinition qNodeTypeDefinition) {
this.nodeTypeDefinition = qNodeTypeDefinition;
this.propConfigs = original.propConfigs;
this.namePatterns = original.namePatterns;
this.condition = original.condition;
......@@ -699,10 +703,11 @@ public class IndexingConfigurationImpl
* @throws MalformedPathException if the condition expression is malformed.
* @throws IllegalNameException if a name contains illegal characters.
* @throws NamespaceException if a name contains an unknown prefix.
* @throws NoSuchNodeTypeException if the nodeType could not be evaluated
*/
IndexingRule(Node config)
throws MalformedPathException, IllegalNameException, NamespaceException {
this.nodeTypeName = getNodeTypeName(config);
throws MalformedPathException, IllegalNameException, NamespaceException, NoSuchNodeTypeException {
this.nodeTypeDefinition = getNodeTypeDefinition(config);
this.condition = getCondition(config);
this.boost = getNodeBoost(config);
this.propConfigs = new HashMap<Name, PropertyConfig>();
......@@ -716,7 +721,7 @@ public class IndexingConfigurationImpl
* @return name of the node type.
*/
public Name getNodeTypeName() {
return nodeTypeName;
return nodeTypeDefinition.getName();
}
/**
......@@ -788,10 +793,19 @@ public class IndexingConfigurationImpl
* <code>state</code>.
*
* @param state the state to check.
* @param propertyName the property name to check.
* @return <code>true</code> the rule applies to the given node;
* <code>false</code> otherwise.
*/
public boolean appliesTo(NodeState state) {
public boolean appliesTo(NodeState state, Name propertyName) {
Name nodeTypeName = getNodeTypeName();
if (propertyName != null) {
for (QPropertyDefinition propertyDefinition : nodeTypeDefinition.getPropertyDefs()) {
if (propertyDefinition.getName().equals(propertyName)) {
return true;
}
}
}
if (!nodeTypeName.equals(state.getNodeTypeName())) {
return false;
}
......@@ -831,11 +845,12 @@ public class IndexingConfigurationImpl
* characters.
* @throws NamespaceException if the node type contains an unknown
* prefix.
* @throws NoSuchNodeTypeException if the node type could not be evaluated
*/
private Name getNodeTypeName(Node config)
throws IllegalNameException, NamespaceException {
private QNodeTypeDefinition getNodeTypeDefinition(Node config)
throws IllegalNameException, NamespaceException, NoSuchNodeTypeException {
String ntString = config.getAttributes().getNamedItem("nodeType").getNodeValue();
return resolver.getQName(ntString);
return ntReg.getNodeTypeDef(resolver.getQName(ntString));
}
/**
......
......@@ -25,6 +25,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.HashSet;
......@@ -45,7 +47,7 @@ class IndexingQueueStore {
/**
* Encoding of the indexing queue store.
*/
private static final String ENCODING = "UTF-8";
private static final Charset ENCODING = StandardCharsets.UTF_8;
/**
* Operation identifier for an added node.
......