You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2018/03/27 04:38:15 UTC
svn commit: r1827801 - in /jackrabbit/commons/filevault/trunk:
vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/
vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/
vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/ vault-c...
Author: tripod
Date: Tue Mar 27 04:38:14 2018
New Revision: 1827801
URL: http://svn.apache.org/viewvc?rev=1827801&view=rev
Log:
JCRVLT-271 Support a CLI command to format vault xml files
(closes #24)
Added:
jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdFormatCli.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/AttributeNameComparator.java
jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/DocViewFormatTest.java
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/DocViewFormat/
jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/DocViewFormat/malformed.xml
Modified:
jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java
jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VltExecutionContext.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSerializer.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/package-info.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/ItemNameComparator.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/OutputFormat.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/XMLSerializer.java
jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/package-info.java
jackrabbit/commons/filevault/trunk/vault-doc/src/site/markdown/usage.md
Added: jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdFormatCli.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdFormatCli.java?rev=1827801&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdFormatCli.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/CmdFormatCli.java Tue Mar 27 04:38:14 2018
@@ -0,0 +1,150 @@
+/*
+ * 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.vault.cli;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.commons.cli2.CommandLine;
+import org.apache.commons.cli2.Option;
+import org.apache.commons.cli2.builder.ArgumentBuilder;
+import org.apache.commons.cli2.builder.CommandBuilder;
+import org.apache.commons.cli2.builder.DefaultOptionBuilder;
+import org.apache.commons.cli2.builder.GroupBuilder;
+import org.apache.commons.cli2.option.Command;
+import org.apache.jackrabbit.vault.fs.io.DocViewFormat;
+import org.apache.jackrabbit.vault.util.console.CliCommand;
+
+public class CmdFormatCli extends AbstractVaultCommand {
+
+ private static final Pattern DEFAULT_PATTERN = Pattern.compile(".*\\.xml");
+
+ private Option optCheckOnly;
+ private Option optPatterns;
+ private Option argPaths;
+
+
+ @Override
+ protected void doExecute(VaultFsApp app, CommandLine cl) throws Exception {
+ boolean checkOnly = cl.hasOption(optCheckOnly);
+ boolean verbose = cl.hasOption(OPT_VERBOSE);
+ List<String> givenPatterns = (List<String>) cl.getValues(optPatterns);
+ List<Pattern> parsedPatterns = new ArrayList<>(givenPatterns.size());
+
+ for (String pattern : givenPatterns) {
+ parsedPatterns.add(Pattern.compile(pattern));
+ }
+ if (parsedPatterns.isEmpty()) {
+ parsedPatterns.add(DEFAULT_PATTERN);
+ }
+
+ List<String> localPaths = cl.getValues(argPaths);
+ List<File> localFiles = app.getPlatformFiles(localPaths, true);
+ if (localFiles.isEmpty()) {
+ localFiles.add(app.getPlatformFile(".", true));
+ }
+
+ List<String> formattedFiles = new LinkedList<>();
+ DocViewFormat format = new DocViewFormat();
+ for (File file: localFiles) {
+ if (file.isDirectory()) {
+ if (verbose) {
+ System.out.printf("traversing: %s%n", file);
+ for (Pattern p: parsedPatterns) {
+ System.out.printf("scanning for files matching: %s%n", p);
+ }
+ }
+ formattedFiles.addAll(format.format(file, parsedPatterns, checkOnly));
+ } else {
+ if (verbose) {
+ System.out.printf("processing: %s%n", file);
+ }
+ if (format.format(file, checkOnly)) {
+ formattedFiles.add(file.getPath());
+ }
+ }
+ }
+ if (formattedFiles.isEmpty()) {
+ System.out.println("All files already properly formatted.");
+ return;
+ }
+
+ final Path cwd = Paths.get(new File("").getAbsolutePath());
+ if (checkOnly) {
+ System.out.println("The following files are not properly formatted:\n");
+ for (String path: formattedFiles) {
+ System.out.println(cwd.relativize(Paths.get(path)));
+ }
+ } else {
+ System.out.println("reformatted files:\n");
+ for (String path: formattedFiles) {
+ System.out.println(cwd.relativize(Paths.get(path)));
+ }
+ }
+ }
+
+ @Override
+ protected Command createCommand() {
+ return new CommandBuilder()
+ .withName("format")
+ .withDescription(getShortDescription())
+ .withChildren(new GroupBuilder()
+ .withOption(CliCommand.OPT_VERBOSE)
+ .withOption(optCheckOnly = new DefaultOptionBuilder()
+ .withShortName("c")
+ .withLongName("check-only")
+ .withDescription("Only check the format.")
+ .create()
+ )
+ .withOption(optPatterns = new DefaultOptionBuilder()
+ .withShortName("p")
+ .withLongName("pattern")
+ .withDescription("pattern for recursive format. defaults to match all xml files.")
+ .withArgument(new ArgumentBuilder()
+ .withMinimum(0)
+ .create())
+ .create())
+ .withOption(argPaths = new ArgumentBuilder()
+ .withName("paths")
+ .withDescription("files or directories to format.")
+ .withMinimum(0)
+ .create()
+ )
+ .create())
+ .create();
+ }
+
+ @Override
+ public String getShortDescription() {
+ return "Formats vault docview files.";
+ }
+
+ @Override
+ public String getLongDescription() {
+ return "Formats the file specified by <path> according to the vault specific docview format." +
+ "If the <path> points at a directory, the files matching the patterns are processed recursively.\n\n" +
+ "Example:\n" +
+ " vlt format -c -p '\\\\.content\\\\.xml' content/jcr_root\n\n";
+ }
+
+}
Modified: jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VaultFsApp.java Tue Mar 27 04:38:14 2018
@@ -225,7 +225,7 @@ public class VaultFsApp extends Abstract
@Override
public String getCopyrightLine() {
- return "Copyright 2013 by Apache Software Foundation. See LICENSE.txt for more information.";
+ return "Copyright 2018 by Apache Software Foundation. See LICENSE.txt for more information.";
}
protected void mount(String creds, String wsp, String root, String config,
Modified: jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VltExecutionContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VltExecutionContext.java?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VltExecutionContext.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-cli/src/main/java/org/apache/jackrabbit/vault/cli/VltExecutionContext.java Tue Mar 27 04:38:14 2018
@@ -51,6 +51,7 @@ public class VltExecutionContext extends
installCommand(new CmdDiff());
installCommand(new CmdRcp());
installCommand(new CmdSync());
+ installCommand(new CmdFormatCli());
//installCommand(new CmdVaultDebug());
}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSerializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSerializer.java?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSerializer.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSerializer.java Tue Mar 27 04:38:14 2018
@@ -25,8 +25,8 @@ import javax.jcr.RepositoryException;
import org.apache.jackrabbit.vault.fs.api.Aggregate;
import org.apache.jackrabbit.vault.fs.api.SerializationType;
import org.apache.jackrabbit.vault.fs.impl.AggregateImpl;
+import org.apache.jackrabbit.vault.fs.io.DocViewFormat;
import org.apache.jackrabbit.vault.fs.io.Serializer;
-import org.apache.jackrabbit.vault.util.xml.serialize.OutputFormat;
import org.apache.jackrabbit.vault.util.xml.serialize.XMLSerializer;
/**
@@ -53,11 +53,7 @@ public class DocViewSerializer implement
*/
public void writeContent(OutputStream out) throws IOException, RepositoryException {
// build content handler and add filter in case of original xml files
- OutputFormat oFmt = new OutputFormat("xml", "UTF-8", true);
- oFmt.setIndent(4);
- oFmt.setLineWidth(0);
- oFmt.setBreakEachAttribute(true);
- XMLSerializer ser = new XMLSerializer(out, oFmt);
+ XMLSerializer ser = new XMLSerializer(out, new DocViewFormat().getXmlOutputFormat());
DocViewSAXFormatter fmt = new DocViewSAXFormatter(aggregate, ser);
aggregate.walk(fmt);
}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java?rev=1827801&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/DocViewFormat.java Tue Mar 27 04:38:14 2018
@@ -0,0 +1,183 @@
+/*
+ * 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.vault.fs.io;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.ref.WeakReference;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedInputStream;
+import java.util.zip.CheckedOutputStream;
+import java.util.zip.Checksum;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.vault.util.xml.serialize.AttributeNameComparator;
+import org.apache.jackrabbit.vault.util.xml.serialize.OutputFormat;
+import org.apache.jackrabbit.vault.util.xml.serialize.XMLSerializer;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * This class provides access to the commonly used doc view xml format and functionality that checks files for the format or reformats
+ * them accordingly.
+ */
+public class DocViewFormat {
+
+ private final OutputFormat format;
+ private WeakReference<ByteArrayOutputStream> formattingBuffer;
+
+ public DocViewFormat() {
+ format = new OutputFormat("xml", "UTF-8", true);
+ format.setIndent(4);
+ format.setLineWidth(0);
+ format.setBreakEachAttribute(true);
+ format.setSortAttributeNamesBy(AttributeNameComparator.INSTANCE);
+ }
+
+ /**
+ * Returns the {@link OutputFormat} used by {@link org.apache.jackrabbit.vault.fs.impl.io.DocViewSerializer} when writing doc view xml
+ * files.
+ *
+ * @return the output format
+ */
+ public OutputFormat getXmlOutputFormat() {
+ return format;
+ }
+
+ /**
+ * Formats a given file using the {@link OutputFormat} returned by {@link DocViewFormat#getXmlOutputFormat()}.
+ * The file is replaced on disk but only if wasn't already formatted correctly and if {@code dryRun} is {@code false}.
+ *
+ * @param file the file to format
+ * @return {@code true} if the formatted version differs from the original.
+ * @throws IOException if an I/O error occurs
+ */
+ public boolean format(File file, boolean dryRun) throws IOException {
+ CRC32 originalCrc32 = new CRC32();
+ CRC32 formattedCrc32 = new CRC32();
+ byte[] formatted = format(file, originalCrc32, formattedCrc32);
+
+ final boolean changed = originalCrc32.getValue() != formattedCrc32.getValue();
+ if (changed && !dryRun) {
+ try (OutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
+ IOUtils.copy(new ByteArrayInputStream(formatted), out);
+ }
+ }
+ return changed;
+ }
+
+ /**
+ * Formats given files using the {@link OutputFormat} returned by {@link DocViewFormat#getXmlOutputFormat()} by traversing the directory
+ * tree given as file. Only those files will be formatted, that have a filename matching at least one of the given filenamePatterns,
+ * and only if {@code dryRun} is {@code false}.
+ *
+ * @param directory the start directory
+ * @param filenamePatterns list of regexp patterns
+ * @return a list of relative paths of those files which are not formatted correctly according to {@link #format(File, boolean)}
+ * @throws IOException in case there is an exception during traversal or formatting. That means formatting will fail on the first error that appeared
+ */
+ public List<String> format(File directory, List<Pattern> filenamePatterns, final boolean dryRun) throws IOException {
+ final List<String> changed = new LinkedList<>();
+ Files.walkFileTree(directory.toPath(), new AbstractFormattingVisitor(filenamePatterns) {
+ @Override protected void process(File file) throws IOException {
+ if (format(file, dryRun)) {
+ changed.add(file.getPath());
+ };
+ }
+ });
+ return changed;
+ }
+
+ /**
+ * internally formats the given file and computes their checksum
+ * @param file the file
+ * @param original checksum of the original file
+ * @param formatted checksum of the formatted file
+ * @return the formatted bytes
+ * @throws IOException if an error occurs
+ */
+ private byte[] format(File file, Checksum original, Checksum formatted) throws IOException {
+ try (InputStream in = new CheckedInputStream(new BufferedInputStream(new FileInputStream(file)), original)) {
+ @SuppressWarnings("resource")
+ ByteArrayOutputStream buffer = formattingBuffer != null ? formattingBuffer.get() : null;
+ if (buffer == null) {
+ buffer = new ByteArrayOutputStream();
+ formattingBuffer = new WeakReference<>(buffer);
+ } else {
+ buffer.reset();
+ }
+
+ XMLSerializer serializer = new XMLSerializer(new CheckedOutputStream(buffer, formatted), format);
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ reader.setContentHandler(serializer);
+ reader.setDTDHandler(serializer);
+ reader.parse(new InputSource(in));
+
+ return buffer.toByteArray();
+ } catch (SAXException ex) {
+ throw new IOException(ex);
+ }
+ }
+
+ private abstract static class AbstractFormattingVisitor extends SimpleFileVisitor<Path> {
+
+ private final List<Pattern> patterns;
+
+ AbstractFormattingVisitor(List<Pattern> patterns) {
+ this.patterns = patterns;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ if (Files.isRegularFile(file) && isIncluded(file)) {
+ process(file.toFile());
+ }
+ return super.visitFile(file, attrs);
+ }
+
+ private boolean isIncluded(Path file) {
+ for (Pattern pattern : patterns) {
+ if (pattern.matcher(file.getFileName().toString()).matches()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected abstract void process(File file) throws IOException;
+ }
+}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/package-info.java?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/package-info.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/package-info.java Tue Mar 27 04:38:14 2018
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-@Version("2.7.0")
+@Version("2.8.0")
package org.apache.jackrabbit.vault.fs.io;
import org.osgi.annotation.versioning.Version;
\ No newline at end of file
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/ItemNameComparator.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/ItemNameComparator.java?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/ItemNameComparator.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/ItemNameComparator.java Tue Mar 27 04:38:14 2018
@@ -22,6 +22,8 @@ import java.util.Comparator;
import javax.jcr.Item;
import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.vault.util.xml.serialize.AttributeNameComparator;
+
/**
* {@code ItemNameComparator}...
*/
@@ -32,17 +34,9 @@ public class ItemNameComparator implemen
public int compare(Item o1, Item o2) {
try {
// sort namespaced first
- String n1 = o1.getName().toLowerCase();
- String n2 = o2.getName().toLowerCase();
- int i1 = n1.indexOf(':');
- int i2 = n2.indexOf(':');
- if (i1 >=0 && i2 < 0) {
- return -1;
- } else if (i1 < 0 && i2 >=0) {
- return 1;
- } else {
- return n1.compareTo(n2);
- }
+ String n1 = o1.getName();
+ String n2 = o2.getName();
+ return AttributeNameComparator.INSTANCE.compare(n1, n2);
} catch (RepositoryException e) {
throw new IllegalStateException(e);
}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/AttributeNameComparator.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/AttributeNameComparator.java?rev=1827801&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/AttributeNameComparator.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/AttributeNameComparator.java Tue Mar 27 04:38:14 2018
@@ -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.vault.util.xml.serialize;
+
+import java.util.Comparator;
+
+import org.apache.jackrabbit.vault.util.xml.xerces.util.XMLSymbols;
+
+public class AttributeNameComparator implements Comparator<String> {
+
+ public static final AttributeNameComparator INSTANCE = new AttributeNameComparator();
+
+ @Override
+ public int compare(String o1, String o2) {
+ String n1 = o1.toLowerCase();
+ String n2 = o2.toLowerCase();
+ // order xmlns(:<prefix>)? attributes always to the front
+ boolean isXmlNs1 = n1.startsWith(XMLSymbols.PREFIX_XMLNS);
+ boolean isXmlNs2 = n2.startsWith(XMLSymbols.PREFIX_XMLNS);
+ if (isXmlNs1 && !isXmlNs2) {
+ return -1;
+ } else if (!isXmlNs1 && isXmlNs2) {
+ return 1;
+ }
+ int i1 = n1.indexOf(':');
+ int i2 = n2.indexOf(':');
+ if (i1 >=0 && i2 < 0) {
+ return -1;
+ } else if (i1 < 0 && i2 >=0) {
+ return 1;
+ } else {
+ return n1.compareTo(n2);
+ }
+ }
+}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/OutputFormat.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/OutputFormat.java?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/OutputFormat.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/OutputFormat.java Tue Mar 27 04:38:14 2018
@@ -28,6 +28,7 @@ package org.apache.jackrabbit.vault.util
import java.io.UnsupportedEncodingException;
+import java.util.Comparator;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
@@ -235,6 +236,10 @@ public class OutputFormat {
* serialized. Defaults to false for backwards compatibility.
*/
private boolean _preserveEmptyAttributes = false;
+ /**
+ * If set the comparator is used to sort the attributes. If not set the order is preserved as it is.
+ */
+ private Comparator<String> _sortAttributeNamesBy = null;
/**
* Constructs a new output format with the default values.
@@ -796,6 +801,24 @@ public class OutputFormat {
}
/**
+ * Returns the {@link Comparator} used to apply an order to attribute names.
+ *
+ * @return
+ */
+ public Comparator<String> getSortAttributeNamesBy() {
+ return _sortAttributeNamesBy;
+ }
+
+ /**
+ * Sets the comparator to use for applying an order to attribute names. If set to null, the original order is preserved.
+ *
+ * @param sortAttributeNamesBy
+ */
+ public void setSortAttributeNamesBy(Comparator<String> sortAttributeNamesBy) {
+ this._sortAttributeNamesBy = sortAttributeNamesBy;
+ }
+
+ /**
* Returns the last printable character based on the selected
* encoding. Control characters and non-printable characters
* are always printed as character references.
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/XMLSerializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/XMLSerializer.java?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/XMLSerializer.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/XMLSerializer.java Tue Mar 27 04:38:14 2018
@@ -35,6 +35,13 @@ package org.apache.jackrabbit.vault.util
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
import org.apache.jackrabbit.vault.util.xml.xerces.dom.DOMMessageFormatter;
import org.apache.jackrabbit.vault.util.xml.xerces.util.NamespaceSupport;
@@ -51,6 +58,7 @@ import org.w3c.dom.Node;
import org.xml.sax.AttributeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributeListImpl;
import org.xml.sax.helpers.AttributesImpl;
/**
@@ -315,6 +323,7 @@ public class XMLSerializer extends BaseM
// separated with a space so the element can be broken on
// multiple lines.
if (attrs != null) {
+ attrs = sortAttributes(attrs);
// added by tripod@apache.org
boolean breakEachAttr = _format.getBreakEachAttribute()
&& attrs.getLength() + (_prefixes == null ? 0 : _prefixes.size()) != 1
@@ -486,6 +495,7 @@ public class XMLSerializer extends BaseM
// separated with a space so the element can be broken on
// multiple lines.
if (attrs != null) {
+ attrs = sortAttributes(attrs);
for (i = 0; i < attrs.getLength(); ++i) {
_printer.printSpace();
name = attrs.getName(i);
@@ -632,7 +642,6 @@ public class XMLSerializer extends BaseM
protected void serializeElement(Element elem)
throws IOException {
Attr attr;
- NamedNodeMap attrMap;
int i;
Node child;
ElementState state;
@@ -689,14 +698,11 @@ public class XMLSerializer extends BaseM
// This only happens in endElement().
fPreserveSpace = state.preserveSpace;
-
- int length = 0;
- attrMap = null;
// retrieve attributes
- if (elem.hasAttributes()) {
- attrMap = elem.getAttributes();
- length = attrMap.getLength();
- }
+ final Iterable<Node> attrMap = elem.hasAttributes()
+ ? sortAttributes(elem.getAttributes())
+ : Collections.<Node>emptyList();
+
if (!fNamespaces) { // no namespace fixup should be performed
@@ -708,8 +714,8 @@ public class XMLSerializer extends BaseM
// For each attribute print it's name and value as one part,
// separated with a space so the element can be broken on
// multiple lines.
- for (i = 0; i < length; ++i) {
- attr = (Attr) attrMap.item(i);
+ for (Node node: attrMap) {
+ attr = (Attr) node;
name = attr.getName();
value = attr.getValue();
if (value == null)
@@ -727,9 +733,8 @@ public class XMLSerializer extends BaseM
// before attempting to fix element's namespace
// ---------------------------------------
- for (i = 0; i < length; i++) {
-
- attr = (Attr) attrMap.item(i);
+ for (Node node: attrMap) {
+ attr = (Attr) node;
uri = attr.getNamespaceURI();
// check if attribute is a namespace decl
if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
@@ -885,9 +890,8 @@ public class XMLSerializer extends BaseM
// check if prefix/namespace is correct the attributes
// -----------------------------------------
- for (i = 0; i < length; i++) {
-
- attr = (Attr) attrMap.item(i);
+ for (Node node: attrMap) {
+ attr = (Attr) node;
value = attr.getValue();
name = attr.getNodeName();
@@ -1100,6 +1104,81 @@ public class XMLSerializer extends BaseM
_printer.printText('"');
}
+ private Iterable<Node> sortAttributes(final NamedNodeMap attributeList) {
+ final Comparator<String> cmp = _format.getSortAttributeNamesBy();
+
+ if (cmp == null) {
+ return new Iterable<Node>() {
+ @Override public Iterator<Node> iterator() {
+ return new NamedNodeMapIterator(attributeList);
+ }
+ };
+ }
+
+ List<Node> attrs = new ArrayList<>(attributeList.getLength());
+
+ for (int i = 0, c = attributeList.getLength(); i < c; i++) {
+ attrs.add(attributeList.item(i));
+ }
+
+
+ Collections.sort(attrs, new Comparator<Node>() {
+ @Override public int compare(Node attr1, Node attr2) {
+ return cmp.compare(getNameOf(attr1), getNameOf(attr2));
+ }
+
+ String getNameOf(Node attr) {
+ String uri = attr.getNamespaceURI();
+ return uri != null && uri.length() == 0 ? attr.getLocalName() : attr.getNodeName();
+ }
+ });
+
+ return attrs;
+ }
+
+ private Attributes sortAttributes(Attributes attributeList) {
+ Comparator<String> cmp = _format.getSortAttributeNamesBy();
+
+ if (cmp == null) {
+ return attributeList;
+ }
+
+ Map<String, Integer> attributes = new TreeMap<>(cmp);
+ for (int i = 0, c = attributeList.getLength(); i < c; i++) {
+ String qname = attributeList.getQName(i);
+ attributes.put(qname, i);
+ }
+
+ AttributesImpl sortedAttributes = new AttributesImpl();
+ for (Integer nextIndex: attributes.values()) {
+ sortedAttributes.addAttribute(attributeList.getURI(nextIndex), attributeList.getLocalName(nextIndex),
+ attributeList.getQName(nextIndex), attributeList.getType(nextIndex), attributeList.getValue(nextIndex));
+ }
+
+ return sortedAttributes;
+ }
+
+ private AttributeList sortAttributes(AttributeList attributeList) {
+ Comparator<String> cmp = _format.getSortAttributeNamesBy();
+
+ if (cmp == null) {
+ return attributeList;
+ }
+
+ Map<String, Integer> attributes = new TreeMap<>(cmp);
+ for (int i = 0, c = attributeList.getLength(); i < c; i++) {
+ String name = attributeList.getName(i);
+ attributes.put(name, i);
+ }
+
+ AttributeListImpl sortedAttributes = new AttributeListImpl();
+ for (Integer nextIndex: attributes.values()) {
+ sortedAttributes.addAttribute(attributeList.getName(nextIndex), attributeList.getType(nextIndex),
+ attributeList.getValue(nextIndex));
+ }
+
+ return sortedAttributes;
+ }
/**
* Prints attribute.
@@ -1444,6 +1523,29 @@ public class XMLSerializer extends BaseM
return true;
}
+ private static class NamedNodeMapIterator implements Iterator<Node> {
+
+ private final NamedNodeMap nodeMap;
+ private int index = 0;
+ private final int length;
+
+ NamedNodeMapIterator(NamedNodeMap nodeMap) {
+ this.nodeMap = nodeMap;
+ this.length = nodeMap.getLength();
+ }
+
+ @Override public boolean hasNext() {
+ return index < length;
+ }
+
+ @Override public Node next() {
+ return this.nodeMap.item(index++);
+ }
+
+ @Override public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
}
Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/package-info.java?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/package-info.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/xml/serialize/package-info.java Tue Mar 27 04:38:14 2018
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-@Version("2.4.0")
+@Version("2.5.0")
package org.apache.jackrabbit.vault.util.xml.serialize;
import org.osgi.annotation.versioning.Version;
\ No newline at end of file
Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/DocViewFormatTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/DocViewFormatTest.java?rev=1827801&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/DocViewFormatTest.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/fs/io/DocViewFormatTest.java Tue Mar 27 04:38:14 2018
@@ -0,0 +1,80 @@
+/*
+ * 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.vault.fs.io;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DocViewFormatTest {
+
+ private File dir;
+ private File docViewFile;
+
+ @Before
+ public void setup() throws IOException {
+ String tempDir = System.getProperty("java.io.tmpdir");
+ dir = new File(tempDir + File.separator + "DocViewFormatTest" + new Date().toString());
+ assert dir.mkdir();
+ docViewFile = new File(dir.getPath() + File.separator + "malformed.xml");
+ assert docViewFile.createNewFile();
+
+ try (InputStream in = this.getClass().getClassLoader()
+ .getResourceAsStream("org/apache/jackrabbit/vault/fs/io/DocViewFormat/malformed.xml")) {
+ try (OutputStream out = new FileOutputStream(docViewFile)) {
+ IOUtils.copy(in, out);
+ }
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (!docViewFile.delete()) {
+ docViewFile.deleteOnExit();
+ dir.deleteOnExit();
+ } else {
+ if (!dir.delete()) {
+ dir.deleteOnExit();
+ }
+ }
+ }
+
+ @Test
+ public void testFormatting() throws IOException {
+ List<Pattern> patterns = Collections.singletonList(Pattern.compile(".+\\.xml"));
+ DocViewFormat format = new DocViewFormat();
+ assertFalse("malformed.xml is expected to be malformed", format.format(dir, patterns, true).isEmpty());
+ format.format(dir, patterns, false);
+ assertTrue("malformed.xml is expected to be formatted", format.format(dir, patterns, true).isEmpty());
+ }
+}
Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/DocViewFormat/malformed.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/DocViewFormat/malformed.xml?rev=1827801&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/DocViewFormat/malformed.xml (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/fs/io/DocViewFormat/malformed.xml Tue Mar 27 04:38:14 2018
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0"
+ jcr:primaryType="nt:unstructured"
+ jcr:title="Test node">
+ <testChild jcr:primaryType="nt:unstructured"
+ foo="bar"/>
+</jcr:root>
Modified: jackrabbit/commons/filevault/trunk/vault-doc/src/site/markdown/usage.md
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-doc/src/site/markdown/usage.md?rev=1827801&r1=1827800&r2=1827801&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-doc/src/site/markdown/usage.md (original)
+++ jackrabbit/commons/filevault/trunk/vault-doc/src/site/markdown/usage.md Tue Mar 27 04:38:14 2018
@@ -27,7 +27,7 @@ The console tool is called `vlt` and has
$vlt --help
----------------------------------------------------------------------------------------------
- Jackrabbit FileVault [version 3.0.0] Copyright 2013 by Apache Software Foundation.
+ Jackrabbit FileVault [version 3.2.2] Copyright 2018 by Apache Software Foundation.
See LICENSE.txt for more information.
----------------------------------------------------------------------------------------------
Usage:
@@ -38,6 +38,8 @@ The console tool is called `vlt` and has
-Xjcrlog <arg> Extended JcrLog options (omit argument for help)
-Xdavex <arg> Extended JCR remoting options (omit argument for help)
--credentials <arg> The default credentials to use
+ --update-credentials if present the credentials-to-host list is updated in the
+ ~/.vault/auth.xml
--config <arg> The JcrFs config to use
-v (--verbose) verbose output
-q (--quiet) print as little as possible
@@ -62,6 +64,7 @@ The console tool is called `vlt` and has
diff (di) Display the differences between two paths.
rcp Remote copy of repository content.
sync Control vault sync service
+ format Formats vault docview files.
console Run an interactive console
----------------------------------------------------------------------------------------------