mirror of
https://github.com/java-diff-utils/java-diff-utils.git
synced 2026-03-13 10:11:17 +08:00
Compare commits
29 Commits
java-diff-
...
java-diff-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0fd3bd8e06 | ||
|
|
eeb819cad4 | ||
|
|
e73742c4fc | ||
|
|
0545519fc3 | ||
|
|
bc65f9703c | ||
|
|
ea9942da12 | ||
|
|
8fdd239961 | ||
|
|
37f9eafaa9 | ||
|
|
0fd38db8ae | ||
|
|
3663cb5d87 | ||
|
|
8ae1f6cbbf | ||
|
|
ab1e38c57b | ||
|
|
286e807232 | ||
|
|
c85296b63d | ||
|
|
4c457b39dc | ||
|
|
7dea4e2298 | ||
|
|
2b02951e89 | ||
|
|
894b8ba300 | ||
|
|
2294c5be7b | ||
|
|
7203d4890f | ||
|
|
e413d79ecd | ||
|
|
c765616957 | ||
|
|
24c3df1f39 | ||
|
|
9765052226 | ||
|
|
8bb4a9a8b1 | ||
|
|
89ce301123 | ||
|
|
3d5343c283 | ||
|
|
d384ab6178 | ||
|
|
f03df6cf38 |
8
.github/release.yml
vendored
Normal file
8
.github/release.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
changelog:
|
||||
categories:
|
||||
- title: Bugs solved
|
||||
labels:
|
||||
- "bug"
|
||||
- title: Changes and new Features
|
||||
labels:
|
||||
- "*"
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -9,6 +9,16 @@ This project uses a custom versioning scheme (and not [Semantic Versioning](http
|
||||
|
||||
### Changed
|
||||
|
||||
## [4.11]
|
||||
|
||||
### Changed
|
||||
|
||||
* bugfixing new UnifiedDiff reader
|
||||
* header for each file
|
||||
* skip empty lines
|
||||
* introduction of Meyers Diff Algorithm with Linear Space improvment (until matured this will not be the default diff algorithm)
|
||||
* introduction of DiffAlgorithmFactory to set the default diff algorithm DiffUtils use (`DiffUtils.withDefaultDiffAlgorithmFactory(MeyersDiffWithLinearSpace.factory());`)
|
||||
|
||||
## [4.10]
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -49,12 +49,13 @@ This is a test ~senctence~**for diffutils**.
|
||||
* producing human-readable differences
|
||||
* inline difference construction
|
||||
* Algorithms:
|
||||
* Myer
|
||||
* Meyers Standard Algorithm
|
||||
* Meyers with linear space improvement
|
||||
* HistogramDiff using JGit Library
|
||||
|
||||
### Algorithms
|
||||
|
||||
* Myer's diff
|
||||
* Meyer's diff
|
||||
* HistogramDiff
|
||||
|
||||
But it can easily replaced by any other which is better for handing your texts. I have plan to add implementation of some in future.
|
||||
@@ -88,7 +89,7 @@ Just add the code below to your maven dependencies:
|
||||
<dependency>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.11</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -96,5 +97,5 @@ or using gradle:
|
||||
|
||||
```groovy
|
||||
// https://mvnrepository.com/artifact/io.github.java-diff-utils/java-diff-utils
|
||||
implementation "io.github.java-diff-utils:java-diff-utils:4.5"
|
||||
implementation "io.github.java-diff-utils:java-diff-utils:4.11"
|
||||
```
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.12</version>
|
||||
</parent>
|
||||
<artifactId>java-diff-utils-jgit</artifactId>
|
||||
<name>java-diff-utils-jgit</name>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.12</version>
|
||||
</parent>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package com.github.difflib;
|
||||
|
||||
import com.github.difflib.algorithm.DiffAlgorithmFactory;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmI;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.algorithm.myers.MyersDiff;
|
||||
import com.github.difflib.algorithm.myers.MeyersDiff;
|
||||
import com.github.difflib.patch.AbstractDelta;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
@@ -34,26 +35,35 @@ import java.util.function.BiPredicate;
|
||||
public final class DiffUtils {
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
* This factory generates the DEFAULT_DIFF algorithm for all these routines.
|
||||
*/
|
||||
static DiffAlgorithmFactory DEFAULT_DIFF = MeyersDiff.factory();
|
||||
|
||||
public static void withDefaultDiffAlgorithmFactory(DiffAlgorithmFactory factory) {
|
||||
DEFAULT_DIFF = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements
|
||||
* with default diff algorithm
|
||||
*
|
||||
* @param <T> types to be diffed
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @param progress progress listener
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
* @return The patch describing the difference between the original and
|
||||
* revised sequences. Never {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmListener progress) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), progress);
|
||||
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), progress);
|
||||
}
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), null);
|
||||
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), null);
|
||||
}
|
||||
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, boolean includeEqualParts) {
|
||||
return DiffUtils.diff(original, revised, new MyersDiff<>(), null, includeEqualParts);
|
||||
return DiffUtils.diff(original, revised, DEFAULT_DIFF.create(), null, includeEqualParts);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,45 +77,46 @@ public final class DiffUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
* Computes the difference between the original and revised list of elements
|
||||
* with default diff algorithm
|
||||
*
|
||||
* @param source The original text. Must not be {@code null}.
|
||||
* @param target The revised text. Must not be {@code null}.
|
||||
*
|
||||
* @param equalizer the equalizer object to replace the default compare algorithm
|
||||
* (Object.equals). If {@code null} the default equalizer of the default algorithm is used..
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
* @param equalizer the equalizer object to replace the default compare
|
||||
* algorithm (Object.equals). If {@code null} the default equalizer of the
|
||||
* default algorithm is used..
|
||||
* @return The patch describing the difference between the original and
|
||||
* revised sequences. Never {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> source, List<T> target,
|
||||
BiPredicate<T, T> equalizer) {
|
||||
if (equalizer != null) {
|
||||
return DiffUtils.diff(source, target,
|
||||
new MyersDiff<>(equalizer));
|
||||
DEFAULT_DIFF.create(equalizer));
|
||||
}
|
||||
return DiffUtils.diff(source, target, new MyersDiff<>());
|
||||
return DiffUtils.diff(source, target, new MeyersDiff<>());
|
||||
}
|
||||
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised,
|
||||
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress) {
|
||||
return diff(original, revised, algorithm, progress, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
* Computes the difference between the original and revised list of elements
|
||||
* with default diff algorithm
|
||||
*
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @param algorithm The diff algorithm. Must not be {@code null}.
|
||||
* @param progress The diff algorithm listener.
|
||||
* @param includeEqualParts Include equal data parts into the patch.
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
* @return The patch describing the difference between the original and
|
||||
* revised sequences. Never {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised,
|
||||
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress,
|
||||
DiffAlgorithmI<T> algorithm, DiffAlgorithmListener progress,
|
||||
boolean includeEqualParts) {
|
||||
Objects.requireNonNull(original, "original must not be null");
|
||||
Objects.requireNonNull(revised, "revised must not be null");
|
||||
@@ -115,23 +126,23 @@ public final class DiffUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the original and revised list of elements with default diff
|
||||
* algorithm
|
||||
* Computes the difference between the original and revised list of elements
|
||||
* with default diff algorithm
|
||||
*
|
||||
* @param original The original text. Must not be {@code null}.
|
||||
* @param revised The revised text. Must not be {@code null}.
|
||||
* @param algorithm The diff algorithm. Must not be {@code null}.
|
||||
* @return The patch describing the difference between the original and revised sequences. Never
|
||||
* {@code null}.
|
||||
* @return The patch describing the difference between the original and
|
||||
* revised sequences. Never {@code null}.
|
||||
*/
|
||||
public static <T> Patch<T> diff(List<T> original, List<T> revised, DiffAlgorithmI<T> algorithm) {
|
||||
return diff(original, revised, algorithm, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the difference between the given texts inline. This one uses the "trick" to make out
|
||||
* of texts lists of characters, like DiffRowGenerator does and merges those changes at the end
|
||||
* together again.
|
||||
* Computes the difference between the given texts inline. This one uses the
|
||||
* "trick" to make out of texts lists of characters, like DiffRowGenerator
|
||||
* does and merges those changes at the end together again.
|
||||
*
|
||||
* @param original
|
||||
* @param revised
|
||||
|
||||
@@ -129,7 +129,7 @@ public final class UnifiedDiffUtils {
|
||||
|
||||
/**
|
||||
* generateUnifiedDiff takes a Patch and some other arguments, returning the Unified Diff format
|
||||
* text representing the Patch.
|
||||
* text representing the Patch. Author: Bill James (tankerbay@gmail.com).
|
||||
*
|
||||
* @param originalFileName - Filename of the original (unrevised file)
|
||||
* @param revisedFileName - Filename of the revised file
|
||||
@@ -137,7 +137,6 @@ public final class UnifiedDiffUtils {
|
||||
* @param patch - Patch created by the diff() function
|
||||
* @param contextSize - number of lines of context output around each difference in the file.
|
||||
* @return List of strings representing the Unified Diff representation of the Patch argument.
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
public static List<String> generateUnifiedDiff(String originalFileName,
|
||||
String revisedFileName, List<String> originalLines, Patch<String> patch,
|
||||
@@ -200,13 +199,12 @@ public final class UnifiedDiffUtils {
|
||||
|
||||
/**
|
||||
* processDeltas takes a list of Deltas and outputs them together in a single block of
|
||||
* Unified-Diff-format text.
|
||||
* Unified-Diff-format text. Author: Bill James (tankerbay@gmail.com).
|
||||
*
|
||||
* @param origLines - the lines of the original file
|
||||
* @param deltas - the Deltas to be output as a single block
|
||||
* @param contextSize - the number of lines of context to place around block
|
||||
* @return
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
private static List<String> processDeltas(List<String> origLines,
|
||||
List<AbstractDelta<String>> deltas, int contextSize, boolean newFile) {
|
||||
@@ -297,11 +295,10 @@ public final class UnifiedDiffUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter. Author: Bill James (tankerbay@gmail.com).
|
||||
*
|
||||
* @param delta - the Delta to output
|
||||
* @return list of String lines of code.
|
||||
* @author Bill James (tankerbay@gmail.com)
|
||||
*/
|
||||
private static List<String> getDeltaText(AbstractDelta<String> delta) {
|
||||
List<String> buffer = new ArrayList<>();
|
||||
|
||||
@@ -36,4 +36,12 @@ public class Change {
|
||||
this.startRevised = startRevised;
|
||||
this.endRevised = endRevised;
|
||||
}
|
||||
|
||||
public Change withEndOriginal(int endOriginal) {
|
||||
return new Change(deltaType, startOriginal, endOriginal, startRevised, endRevised);
|
||||
}
|
||||
|
||||
public Change withEndRevised(int endRevised) {
|
||||
return new Change(deltaType, startOriginal, endOriginal, startRevised, endRevised);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2021 java-diff-utils.
|
||||
*
|
||||
* Licensed 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 com.github.difflib.algorithm;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* Tool to create new instances of a diff algorithm. This one is only needed at the moment to
|
||||
* set DiffUtils default diff algorithm.
|
||||
* @author tw
|
||||
*/
|
||||
public interface DiffAlgorithmFactory {
|
||||
<T> DiffAlgorithmI<T> create();
|
||||
|
||||
<T> DiffAlgorithmI<T> create(BiPredicate<T, T> equalizer);
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.algorithm.Change;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmFactory;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmI;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.DeltaType;
|
||||
@@ -26,18 +27,17 @@ import java.util.Objects;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* A clean-room implementation of Eugene Myers greedy differencing algorithm.
|
||||
* A clean-room implementation of Eugene Meyers greedy differencing algorithm.
|
||||
*/
|
||||
public final class MyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
public final class MeyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
|
||||
private final BiPredicate<T, T> DEFAULT_EQUALIZER = Object::equals;
|
||||
private final BiPredicate<T, T> equalizer;
|
||||
|
||||
public MyersDiff() {
|
||||
equalizer = DEFAULT_EQUALIZER;
|
||||
public MeyersDiff() {
|
||||
equalizer = Object::equals;
|
||||
}
|
||||
|
||||
public MyersDiff(final BiPredicate<T, T> equalizer) {
|
||||
public MeyersDiff(final BiPredicate<T, T> equalizer) {
|
||||
Objects.requireNonNull(equalizer, "equalizer must not be null");
|
||||
this.equalizer = equalizer;
|
||||
}
|
||||
@@ -64,8 +64,9 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the minimum diffpath that expresses de differences between the original and revised
|
||||
* sequences, according to Gene Myers differencing algorithm.
|
||||
* Computes the minimum diffpath that expresses de differences between the
|
||||
* original and revised sequences, according to Gene Myers differencing
|
||||
* algorithm.
|
||||
*
|
||||
* @param orig The original sequence.
|
||||
* @param rev The revised sequence.
|
||||
@@ -139,8 +140,8 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
* @param orig The original sequence.
|
||||
* @param rev The revised sequence.
|
||||
* @return A {@link Patch} script corresponding to the path.
|
||||
* @throws DifferentiationFailedException if a {@link Patch} could not be built from the given
|
||||
* path.
|
||||
* @throws DifferentiationFailedException if a {@link Patch} could not be
|
||||
* built from the given path.
|
||||
*/
|
||||
private List<Change> buildRevision(PathNode actualPath, List<T> orig, List<T> rev) {
|
||||
Objects.requireNonNull(actualPath, "path is null");
|
||||
@@ -177,4 +178,23 @@ public final class MyersDiff<T> implements DiffAlgorithmI<T> {
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to create instances of this specific diff algorithm.
|
||||
*/
|
||||
public static DiffAlgorithmFactory factory() {
|
||||
return new DiffAlgorithmFactory() {
|
||||
@Override
|
||||
public <T> DiffAlgorithmI<T>
|
||||
create() {
|
||||
return new MeyersDiff<T>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DiffAlgorithmI<T>
|
||||
create(BiPredicate < T, T > equalizer) {
|
||||
return new MeyersDiff<T>(equalizer);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2021 java-diff-utils.
|
||||
*
|
||||
* Licensed 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 com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.algorithm.Change;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmFactory;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmI;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.DeltaType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class MeyersDiffWithLinearSpace<T> implements DiffAlgorithmI<T> {
|
||||
|
||||
private final BiPredicate<T, T> equalizer;
|
||||
|
||||
public MeyersDiffWithLinearSpace() {
|
||||
equalizer = Object::equals;
|
||||
}
|
||||
|
||||
public MeyersDiffWithLinearSpace(final BiPredicate<T, T> equalizer) {
|
||||
Objects.requireNonNull(equalizer, "equalizer must not be null");
|
||||
this.equalizer = equalizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Change> computeDiff(List<T> source, List<T> target, DiffAlgorithmListener progress) {
|
||||
Objects.requireNonNull(source, "source list must not be null");
|
||||
Objects.requireNonNull(target, "target list must not be null");
|
||||
|
||||
if (progress != null) {
|
||||
progress.diffStart();
|
||||
}
|
||||
|
||||
DiffData data = new DiffData(source, target);
|
||||
|
||||
int maxIdx = source.size() + target.size();
|
||||
|
||||
buildScript(data, 0, source.size(), 0, target.size(), idx -> {
|
||||
if (progress != null) {
|
||||
progress.diffStep(idx, maxIdx);
|
||||
}
|
||||
});
|
||||
|
||||
if (progress != null) {
|
||||
progress.diffEnd();
|
||||
}
|
||||
return data.script;
|
||||
}
|
||||
|
||||
private void buildScript(DiffData data, int start1, int end1, int start2, int end2, Consumer<Integer> progress) {
|
||||
if (progress != null) {
|
||||
progress.accept((end1 - start1) / 2 + (end2 - start2) / 2);
|
||||
}
|
||||
final Snake middle = getMiddleSnake(data, start1, end1, start2, end2);
|
||||
if (middle == null
|
||||
|| middle.start == end1 && middle.diag == end1 - end2
|
||||
|| middle.end == start1 && middle.diag == start1 - start2) {
|
||||
int i = start1;
|
||||
int j = start2;
|
||||
while (i < end1 || j < end2) {
|
||||
if (i < end1 && j < end2 && equalizer.test(data.source.get(i), data.target.get(j))) {
|
||||
//script.append(new KeepCommand<>(left.charAt(i)));
|
||||
++i;
|
||||
++j;
|
||||
} else {
|
||||
//TODO: compress these commands.
|
||||
if (end1 - start1 > end2 - start2) {
|
||||
//script.append(new DeleteCommand<>(left.charAt(i)));
|
||||
if (data.script.isEmpty()
|
||||
|| data.script.get(data.script.size() - 1).endOriginal != i
|
||||
|| data.script.get(data.script.size() - 1).deltaType != DeltaType.DELETE) {
|
||||
data.script.add(new Change(DeltaType.DELETE, i, i + 1, j, j));
|
||||
} else {
|
||||
data.script.set(data.script.size() - 1, data.script.get(data.script.size() - 1).withEndOriginal(i + 1));
|
||||
}
|
||||
++i;
|
||||
} else {
|
||||
if (data.script.isEmpty()
|
||||
|| data.script.get(data.script.size() - 1).endRevised != j
|
||||
|| data.script.get(data.script.size() - 1).deltaType != DeltaType.INSERT) {
|
||||
data.script.add(new Change(DeltaType.INSERT, i, i, j, j + 1));
|
||||
} else {
|
||||
data.script.set(data.script.size() - 1, data.script.get(data.script.size() - 1).withEndRevised(j + 1));
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buildScript(data, start1, middle.start, start2, middle.start - middle.diag, progress);
|
||||
buildScript(data, middle.end, end1, middle.end - middle.diag, end2, progress);
|
||||
}
|
||||
}
|
||||
|
||||
private Snake getMiddleSnake(DiffData data, int start1, int end1, int start2, int end2) {
|
||||
final int m = end1 - start1;
|
||||
final int n = end2 - start2;
|
||||
if (m == 0 || n == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int delta = m - n;
|
||||
final int sum = n + m;
|
||||
final int offset = (sum % 2 == 0 ? sum : sum + 1) / 2;
|
||||
data.vDown[1 + offset] = start1;
|
||||
data.vUp[1 + offset] = end1 + 1;
|
||||
|
||||
for (int d = 0; d <= offset; ++d) {
|
||||
// Down
|
||||
for (int k = -d; k <= d; k += 2) {
|
||||
// First step
|
||||
|
||||
final int i = k + offset;
|
||||
if (k == -d || k != d && data.vDown[i - 1] < data.vDown[i + 1]) {
|
||||
data.vDown[i] = data.vDown[i + 1];
|
||||
} else {
|
||||
data.vDown[i] = data.vDown[i - 1] + 1;
|
||||
}
|
||||
|
||||
int x = data.vDown[i];
|
||||
int y = x - start1 + start2 - k;
|
||||
|
||||
while (x < end1 && y < end2 && equalizer.test(data.source.get(x), data.target.get(y))) {
|
||||
data.vDown[i] = ++x;
|
||||
++y;
|
||||
}
|
||||
// Second step
|
||||
if (delta % 2 != 0 && delta - d <= k && k <= delta + d) {
|
||||
if (data.vUp[i - delta] <= data.vDown[i]) {
|
||||
return buildSnake(data, data.vUp[i - delta], k + start1 - start2, end1, end2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Up
|
||||
for (int k = delta - d; k <= delta + d; k += 2) {
|
||||
// First step
|
||||
final int i = k + offset - delta;
|
||||
if (k == delta - d
|
||||
|| k != delta + d && data.vUp[i + 1] <= data.vUp[i - 1]) {
|
||||
data.vUp[i] = data.vUp[i + 1] - 1;
|
||||
} else {
|
||||
data.vUp[i] = data.vUp[i - 1];
|
||||
}
|
||||
|
||||
int x = data.vUp[i] - 1;
|
||||
int y = x - start1 + start2 - k;
|
||||
while (x >= start1 && y >= start2 && equalizer.test(data.source.get(x), data.target.get(y))) {
|
||||
data.vUp[i] = x--;
|
||||
y--;
|
||||
}
|
||||
// Second step
|
||||
if (delta % 2 == 0 && -d <= k && k <= d) {
|
||||
if (data.vUp[i] <= data.vDown[i + delta]) {
|
||||
return buildSnake(data, data.vUp[i], k + start1 - start2, end1, end2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// According to Myers, this cannot happen
|
||||
throw new IllegalStateException("could not find a diff path");
|
||||
}
|
||||
|
||||
private Snake buildSnake(DiffData data, final int start, final int diag, final int end1, final int end2) {
|
||||
int end = start;
|
||||
while (end - diag < end2 && end < end1 && equalizer.test(data.source.get(end), data.target.get(end - diag))) {
|
||||
++end;
|
||||
}
|
||||
return new Snake(start, end, diag);
|
||||
}
|
||||
|
||||
private class DiffData {
|
||||
|
||||
final int size;
|
||||
final int[] vDown;
|
||||
final int[] vUp;
|
||||
final List<Change> script;
|
||||
final List<T> source;
|
||||
final List<T> target;
|
||||
|
||||
public DiffData(List<T> source, List<T> target) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
size = source.size() + target.size() + 2;
|
||||
vDown = new int[size];
|
||||
vUp = new int[size];
|
||||
script = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private class Snake {
|
||||
|
||||
final int start;
|
||||
final int end;
|
||||
final int diag;
|
||||
|
||||
public Snake(final int start, final int end, final int diag) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.diag = diag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to create instances of this specific diff algorithm.
|
||||
*/
|
||||
public static DiffAlgorithmFactory factory() {
|
||||
return new DiffAlgorithmFactory() {
|
||||
@Override
|
||||
public <T> DiffAlgorithmI<T>
|
||||
create() {
|
||||
return new MeyersDiffWithLinearSpace<T>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DiffAlgorithmI<T>
|
||||
create(BiPredicate < T, T > equalizer) {
|
||||
return new MeyersDiffWithLinearSpace<T>(equalizer);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,19 @@ public abstract class AbstractDelta<T> implements Serializable {
|
||||
|
||||
protected abstract void restore(List<T> target);
|
||||
|
||||
/**
|
||||
* Apply patch fuzzy.
|
||||
*
|
||||
* @param target the list this patch will be applied to
|
||||
* @param fuzz the number of elements to ignore before/after the patched elements
|
||||
* @param position the position this patch will be applied to. ignores {@code source.getPosition()}
|
||||
* @see <a href="https://www.gnu.org/software/diffutils/manual/html_node/Inexact.html">Description of Fuzzy Patch</a> for more information.
|
||||
*/
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
protected void applyFuzzyToAt(List<T> target, int fuzz, int position) throws PatchFailedException {
|
||||
throw new UnsupportedOperationException(this.getClass().getSimpleName() + " does not supports applying patch fuzzy");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new delta of the actual instance with customized chunk data.
|
||||
*/
|
||||
|
||||
@@ -66,6 +66,19 @@ public final class ChangeDelta<T> extends AbstractDelta<T> {
|
||||
}
|
||||
}
|
||||
|
||||
protected void applyFuzzyToAt(List<T> target, int fuzz, int position) throws PatchFailedException {
|
||||
int size = getSource().size();
|
||||
for (int i = fuzz; i < size - fuzz; i++) {
|
||||
target.remove(position + fuzz);
|
||||
}
|
||||
|
||||
int i = fuzz;
|
||||
for (T line : getTarget().getLines().subList(fuzz, getTarget().size() - fuzz)) {
|
||||
target.add(position + i, line);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[ChangeDelta, position: " + getSource().getPosition() + ", lines: "
|
||||
|
||||
@@ -95,10 +95,28 @@ public final class Chunk<T> implements Serializable {
|
||||
* @throws com.github.difflib.patch.PatchFailedException
|
||||
*/
|
||||
public VerifyChunk verifyChunk(List<T> target) throws PatchFailedException {
|
||||
if (position > target.size() || last() > target.size()) {
|
||||
return verifyChunk(target, 0, getPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that this chunk's saved text matches the corresponding text in
|
||||
* the given sequence.
|
||||
*
|
||||
* @param target the sequence to verify against.
|
||||
* @param fuzz the count of ignored prefix/suffix
|
||||
* @param position the position of target
|
||||
* @throws com.github.difflib.patch.PatchFailedException
|
||||
*/
|
||||
public VerifyChunk verifyChunk(List<T> target, int fuzz, int position) throws PatchFailedException {
|
||||
//noinspection UnnecessaryLocalVariable
|
||||
int startIndex = fuzz;
|
||||
int lastIndex = size() - fuzz;
|
||||
int last = position + size() - 1;
|
||||
|
||||
if (position + fuzz > target.size() || last - fuzz > target.size()) {
|
||||
return VerifyChunk.POSITION_OUT_OF_TARGET;
|
||||
}
|
||||
for (int i = 0; i < size(); i++) {
|
||||
for (int i = startIndex; i < lastIndex; i++) {
|
||||
if (!target.get(position + i).equals(lines.get(i))) {
|
||||
return VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,14 @@ public class EqualDelta<T> extends AbstractDelta<T> {
|
||||
protected void restore(List<T> target) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void applyFuzzyToAt(List<T> target, int fuzz, int delta) {
|
||||
// equals so no operations
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[EqualDelta, position: " + getSource().getPosition() + ", lines: "
|
||||
|
||||
@@ -66,6 +66,117 @@ public final class Patch<T> implements Serializable {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class PatchApplyingContext<T> {
|
||||
public final List<T> result;
|
||||
public final int maxFuzz;
|
||||
|
||||
// the position last patch applied to.
|
||||
public int lastPatchEnd = -1;
|
||||
|
||||
///// passing values from find to apply
|
||||
public int currentFuzz = 0;
|
||||
|
||||
public int defaultPosition;
|
||||
public boolean beforeOutRange = false;
|
||||
public boolean afterOutRange = false;
|
||||
|
||||
private PatchApplyingContext(List<T> result, int maxFuzz) {
|
||||
this.result = result;
|
||||
this.maxFuzz = maxFuzz;
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> applyFuzzy(List<T> target, int maxFuzz) throws PatchFailedException {
|
||||
PatchApplyingContext<T> ctx = new PatchApplyingContext<>(new ArrayList<>(target), maxFuzz);
|
||||
|
||||
// the difference between patch's position and actually applied position
|
||||
int lastPatchDelta = 0;
|
||||
|
||||
for (AbstractDelta<T> delta : getDeltas()) {
|
||||
ctx.defaultPosition = delta.getSource().getPosition() + lastPatchDelta;
|
||||
int patchPosition = findPositionFuzzy(ctx, delta);
|
||||
if (0 <= patchPosition) {
|
||||
delta.applyFuzzyToAt(ctx.result, ctx.currentFuzz, patchPosition);
|
||||
lastPatchDelta = patchPosition - delta.getSource().getPosition();
|
||||
ctx.lastPatchEnd = delta.getSource().last() + lastPatchDelta;
|
||||
} else {
|
||||
conflictOutput.processConflict(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET, delta, ctx.result);
|
||||
}
|
||||
}
|
||||
|
||||
return ctx.result;
|
||||
}
|
||||
|
||||
// negative for not found
|
||||
private int findPositionFuzzy(PatchApplyingContext<T> ctx, AbstractDelta<T> delta) throws PatchFailedException {
|
||||
for (int fuzz = 0; fuzz <= ctx.maxFuzz; fuzz++) {
|
||||
ctx.currentFuzz = fuzz;
|
||||
int foundPosition = findPositionWithFuzz(ctx, delta, fuzz);
|
||||
if (foundPosition >= 0) {
|
||||
return foundPosition;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// negative for not found
|
||||
private int findPositionWithFuzz(PatchApplyingContext<T> ctx, AbstractDelta<T> delta, int fuzz) throws PatchFailedException {
|
||||
if (delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition) == VerifyChunk.OK) {
|
||||
return ctx.defaultPosition;
|
||||
}
|
||||
|
||||
ctx.beforeOutRange = false;
|
||||
ctx.afterOutRange = false;
|
||||
|
||||
// moreDelta >= 0: just for overflow guard, not a normal condition
|
||||
//noinspection OverflowingLoopIndex
|
||||
for (int moreDelta = 0; moreDelta >= 0; moreDelta++) {
|
||||
int pos = findPositionWithFuzzAndMoreDelta(ctx, delta, fuzz, moreDelta);
|
||||
if (pos >= 0) {
|
||||
return pos;
|
||||
}
|
||||
if (ctx.beforeOutRange && ctx.afterOutRange) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// negative for not found
|
||||
private int findPositionWithFuzzAndMoreDelta(PatchApplyingContext<T> ctx, AbstractDelta<T> delta, int fuzz, int moreDelta) throws PatchFailedException {
|
||||
// range check: can't apply before end of last patch
|
||||
if (!ctx.beforeOutRange) {
|
||||
int beginAt = ctx.defaultPosition - moreDelta + fuzz;
|
||||
// We can't apply patch before end of last patch.
|
||||
if (beginAt <= ctx.lastPatchEnd) {
|
||||
ctx.beforeOutRange = true;
|
||||
}
|
||||
}
|
||||
// range check: can't apply after end of result
|
||||
if (!ctx.afterOutRange) {
|
||||
int beginAt = ctx.defaultPosition + moreDelta + delta.getSource().size() - fuzz;
|
||||
// We can't apply patch before end of last patch.
|
||||
if (ctx.result.size() < beginAt) {
|
||||
ctx.afterOutRange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctx.beforeOutRange) {
|
||||
VerifyChunk before = delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition - moreDelta);
|
||||
if (before == VerifyChunk.OK) {
|
||||
return ctx.defaultPosition - moreDelta;
|
||||
}
|
||||
}
|
||||
if (!ctx.afterOutRange) {
|
||||
VerifyChunk after = delta.getSource().verifyChunk(ctx.result, fuzz, ctx.defaultPosition + moreDelta);
|
||||
if (after == VerifyChunk.OK) {
|
||||
return ctx.defaultPosition + moreDelta;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard Patch behaviour to throw an exception for pathching conflicts.
|
||||
*/
|
||||
|
||||
@@ -173,6 +173,7 @@ public final class DiffRowGenerator {
|
||||
|
||||
private final boolean showInlineDiffs;
|
||||
private final boolean replaceOriginalLinefeedInChangesWithSpaces;
|
||||
private final boolean decompressDeltas;
|
||||
|
||||
private DiffRowGenerator(Builder builder) {
|
||||
showInlineDiffs = builder.showInlineDiffs;
|
||||
@@ -182,6 +183,7 @@ public final class DiffRowGenerator {
|
||||
columnWidth = builder.columnWidth;
|
||||
mergeOriginalRevised = builder.mergeOriginalRevised;
|
||||
inlineDiffSplitter = builder.inlineDiffSplitter;
|
||||
decompressDeltas = builder.decompressDeltas;
|
||||
|
||||
if (builder.equalizer != null) {
|
||||
equalizer = builder.equalizer;
|
||||
@@ -225,8 +227,14 @@ public final class DiffRowGenerator {
|
||||
int endPos = 0;
|
||||
final List<AbstractDelta<String>> deltaList = patch.getDeltas();
|
||||
|
||||
for (AbstractDelta<String> originalDelta : deltaList) {
|
||||
for (AbstractDelta<String> delta : decompressDeltas(originalDelta)) {
|
||||
if (decompressDeltas) {
|
||||
for (AbstractDelta<String> originalDelta : deltaList) {
|
||||
for (AbstractDelta<String> delta : decompressDeltas(originalDelta)) {
|
||||
endPos = transformDeltaIntoDiffRow(original, endPos, diffRows, delta);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (AbstractDelta<String> delta : deltaList) {
|
||||
endPos = transformDeltaIntoDiffRow(original, endPos, diffRows, delta);
|
||||
}
|
||||
}
|
||||
@@ -442,6 +450,7 @@ public final class DiffRowGenerator {
|
||||
|
||||
private boolean showInlineDiffs = false;
|
||||
private boolean ignoreWhiteSpaces = false;
|
||||
private boolean decompressDeltas = true;
|
||||
|
||||
private BiFunction<Tag, Boolean, String> oldTag
|
||||
= (tag, f) -> f ? "<span class=\"editOldInline\">" : "</span>";
|
||||
@@ -554,8 +563,9 @@ public final class DiffRowGenerator {
|
||||
* Set the column width of generated lines of original and revised
|
||||
* texts.
|
||||
*
|
||||
* @param width the width to set. Making it < 0 doesn't make any sense.
|
||||
* Default 80. @return builder with config of column width
|
||||
* @param width the width to set. Making it < 0 doesn't make any
|
||||
* sense. Default 80.
|
||||
* @return builder with config of column width
|
||||
*/
|
||||
public Builder columnWidth(int width) {
|
||||
if (width >= 0) {
|
||||
@@ -586,6 +596,19 @@ public final class DiffRowGenerator {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deltas could be in a state, that would produce some unreasonable
|
||||
* results within an inline diff. So the deltas are decompressed into
|
||||
* smaller parts and rebuild. But this could result in more differences.
|
||||
*
|
||||
* @param decompressDeltas
|
||||
* @return
|
||||
*/
|
||||
public Builder decompressDeltas(boolean decompressDeltas) {
|
||||
this.decompressDeltas = decompressDeltas;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per default each character is separatly processed. This variant
|
||||
* introduces processing by word, which does not deliver in word
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class UnifiedDiff {
|
||||
return tail;
|
||||
}
|
||||
|
||||
public List<String> spplyPatchTo(Predicate<String> findFile, List<String> originalLines) throws PatchFailedException {
|
||||
public List<String> applyPatchTo(Predicate<String> findFile, List<String> originalLines) throws PatchFailedException {
|
||||
UnifiedDiffFile file = files.stream()
|
||||
.filter(diff -> findFile.test(diff.getFromFile()))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
@@ -72,26 +72,45 @@ public final class UnifiedDiffReader {
|
||||
// [/^---\s/, from_file], [/^\+\+\+\s/, to_file], [/^@@\s+\-(\d+),?(\d+)?\s+\+(\d+),?(\d+)?\s@@/, chunk],
|
||||
// [/^-/, del], [/^\+/, add], [/^\\ No newline at end of file$/, eof]];
|
||||
private UnifiedDiff parse() throws IOException, UnifiedDiffParserException {
|
||||
String headerTxt = "";
|
||||
LOG.log(Level.FINE, "header parsing");
|
||||
String line = null;
|
||||
while (READER.ready()) {
|
||||
line = READER.readLine();
|
||||
LOG.log(Level.FINE, "parsing line {0}", line);
|
||||
if (DIFF_COMMAND.validLine(line) || INDEX.validLine(line)
|
||||
|| FROM_FILE.validLine(line) || TO_FILE.validLine(line)
|
||||
|| NEW_FILE_MODE.validLine(line)) {
|
||||
break;
|
||||
} else {
|
||||
headerTxt += line + "\n";
|
||||
}
|
||||
}
|
||||
if (!"".equals(headerTxt)) {
|
||||
data.setHeader(headerTxt);
|
||||
}
|
||||
// String headerTxt = "";
|
||||
// LOG.log(Level.FINE, "header parsing");
|
||||
// String line = null;
|
||||
// while (READER.ready()) {
|
||||
// line = READER.readLine();
|
||||
// LOG.log(Level.FINE, "parsing line {0}", line);
|
||||
// if (DIFF_COMMAND.validLine(line) || INDEX.validLine(line)
|
||||
// || FROM_FILE.validLine(line) || TO_FILE.validLine(line)
|
||||
// || NEW_FILE_MODE.validLine(line)) {
|
||||
// break;
|
||||
// } else {
|
||||
// headerTxt += line + "\n";
|
||||
// }
|
||||
// }
|
||||
// if (!"".equals(headerTxt)) {
|
||||
// data.setHeader(headerTxt);
|
||||
// }
|
||||
|
||||
String line = READER.readLine();
|
||||
while (line != null) {
|
||||
if (!CHUNK.validLine(line)) {
|
||||
String headerTxt = "";
|
||||
LOG.log(Level.FINE, "header parsing");
|
||||
while (line != null) {
|
||||
LOG.log(Level.FINE, "parsing line {0}", line);
|
||||
if (validLine(line, DIFF_COMMAND, SIMILARITY_INDEX, INDEX,
|
||||
FROM_FILE, TO_FILE,
|
||||
RENAME_FROM, RENAME_TO,
|
||||
NEW_FILE_MODE, DELETED_FILE_MODE,
|
||||
CHUNK)) {
|
||||
break;
|
||||
} else {
|
||||
headerTxt += line + "\n";
|
||||
}
|
||||
line = READER.readLine();
|
||||
}
|
||||
if (!"".equals(headerTxt)) {
|
||||
data.setHeader(headerTxt);
|
||||
}
|
||||
if (line != null && !CHUNK.validLine(line)) {
|
||||
initFileIfNecessary();
|
||||
while (line != null && !CHUNK.validLine(line)) {
|
||||
if (!processLine(line, DIFF_COMMAND, SIMILARITY_INDEX, INDEX,
|
||||
@@ -106,6 +125,8 @@ public final class UnifiedDiffReader {
|
||||
if (line != null) {
|
||||
processLine(line, CHUNK);
|
||||
while ((line = READER.readLine()) != null) {
|
||||
line = checkForNoNewLineAtTheEndOfTheFile(line);
|
||||
|
||||
if (!processLine(line, LINE_NORMAL, LINE_ADD, LINE_DEL)) {
|
||||
throw new UnifiedDiffParserException("expected data line not found");
|
||||
}
|
||||
@@ -118,10 +139,7 @@ public final class UnifiedDiffReader {
|
||||
}
|
||||
line = READER.readLine();
|
||||
|
||||
if ("\\ No newline at end of file".equals(line)) {
|
||||
actualFile.setNoNewLineAtTheEndOfTheFile(true);
|
||||
line = READER.readLine();
|
||||
}
|
||||
line = checkForNoNewLineAtTheEndOfTheFile(line);
|
||||
}
|
||||
if (line == null || (line.startsWith("--") && !line.startsWith("---"))) {
|
||||
break;
|
||||
@@ -142,6 +160,14 @@ public final class UnifiedDiffReader {
|
||||
return data;
|
||||
}
|
||||
|
||||
private String checkForNoNewLineAtTheEndOfTheFile(String line) throws IOException {
|
||||
if ("\\ No newline at end of file".equals(line)) {
|
||||
actualFile.setNoNewLineAtTheEndOfTheFile(true);
|
||||
return READER.readLine();
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
static String[] parseFileNames(String line) {
|
||||
String[] split = line.split(" ");
|
||||
return new String[]{
|
||||
@@ -179,6 +205,19 @@ public final class UnifiedDiffReader {
|
||||
return false;
|
||||
//throw new UnifiedDiffParserException("parsing error at line " + line);
|
||||
}
|
||||
|
||||
private boolean validLine(String line, UnifiedDiffLine ... rules) {
|
||||
if (line == null) {
|
||||
return false;
|
||||
}
|
||||
for (UnifiedDiffLine rule : rules) {
|
||||
if (rule.validLine(line)) {
|
||||
LOG.fine(" >>> accepted rule " + rule.toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void initFileIfNecessary() {
|
||||
if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) {
|
||||
@@ -314,7 +353,7 @@ public final class UnifiedDiffReader {
|
||||
line = line.substring(0, matcher.start());
|
||||
}
|
||||
line = line.split("\t")[0];
|
||||
return line.substring(4).replaceFirst("^(a|b|old|new)(\\/)?", "")
|
||||
return line.substring(4).replaceFirst("^(a|b|old|new)/", "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
|
||||
@@ -189,10 +189,10 @@ public class UnifiedDiffWriter {
|
||||
}
|
||||
|
||||
/**
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter
|
||||
* getDeltaText returns the lines to be added to the Unified Diff text from the Delta parameter.
|
||||
*
|
||||
* @param delta - the Delta to output
|
||||
* @return list of String lines of code.
|
||||
* @param writer consumer for the list of String lines of code
|
||||
* @param delta the Delta to output
|
||||
*/
|
||||
private static void getDeltaText(Consumer<String> writer, AbstractDelta<String> delta) {
|
||||
for (String line : delta.getSource().getLines()) {
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2021 java-diff-utils.
|
||||
*
|
||||
* Licensed 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 com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmListener;
|
||||
import com.github.difflib.patch.Patch;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import java.util.stream.IntStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class MeyersDiffWithLinearSpaceTest {
|
||||
|
||||
@Test
|
||||
public void testDiffMyersExample1Forward() {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
final Patch<String> patch = Patch.generate(original, revised, new MeyersDiffWithLinearSpace<String>().computeDiff(original, revised, null));
|
||||
assertNotNull(patch);
|
||||
System.out.println(patch);
|
||||
assertEquals(5, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[InsertDelta, position: 0, lines: [C]], [DeleteDelta, position: 0, lines: [A]], [DeleteDelta, position: 2, lines: [C]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiffMyersExample1ForwardWithListener() {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
|
||||
List<String> logdata = new ArrayList<>();
|
||||
final Patch<String> patch = Patch.generate(original, revised,
|
||||
new MeyersDiffWithLinearSpace<String>().computeDiff(original, revised, new DiffAlgorithmListener() {
|
||||
@Override
|
||||
public void diffStart() {
|
||||
logdata.add("start");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffStep(int value, int max) {
|
||||
logdata.add(value + " - " + max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void diffEnd() {
|
||||
logdata.add("end");
|
||||
}
|
||||
}));
|
||||
assertNotNull(patch);
|
||||
System.out.println(patch);
|
||||
assertEquals(5, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[InsertDelta, position: 0, lines: [C]], [DeleteDelta, position: 0, lines: [A]], [DeleteDelta, position: 2, lines: [C]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
System.out.println(logdata);
|
||||
assertEquals(11, logdata.size());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPerformanceProblemsIssue124() {
|
||||
List<String> old = Arrays.asList("abcd");
|
||||
List<String> newl = IntStream.range(0, 90000)
|
||||
.boxed()
|
||||
.map(i -> i.toString())
|
||||
.collect(toList());
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
Patch<String> diff = DiffUtils.diff(old, newl, new MeyersDiffWithLinearSpace<String>());
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("Finished in " + (end - start) + "ms and resulted " + diff.getDeltas().size() + " deltas");
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public class MyersDiffTest {
|
||||
public void testDiffMyersExample1Forward() {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "A", "B", "B", "A");
|
||||
List<String> revised = Arrays.asList("C", "B", "A", "B", "A", "C");
|
||||
final Patch<String> patch = Patch.generate(original, revised, new MyersDiff<String>().computeDiff(original, revised, null));
|
||||
final Patch<String> patch = Patch.generate(original, revised, new MeyersDiff<String>().computeDiff(original, revised, null));
|
||||
assertNotNull(patch);
|
||||
assertEquals(4, patch.getDeltas().size());
|
||||
assertEquals("Patch{deltas=[[DeleteDelta, position: 0, lines: [A, B]], [InsertDelta, position: 3, lines: [B]], [DeleteDelta, position: 5, lines: [B]], [InsertDelta, position: 7, lines: [C]]]}", patch.toString());
|
||||
@@ -47,7 +47,7 @@ public class MyersDiffTest {
|
||||
|
||||
List<String> logdata = new ArrayList<>();
|
||||
final Patch<String> patch = Patch.generate(original, revised,
|
||||
new MyersDiff<String>().computeDiff(original, revised, new DiffAlgorithmListener() {
|
||||
new MeyersDiff<String>().computeDiff(original, revised, new DiffAlgorithmListener() {
|
||||
@Override
|
||||
public void diffStart() {
|
||||
logdata.add("start");
|
||||
@@ -69,5 +69,4 @@ public class MyersDiffTest {
|
||||
System.out.println(logdata);
|
||||
assertEquals(8, logdata.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,394 @@
|
||||
package com.github.difflib.algorithm.myers;
|
||||
|
||||
import com.github.difflib.patch.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
|
||||
public class WithMeyersDiffWithLinearSpacePatchTest {
|
||||
|
||||
@Test
|
||||
public void testPatch_Insert() {
|
||||
final List<String> insertTest_from = Arrays.asList("hhh");
|
||||
final List<String> insertTest_to = Arrays.asList("hhh", "jjj", "kkk", "lll");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(insertTest_from, insertTest_to, new MeyersDiffWithLinearSpace<String>());
|
||||
try {
|
||||
assertEquals(insertTest_to, DiffUtils.patch(insertTest_from, patch));
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Delete() {
|
||||
final List<String> deleteTest_from = Arrays.asList("ddd", "fff", "ggg", "hhh");
|
||||
final List<String> deleteTest_to = Arrays.asList("ggg");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(deleteTest_from, deleteTest_to, new MeyersDiffWithLinearSpace<String>());
|
||||
try {
|
||||
assertEquals(deleteTest_to, DiffUtils.patch(deleteTest_from, patch));
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to, new MeyersDiffWithLinearSpace<String>());
|
||||
try {
|
||||
assertEquals(changeTest_to, DiffUtils.patch(changeTest_from, patch));
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// region testPatch_fuzzyApply utils
|
||||
|
||||
private List<String> intRange(int count) {
|
||||
return IntStream.range(0, count)
|
||||
.mapToObj(Integer::toString)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private final List<String> join(List<String>... lists) {
|
||||
return Arrays.stream(lists).flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static class FuzzyApplyTestPair {
|
||||
public final List<String> from;
|
||||
public final List<String> to;
|
||||
public final int requiredFuzz;
|
||||
|
||||
private FuzzyApplyTestPair(List<String> from, List<String> to, int requiredFuzz) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.requiredFuzz = requiredFuzz;
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
@Test
|
||||
public void fuzzyApply() throws PatchFailedException {
|
||||
Patch<String> patch = new Patch<>();
|
||||
List<String> deltaFrom = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fff");
|
||||
List<String> deltaTo = Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fff");
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(6, deltaFrom),
|
||||
new Chunk<>(6, deltaTo)));
|
||||
|
||||
//noinspection unchecked
|
||||
List<String>[] moves = new List[] {
|
||||
intRange(6), // no patch move
|
||||
intRange(3), // forward patch move
|
||||
intRange(9), // backward patch move
|
||||
intRange(0), // apply to the first
|
||||
};
|
||||
|
||||
for (FuzzyApplyTestPair pair : FUZZY_APPLY_TEST_PAIRS) {
|
||||
for (List<String> move : moves) {
|
||||
List<String> from = join(move, pair.from);
|
||||
List<String> to = join(move, pair.to);
|
||||
|
||||
for (int i = 0; i < pair.requiredFuzz; i++) {
|
||||
int maxFuzz = i;
|
||||
assertThrows(PatchFailedException.class, () ->
|
||||
patch.applyFuzzy(from, maxFuzz),
|
||||
() -> "fail for " + from + " -> " + to + " for fuzz " + maxFuzz + " required " + pair.requiredFuzz);
|
||||
}
|
||||
for (int i = pair.requiredFuzz; i < 4; i++) {
|
||||
int maxFuzz = i;
|
||||
assertEquals(to, patch.applyFuzzy(from, maxFuzz),
|
||||
() -> "with " + maxFuzz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fuzzyApplyTwoSideBySidePatches() throws PatchFailedException {
|
||||
Patch<String> patch = new Patch<>();
|
||||
List<String> deltaFrom = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fff");
|
||||
List<String> deltaTo = Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fff");
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(0, deltaFrom),
|
||||
new Chunk<>(0, deltaTo)));
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(6, deltaFrom),
|
||||
new Chunk<>(6, deltaTo)));
|
||||
|
||||
|
||||
assertEquals(join(deltaTo, deltaTo), patch.applyFuzzy(join(deltaFrom, deltaFrom), 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fuzzyApplyToNearest() throws PatchFailedException {
|
||||
Patch<String> patch = new Patch<>();
|
||||
List<String> deltaFrom = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fff");
|
||||
List<String> deltaTo = Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fff");
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(0, deltaFrom),
|
||||
new Chunk<>(0, deltaTo)));
|
||||
patch.addDelta(new ChangeDelta<>(
|
||||
new Chunk<>(10, deltaFrom),
|
||||
new Chunk<>(10, deltaTo)));
|
||||
|
||||
assertEquals(join(deltaTo, deltaFrom, deltaTo),
|
||||
patch.applyFuzzy(join(deltaFrom, deltaFrom, deltaFrom), 0));
|
||||
assertEquals(join(intRange(1), deltaTo, deltaFrom, deltaTo),
|
||||
patch.applyFuzzy(join(intRange(1), deltaFrom, deltaFrom, deltaFrom), 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Serializable() throws IOException, ClassNotFoundException {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to, new MeyersDiffWithLinearSpace<String>());
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(baos);
|
||||
out.writeObject(patch);
|
||||
out.close();
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
||||
ObjectInputStream in = new ObjectInputStream(bais);
|
||||
Patch<String> result = (Patch<String>) in.readObject();
|
||||
in.close();
|
||||
|
||||
try {
|
||||
assertEquals(changeTest_to, DiffUtils.patch(changeTest_from, result));
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change_withExceptionProcessor() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to, new MeyersDiffWithLinearSpace<String>());
|
||||
|
||||
changeTest_from.set(2, "CDC");
|
||||
|
||||
patch.withConflictOutput(Patch.CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
try {
|
||||
List<String> data = DiffUtils.patch(changeTest_from, patch);
|
||||
assertEquals(11, data.size());
|
||||
|
||||
assertEquals(Arrays.asList("aaa", "bxb", "cxc", "<<<<<< HEAD", "bbb", "CDC", "======", "bbb", "ccc", ">>>>>>> PATCH", "ddd"), data);
|
||||
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
static class FuzzyApplyTestDataGenerator {
|
||||
private static String createList(List<String> values) {
|
||||
return values.stream()
|
||||
.map(x -> '"' + x + '"')
|
||||
.collect(Collectors.joining(", ", "Arrays.asList(", ")"));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String[] deltaFrom = new String[] { "aaa", "bbb", "ccc", "ddd", "eee", "fff" };
|
||||
String[] deltaTo = new String[] { "aaa", "bbb", "cxc", "dxd", "eee", "fff" };
|
||||
|
||||
List<FuzzyApplyTestPair> pairs = new ArrayList<>();
|
||||
|
||||
// create test data.
|
||||
// Brute-force search
|
||||
String[] changedValue = new String[]{"axa", "bxb", "czc", "dzd", "exe", "fxf"};
|
||||
for (int i = 0; i < 1 << 6; i++) {
|
||||
if ((i & 0b001100) != 0 && (i & 0b001100) != 0b001100) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] from = deltaFrom.clone();
|
||||
String[] to = deltaTo.clone();
|
||||
for (int j = 0; j < 6; j++) {
|
||||
if ((i & (1 << j)) != 0) {
|
||||
from[j] = changedValue[j];
|
||||
to[j] = changedValue[j];
|
||||
}
|
||||
}
|
||||
|
||||
int requiredFuzz;
|
||||
if ((i & 0b001100) != 0) {
|
||||
requiredFuzz = 3;
|
||||
} else if ((i & 0b010010) != 0) {
|
||||
requiredFuzz = 2;
|
||||
} else if ((i & 0b100001) != 0) {
|
||||
requiredFuzz = 1;
|
||||
} else {
|
||||
requiredFuzz = 0;
|
||||
}
|
||||
|
||||
pairs.add(new FuzzyApplyTestPair(Arrays.asList(from), Arrays.asList(to), requiredFuzz));
|
||||
}
|
||||
pairs.sort(Comparator.comparingInt(a -> a.requiredFuzz));
|
||||
System.out.println("FuzzyApplyTestPair[] pairs = new FuzzyApplyTestPair[] {");
|
||||
for (FuzzyApplyTestPair pair : pairs) {
|
||||
System.out.println(" new FuzzyApplyTestPair(");
|
||||
System.out.println(" " + createList(pair.from) + ",");
|
||||
System.out.println(" " + createList(pair.to) + ",");
|
||||
System.out.println(" " + pair.requiredFuzz + "),");
|
||||
}
|
||||
System.out.println("};");
|
||||
}
|
||||
}
|
||||
|
||||
private static final FuzzyApplyTestPair[] FUZZY_APPLY_TEST_PAIRS = new FuzzyApplyTestPair[] {
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fff"),
|
||||
Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fff"),
|
||||
0),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "ccc", "ddd", "eee", "fff"),
|
||||
Arrays.asList("axa", "bbb", "cxc", "dxd", "eee", "fff"),
|
||||
1),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee", "fxf"),
|
||||
Arrays.asList("aaa", "bbb", "cxc", "dxd", "eee", "fxf"),
|
||||
1),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "ccc", "ddd", "eee", "fxf"),
|
||||
Arrays.asList("axa", "bbb", "cxc", "dxd", "eee", "fxf"),
|
||||
1),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "ccc", "ddd", "eee", "fff"),
|
||||
Arrays.asList("aaa", "bxb", "cxc", "dxd", "eee", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "ccc", "ddd", "eee", "fff"),
|
||||
Arrays.asList("axa", "bxb", "cxc", "dxd", "eee", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "ccc", "ddd", "exe", "fff"),
|
||||
Arrays.asList("aaa", "bbb", "cxc", "dxd", "exe", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "ccc", "ddd", "exe", "fff"),
|
||||
Arrays.asList("axa", "bbb", "cxc", "dxd", "exe", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "ccc", "ddd", "exe", "fff"),
|
||||
Arrays.asList("aaa", "bxb", "cxc", "dxd", "exe", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "ccc", "ddd", "exe", "fff"),
|
||||
Arrays.asList("axa", "bxb", "cxc", "dxd", "exe", "fff"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "ccc", "ddd", "eee", "fxf"),
|
||||
Arrays.asList("aaa", "bxb", "cxc", "dxd", "eee", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "ccc", "ddd", "eee", "fxf"),
|
||||
Arrays.asList("axa", "bxb", "cxc", "dxd", "eee", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "ccc", "ddd", "exe", "fxf"),
|
||||
Arrays.asList("aaa", "bbb", "cxc", "dxd", "exe", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "ccc", "ddd", "exe", "fxf"),
|
||||
Arrays.asList("axa", "bbb", "cxc", "dxd", "exe", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "ccc", "ddd", "exe", "fxf"),
|
||||
Arrays.asList("aaa", "bxb", "cxc", "dxd", "exe", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "ccc", "ddd", "exe", "fxf"),
|
||||
Arrays.asList("axa", "bxb", "cxc", "dxd", "exe", "fxf"),
|
||||
2),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "eee", "fff"),
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "eee", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "eee", "fff"),
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "eee", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "eee", "fff"),
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "eee", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "eee", "fff"),
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "eee", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "exe", "fff"),
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "exe", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "exe", "fff"),
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "exe", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "exe", "fff"),
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "exe", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "exe", "fff"),
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "exe", "fff"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "eee", "fxf"),
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "eee", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "eee", "fxf"),
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "eee", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "eee", "fxf"),
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "eee", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "eee", "fxf"),
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "eee", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "exe", "fxf"),
|
||||
Arrays.asList("aaa", "bbb", "czc", "dzd", "exe", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "exe", "fxf"),
|
||||
Arrays.asList("axa", "bbb", "czc", "dzd", "exe", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "exe", "fxf"),
|
||||
Arrays.asList("aaa", "bxb", "czc", "dzd", "exe", "fxf"),
|
||||
3),
|
||||
new FuzzyApplyTestPair(
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "exe", "fxf"),
|
||||
Arrays.asList("axa", "bxb", "czc", "dzd", "exe", "fxf"),
|
||||
3),
|
||||
};
|
||||
}
|
||||
@@ -12,11 +12,11 @@ import java.util.List;
|
||||
public class ComputeDifference {
|
||||
|
||||
private static final String ORIGINAL = TestConstants.MOCK_FOLDER + "original.txt";
|
||||
private static final String RIVISED = TestConstants.MOCK_FOLDER + "revised.txt";
|
||||
private static final String REVISED = TestConstants.MOCK_FOLDER + "revised.txt";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
List<String> original = Files.readAllLines(new File(ORIGINAL).toPath());
|
||||
List<String> revised = Files.readAllLines(new File(RIVISED).toPath());
|
||||
List<String> revised = Files.readAllLines(new File(REVISED).toPath());
|
||||
|
||||
// Compute diff. Get the Patch object. Patch is the container for computed deltas.
|
||||
Patch<String> patch = DiffUtils.diff(original, revised);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.github.difflib.patch;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ChunkTest {
|
||||
@Test
|
||||
void verifyChunk() throws PatchFailedException {
|
||||
Chunk<Character> chunk = new Chunk<>(7, toCharList("test"));
|
||||
|
||||
// normal check
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("prefix test suffix")));
|
||||
assertEquals(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET,
|
||||
chunk.verifyChunk(toCharList("prefix es suffix"), 0, 7));
|
||||
|
||||
// position
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("short test suffix"), 0, 6));
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("loonger test suffix"), 0, 8));
|
||||
assertEquals(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET,
|
||||
chunk.verifyChunk(toCharList("prefix test suffix"), 0, 6));
|
||||
assertEquals(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET,
|
||||
chunk.verifyChunk(toCharList("prefix test suffix"), 0, 8));
|
||||
|
||||
// fuzz
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("prefix test suffix"), 1, 7));
|
||||
assertEquals(VerifyChunk.OK,
|
||||
chunk.verifyChunk(toCharList("prefix es suffix"), 1, 7));
|
||||
assertEquals(VerifyChunk.CONTENT_DOES_NOT_MATCH_TARGET,
|
||||
chunk.verifyChunk(toCharList("prefix suffix"), 1, 7));
|
||||
}
|
||||
|
||||
private List<Character> toCharList(String str) {
|
||||
return str.chars().mapToObj(x -> (char) x).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -11,14 +11,35 @@ import java.io.ObjectOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.DiffAlgorithmFactory;
|
||||
import com.github.difflib.algorithm.myers.MeyersDiff;
|
||||
import com.github.difflib.algorithm.myers.MeyersDiffWithLinearSpace;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class PatchTest {
|
||||
public class PatchWithAllDiffAlgorithmsTest {
|
||||
|
||||
@Test
|
||||
public void testPatch_Insert() {
|
||||
private static Stream<Arguments> provideAlgorithms() {
|
||||
return Stream.of(
|
||||
Arguments.of(MeyersDiff.factory()),
|
||||
Arguments.of(MeyersDiffWithLinearSpace.factory()));
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterAll() {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(MeyersDiff.factory());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideAlgorithms")
|
||||
public void testPatch_Insert(DiffAlgorithmFactory factory) {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(factory);
|
||||
|
||||
final List<String> insertTest_from = Arrays.asList("hhh");
|
||||
final List<String> insertTest_to = Arrays.asList("hhh", "jjj", "kkk", "lll");
|
||||
|
||||
@@ -30,8 +51,11 @@ public class PatchTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Delete() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideAlgorithms")
|
||||
public void testPatch_Delete(DiffAlgorithmFactory factory) {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(factory);
|
||||
|
||||
final List<String> deleteTest_from = Arrays.asList("ddd", "fff", "ggg", "hhh");
|
||||
final List<String> deleteTest_to = Arrays.asList("ggg");
|
||||
|
||||
@@ -43,8 +67,11 @@ public class PatchTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change() {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideAlgorithms")
|
||||
public void testPatch_Change(DiffAlgorithmFactory factory) {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(factory);
|
||||
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
@@ -56,8 +83,11 @@ public class PatchTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Serializable() throws IOException, ClassNotFoundException {
|
||||
@ParameterizedTest
|
||||
@MethodSource("provideAlgorithms")
|
||||
public void testPatch_Serializable(DiffAlgorithmFactory factory) throws IOException, ClassNotFoundException {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(factory);
|
||||
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
@@ -77,27 +107,5 @@ public class PatchTest {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change_withExceptionProcessor() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to);
|
||||
|
||||
changeTest_from.set(2, "CDC");
|
||||
|
||||
patch.withConflictOutput(Patch.CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
try {
|
||||
List<String> data = DiffUtils.patch(changeTest_from, patch);
|
||||
assertEquals(9, data.size());
|
||||
|
||||
assertEquals(Arrays.asList("aaa", "<<<<<< HEAD", "bbb", "CDC", "======", "bbb", "ccc", ">>>>>>> PATCH", "ddd"), data);
|
||||
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2021 java-diff-utils.
|
||||
*
|
||||
* Licensed 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 com.github.difflib.patch;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import static com.github.difflib.patch.Patch.CONFLICT_PRODUCES_MERGE_CONFLICT;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class PatchWithMeyerDiffTest {
|
||||
|
||||
@Test
|
||||
public void testPatch_Change_withExceptionProcessor() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to);
|
||||
|
||||
changeTest_from.set(2, "CDC");
|
||||
|
||||
patch.withConflictOutput(Patch.CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
try {
|
||||
List<String> data = DiffUtils.patch(changeTest_from, patch);
|
||||
assertEquals(9, data.size());
|
||||
|
||||
assertEquals(Arrays.asList("aaa", "<<<<<< HEAD", "bbb", "CDC", "======", "bbb", "ccc", ">>>>>>> PATCH", "ddd"), data);
|
||||
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchThreeWayIssue138() throws PatchFailedException {
|
||||
List<String> base = Arrays.asList("Imagine there's no heaven".split("\\s+"));
|
||||
List<String> left = Arrays.asList("Imagine there's no HEAVEN".split("\\s+"));
|
||||
List<String> right = Arrays.asList("IMAGINE there's no heaven".split("\\s+"));
|
||||
|
||||
Patch<String> rightPatch = DiffUtils.diff(base, right)
|
||||
.withConflictOutput(CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
List<String> applied = rightPatch.applyTo(left);
|
||||
|
||||
assertEquals("IMAGINE there's no HEAVEN", applied.stream().collect(joining(" ")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2021 java-diff-utils.
|
||||
*
|
||||
* Licensed 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 com.github.difflib.patch;
|
||||
|
||||
import com.github.difflib.DiffUtils;
|
||||
import com.github.difflib.algorithm.myers.MeyersDiff;
|
||||
import com.github.difflib.algorithm.myers.MeyersDiffWithLinearSpace;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tw
|
||||
*/
|
||||
public class PatchWithMeyerDiffWithLinearSpaceTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void setupClass() {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(MeyersDiffWithLinearSpace.factory());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void resetClass() {
|
||||
DiffUtils.withDefaultDiffAlgorithmFactory(MeyersDiff.factory());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch_Change_withExceptionProcessor() {
|
||||
final List<String> changeTest_from = Arrays.asList("aaa", "bbb", "ccc", "ddd");
|
||||
final List<String> changeTest_to = Arrays.asList("aaa", "bxb", "cxc", "ddd");
|
||||
|
||||
final Patch<String> patch = DiffUtils.diff(changeTest_from, changeTest_to);
|
||||
|
||||
changeTest_from.set(2, "CDC");
|
||||
|
||||
patch.withConflictOutput(Patch.CONFLICT_PRODUCES_MERGE_CONFLICT);
|
||||
|
||||
try {
|
||||
List<String> data = DiffUtils.patch(changeTest_from, patch);
|
||||
assertEquals(11, data.size());
|
||||
|
||||
assertEquals(Arrays.asList("aaa", "bxb", "cxc", "<<<<<< HEAD", "bbb", "CDC", "======", "bbb", "ccc", ">>>>>>> PATCH", "ddd"), data);
|
||||
|
||||
} catch (PatchFailedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -641,7 +641,7 @@ public class DiffRowGeneratorTest {
|
||||
|
||||
assertThat(rows).extracting(item -> item.getTag().name()).containsExactly("CHANGE", "DELETE", "EQUAL", "CHANGE", "EQUAL");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCorrectChangeIssue114_2() throws IOException {
|
||||
List<String> original = Arrays.asList("A", "B", "C", "D", "E");
|
||||
@@ -662,7 +662,7 @@ public class DiffRowGeneratorTest {
|
||||
assertThat(rows).extracting(item -> item.getTag().name()).containsExactly("CHANGE", "DELETE", "EQUAL", "CHANGE", "EQUAL");
|
||||
assertThat(rows.get(1).toString()).isEqualTo("[DELETE,~B~,]");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIssue119WrongContextLength() throws IOException {
|
||||
String original = Files.lines(Paths.get("target/test-classes/com/github/difflib/text/issue_119_original.txt")).collect(joining("\n"));
|
||||
@@ -683,4 +683,106 @@ public class DiffRowGeneratorTest {
|
||||
.filter(item -> item.getTag() != DiffRow.Tag.EQUAL)
|
||||
.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue129WithDeltaDecompression() {
|
||||
List<String> lines1 = Arrays.asList(
|
||||
"apple1",
|
||||
"apple2",
|
||||
"apple3",
|
||||
"A man named Frankenstein abc to Switzerland for cookies!",
|
||||
"banana1",
|
||||
"banana2",
|
||||
"banana3");
|
||||
List<String> lines2 = Arrays.asList(
|
||||
"apple1",
|
||||
"apple2",
|
||||
"apple3",
|
||||
"A man named Frankenstein",
|
||||
"xyz",
|
||||
"to Switzerland for cookies!",
|
||||
"banana1",
|
||||
"banana2",
|
||||
"banana3");
|
||||
int[] entry = {1};
|
||||
String txt = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.oldTag((tag, isOpening) -> isOpening ? "==old" + tag + "==>" : "<==old==")
|
||||
.newTag((tag, isOpening) -> isOpening ? "==new" + tag + "==>" : "<==new==")
|
||||
.build()
|
||||
.generateDiffRows(lines1, lines2)
|
||||
.stream()
|
||||
.map(row -> row.getTag().toString())
|
||||
.collect(joining(" "));
|
||||
// .forEachOrdered(row -> {
|
||||
// System.out.printf("%4d %-8s %-80s %-80s\n", entry[0]++,
|
||||
// row.getTag(), row.getOldLine(), row.getNewLine());
|
||||
// });
|
||||
|
||||
assertThat(txt).isEqualTo("EQUAL EQUAL EQUAL CHANGE INSERT INSERT EQUAL EQUAL EQUAL");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue129SkipDeltaDecompression() {
|
||||
List<String> lines1 = Arrays.asList(
|
||||
"apple1",
|
||||
"apple2",
|
||||
"apple3",
|
||||
"A man named Frankenstein abc to Switzerland for cookies!",
|
||||
"banana1",
|
||||
"banana2",
|
||||
"banana3");
|
||||
List<String> lines2 = Arrays.asList(
|
||||
"apple1",
|
||||
"apple2",
|
||||
"apple3",
|
||||
"A man named Frankenstein",
|
||||
"xyz",
|
||||
"to Switzerland for cookies!",
|
||||
"banana1",
|
||||
"banana2",
|
||||
"banana3");
|
||||
int[] entry = {1};
|
||||
String txt =
|
||||
DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.decompressDeltas(false)
|
||||
.oldTag((tag, isOpening) -> isOpening ? "==old" + tag + "==>" : "<==old==")
|
||||
.newTag((tag, isOpening) -> isOpening ? "==new" + tag + "==>" : "<==new==")
|
||||
.build()
|
||||
.generateDiffRows(lines1, lines2)
|
||||
.stream()
|
||||
.map(row -> row.getTag().toString())
|
||||
.collect(joining(" "));
|
||||
// .forEachOrdered(row -> {
|
||||
// System.out.printf("%4d %-8s %-80s %-80s\n", entry[0]++,
|
||||
// row.getTag(), row.getOldLine(), row.getNewLine());
|
||||
// });
|
||||
|
||||
assertThat(txt).isEqualTo("EQUAL EQUAL EQUAL CHANGE CHANGE CHANGE EQUAL EQUAL EQUAL");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssue129SkipWhitespaceChanges() throws IOException {
|
||||
String original = Files.lines(Paths.get("target/test-classes/com/github/difflib/text/issue129_1.txt")).collect(joining("\n"));
|
||||
String revised = Files.lines(Paths.get("target/test-classes/com/github/difflib/text/issue129_2.txt")).collect(joining("\n"));
|
||||
|
||||
DiffRowGenerator generator = DiffRowGenerator.create()
|
||||
.showInlineDiffs(true)
|
||||
.mergeOriginalRevised(true)
|
||||
.inlineDiffByWord(true)
|
||||
.ignoreWhiteSpaces(true)
|
||||
.oldTag((tag, isOpening) -> isOpening ? "==old" + tag + "==>" : "<==old==")
|
||||
.newTag((tag, isOpening) -> isOpening ? "==new" + tag + "==>" : "<==new==")
|
||||
.build();
|
||||
List<DiffRow> rows = generator.generateDiffRows(
|
||||
Arrays.asList(original.split("\n")),
|
||||
Arrays.asList(revised.split("\n")));
|
||||
|
||||
assertThat(rows).hasSize(13);
|
||||
|
||||
rows.stream()
|
||||
.filter(item -> item.getTag() != DiffRow.Tag.EQUAL)
|
||||
.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ public class UnifiedDiffReaderTest {
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo(".vhd");
|
||||
assertThat(file1.getFromFile()).isEqualTo("a.vhd");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
assertThat(diff.getTail()).isNull();
|
||||
@@ -277,12 +277,44 @@ public class UnifiedDiffReaderTest {
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(2);
|
||||
|
||||
final UnifiedDiffFile file = diff.getFiles().get(0);
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("Main.java");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue107_3() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue107_3.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
assertThat(file1.getFromFile()).isEqualTo("Billion laughs attack.md");
|
||||
assertThat(file1.getPatch().getDeltas().size()).isEqualTo(1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue107_4() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue107_4.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(27);
|
||||
|
||||
assertThat(diff.getFiles()).extracting(f -> f.getFromFile()).contains("README.md");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue107_5() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue107_5.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(22);
|
||||
|
||||
assertThat(diff.getFiles()).extracting(f -> f.getFromFile()).contains("rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorFactoryTest.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue110() throws IOException {
|
||||
@@ -332,4 +364,34 @@ public class UnifiedDiffReaderTest {
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue122() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue122.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(1);
|
||||
|
||||
assertThat(diff.getFiles()).extracting(f -> f.getFromFile()).contains("coders/wpg.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue123() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue123.diff"));
|
||||
|
||||
assertThat(diff.getFiles().size()).isEqualTo(2);
|
||||
|
||||
assertThat(diff.getFiles()).extracting(f -> f.getFromFile()).contains("src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseIssue141() throws IOException {
|
||||
UnifiedDiff diff = UnifiedDiffReader.parseUnifiedDiff(
|
||||
UnifiedDiffReaderTest.class.getResourceAsStream("problem_diff_issue141.diff"));
|
||||
UnifiedDiffFile file1 = diff.getFiles().get(0);
|
||||
|
||||
assertThat(file1.getFromFile()).isEqualTo("a.txt");
|
||||
assertThat(file1.getToFile()).isEqualTo("a1.txt");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2022 java-diff-utils.
|
||||
*
|
||||
* Licensed 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 com.github.difflib.unifieddiff;
|
||||
|
||||
import com.github.difflib.patch.PatchFailedException;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@Disabled("for next release")
|
||||
public class UnifiedDiffRoundTripNewLineTest {
|
||||
@Test
|
||||
public void testIssue135MissingNoNewLineInPatched() throws IOException, PatchFailedException {
|
||||
String beforeContent = "rootProject.name = \"sample-repo\"";
|
||||
String afterContent = "rootProject.name = \"sample-repo\"\n";
|
||||
String patch = "diff --git a/settings.gradle b/settings.gradle\n" +
|
||||
"index ef3b8e2..ab30124 100644\n" +
|
||||
"--- a/settings.gradle\n" +
|
||||
"+++ b/settings.gradle\n" +
|
||||
"@@ -1 +1 @@\n" +
|
||||
"-rootProject.name = \"sample-repo\"\n" +
|
||||
"\\ No newline at end of file\n" +
|
||||
"+rootProject.name = \"sample-repo\"\n";
|
||||
UnifiedDiff unifiedDiff = UnifiedDiffReader.parseUnifiedDiff(new ByteArrayInputStream(patch.getBytes()));
|
||||
String unifiedAfterContent = unifiedDiff.getFiles().get(0).getPatch()
|
||||
.applyTo(Arrays.asList(beforeContent.split("\n"))).stream().collect(joining("\n"));
|
||||
assertEquals(afterContent, unifiedAfterContent);
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public class UnifiedDiffRoundTripTest {
|
||||
// Patch<String> fromUnifiedPatch = unifiedDiff.getFiles().get(0).getPatch();
|
||||
// patchedLines = fromUnifiedPatch.applyTo(origLines);
|
||||
// }
|
||||
patchedLines = unifiedDiff.spplyPatchTo(file -> originalFile.equals(file), origLines);
|
||||
patchedLines = unifiedDiff.applyPatchTo(file -> originalFile.equals(file), origLines);
|
||||
assertEquals(revLines.size(), patchedLines.size());
|
||||
for (int i = 0; i < revLines.size(); i++) {
|
||||
String l1 = revLines.get(i);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated
|
||||
to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or
|
||||
any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to
|
||||
dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live.
|
||||
It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate -- we can not
|
||||
consecrate -- we can not hallow -- this ground. The brave men, living and dead, who struggled here, have consecrated it,
|
||||
far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never
|
||||
forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought
|
||||
here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us -- that
|
||||
from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion -- that
|
||||
we here highly resolve that these dead shall not have died in vain -- that this nation, under God, shall have a new birth of
|
||||
freedom -- and that government of the people, by the people, for the people, shall not perish from the earth.
|
||||
@@ -0,0 +1,13 @@
|
||||
Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and
|
||||
dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether
|
||||
that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that
|
||||
war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives
|
||||
that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we
|
||||
can not dedicate -- we can not consecrate -- we can not hallow -- this ground. The brave men, living and dead, who
|
||||
struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long
|
||||
remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated
|
||||
here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here
|
||||
dedicated to the great task remaining before us -- that from these honored dead we take increased devotion to that cause
|
||||
for which they gave the last full measure of devotion -- that we here highly resolve that these dead shall not have died
|
||||
in vain -- that this nation, under God, shall have a new birth of freedom -- and that government of the people, by the
|
||||
people, for the people, shall not perish from the earth.
|
||||
@@ -0,0 +1,24 @@
|
||||
diff -r 4d1de0a006b7 -r ace1482360cb Billion laughs attack.md
|
||||
--- a/Billion laughs attack.md Mon Feb 24 13:37:17 2020 +0000
|
||||
+++ b/Billion laughs attack.md Mon Feb 24 14:22:50 2020 +0000
|
||||
@@ -11,14 +11,12 @@
|
||||
|
||||
*The problem is*: when you stay with the mouth open and eyes closed then they may throw trash and you get sick.
|
||||
|
||||
-
|
||||
-SnakeYAML Engine [has a way to restrict the amount of aliases for collections](https://bitbucket.org/asomov/snakeyaml-engine/src/default/src/test/java/org/snakeyaml/engine/usecases/references/ReferencesTest.java) to fail early without allocation too much resources.
|
||||
+SnakeYAML 1.26+ [has a way to restrict the amount of aliases for collections](https://bitbucket.org/asomov/snakeyaml/src/default/src/test/java/org/yaml/snakeyaml/issues/issue377/ReferencesTest.java) to fail early without allocation too much resources.
|
||||
|
||||
# Solution #
|
||||
|
||||
-1. If the YAML is not coming from untrusted source (it is merely a configuration file) then it is a false positive. Just ignore it. The quality of NVD database is very low and contains tons of issues which appear to be false positives.
|
||||
-2. Migrate to [SnakeYAML Engine](https://bitbucket.org/asomov/snakeyaml-engine/src/default/). It has a configuration option to restrict aliases for collections (the aliases for scalars cannot grow and they are not restricted)
|
||||
-3. Check how it is done in SnakeYAML Engine and build your own SnakeYAML version with the same change.
|
||||
-4. Read the YAML and check its quality before giving the document to SnakeYAML (count `*` and `&` for instance)
|
||||
+1. Update to SnakeYAML 1.26. It has a configuration option to restrict aliases for collections (the aliases for scalars cannot grow and they are not restricted)
|
||||
+2. If the YAML is not coming from untrusted source (it is merely a configuration file) then it is a false positive. Just ignore it. The quality of NVD database is very low and contains tons of issues which appear to be false positives.
|
||||
+3. Read the YAML and check its quality before giving the document to SnakeYAML (count `*` and `&` for instance)
|
||||
|
||||
-Enjoy.
|
||||
\ No newline at end of file
|
||||
+Enjoy.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,835 @@
|
||||
diff --git a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
|
||||
index 1f2a7c4baec..9d636200d61 100644
|
||||
--- a/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
|
||||
+++ b/distribution/src/main/release/samples/throttling/src/main/java/demo/throttling/client/Client.java
|
||||
@@ -112,7 +112,6 @@ public static void main(String[] args) throws Exception {
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("bus.jmx.usePlatformMBeanServer", Boolean.TRUE);
|
||||
properties.put("bus.jmx.enabled", Boolean.TRUE);
|
||||
- properties.put("bus.jmx.createMBServerConnectorFactory", Boolean.FALSE);
|
||||
Bus b = new CXFBusFactory().createBus(null, properties);
|
||||
MetricRegistry registry = new MetricRegistry();
|
||||
CodahaleMetricsProvider.setupJMXReporter(b, registry);
|
||||
diff --git a/distribution/src/main/release/samples/wsdl_first/src/main/resources/server-applicationContext.xml b/distribution/src/main/release/samples/wsdl_first/src/main/resources/server-applicationContext.xml
|
||||
index 8bf5109ec95..391f97c624e 100644
|
||||
--- a/distribution/src/main/release/samples/wsdl_first/src/main/resources/server-applicationContext.xml
|
||||
+++ b/distribution/src/main/release/samples/wsdl_first/src/main/resources/server-applicationContext.xml
|
||||
@@ -45,4 +45,4 @@
|
||||
<bean class="org.apache.cxf.ext.logging.LoggingFeature"/>
|
||||
</jaxws:features>
|
||||
</jaxws:endpoint>
|
||||
-</beans>
|
||||
\ No newline at end of file
|
||||
+</beans>
|
||||
diff --git a/rt/management/pom.xml b/rt/management/pom.xml
|
||||
index f63f3bfa6d7..19ccf6ada0c 100644
|
||||
--- a/rt/management/pom.xml
|
||||
+++ b/rt/management/pom.xml
|
||||
@@ -34,8 +34,7 @@
|
||||
<cxf.module.name>org.apache.cxf.management</cxf.module.name>
|
||||
<cxf.osgi.import>
|
||||
javax.xml.bind*;version="${cxf.osgi.javax.bind.version}",
|
||||
- javax.annotation*;version="${cxf.osgi.javax.annotation.version}",
|
||||
- sun.rmi*;resolution:=optional
|
||||
+ javax.annotation*;version="${cxf.osgi.javax.annotation.version}"
|
||||
</cxf.osgi.import>
|
||||
</properties>
|
||||
<dependencies>
|
||||
diff --git a/rt/management/src/main/java/org/apache/cxf/management/jmx/InstrumentationManagerImpl.java b/rt/management/src/main/java/org/apache/cxf/management/jmx/InstrumentationManagerImpl.java
|
||||
index ee7f0a71fee..d898a4b6f5f 100644
|
||||
--- a/rt/management/src/main/java/org/apache/cxf/management/jmx/InstrumentationManagerImpl.java
|
||||
+++ b/rt/management/src/main/java/org/apache/cxf/management/jmx/InstrumentationManagerImpl.java
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package org.apache.cxf.management.jmx;
|
||||
|
||||
-import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -53,31 +52,25 @@
|
||||
import org.apache.cxf.management.ManagedComponent;
|
||||
import org.apache.cxf.management.ManagementConstants;
|
||||
import org.apache.cxf.management.jmx.export.runtime.ModelMBeanAssembler;
|
||||
-import org.apache.cxf.management.jmx.type.JMXConnectorPolicyType;
|
||||
|
||||
/**
|
||||
* The manager class for the JMXManagedComponent which hosts the JMXManagedComponents.
|
||||
*/
|
||||
-public class InstrumentationManagerImpl extends JMXConnectorPolicyType
|
||||
+public class InstrumentationManagerImpl
|
||||
implements InstrumentationManager, BusLifeCycleListener {
|
||||
private static final Logger LOG = LogUtils.getL7dLogger(InstrumentationManagerImpl.class);
|
||||
|
||||
private static Map<String, String> mbeanServerIDMap = new HashMap<>();
|
||||
|
||||
private Bus bus;
|
||||
- private MBServerConnectorFactory mcf;
|
||||
private MBeanServer mbs;
|
||||
private Set<ObjectName> busMBeans = new HashSet<>();
|
||||
private boolean connectFailed;
|
||||
private String persistentBusId;
|
||||
- private Map<String, ?> environment;
|
||||
|
||||
- /**
|
||||
- * For backward compatibility, {@link #createMBServerConnectorFactory} is <code>true</code> by default.
|
||||
- */
|
||||
- private boolean createMBServerConnectorFactory = true;
|
||||
private String mbeanServerName = ManagementConstants.DEFAULT_DOMAIN_NAME;
|
||||
private boolean usePlatformMBeanServer;
|
||||
+ private boolean enabled;
|
||||
|
||||
public InstrumentationManagerImpl() {
|
||||
super();
|
||||
@@ -119,16 +112,16 @@ public void setServerName(String s) {
|
||||
mbeanServerName = s;
|
||||
}
|
||||
|
||||
- public void setCreateMBServerConnectorFactory(boolean createMBServerConnectorFactory) {
|
||||
- this.createMBServerConnectorFactory = createMBServerConnectorFactory;
|
||||
- }
|
||||
-
|
||||
public void setUsePlatformMBeanServer(Boolean flag) {
|
||||
usePlatformMBeanServer = flag;
|
||||
}
|
||||
|
||||
- public void setEnvironment(Map<String, ?> env) {
|
||||
- environment = env;
|
||||
+ public void setEnabled(boolean enabled) {
|
||||
+ this.enabled = enabled;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isEnabled() {
|
||||
+ return enabled;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -139,7 +132,6 @@ public void register() {
|
||||
public void init() {
|
||||
if (bus != null && bus.getExtension(MBeanServer.class) != null) {
|
||||
enabled = true;
|
||||
- createMBServerConnectorFactory = false;
|
||||
mbs = bus.getExtension(MBeanServer.class);
|
||||
}
|
||||
if (isEnabled()) {
|
||||
@@ -168,21 +160,6 @@ public void init() {
|
||||
}
|
||||
}
|
||||
|
||||
- if (createMBServerConnectorFactory) {
|
||||
- mcf = MBServerConnectorFactory.getInstance();
|
||||
- mcf.setMBeanServer(mbs);
|
||||
- mcf.setThreaded(isThreaded());
|
||||
- mcf.setDaemon(isDaemon());
|
||||
- mcf.setServiceUrl(getJMXServiceURL());
|
||||
- mcf.setEnvironment(environment);
|
||||
- try {
|
||||
- mcf.createConnector();
|
||||
- } catch (IOException ex) {
|
||||
- connectFailed = true;
|
||||
- LOG.log(Level.SEVERE, "START_CONNECTOR_FAILURE_MSG", new Object[] {ex});
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (!connectFailed && null != bus) {
|
||||
try {
|
||||
//Register Bus here since we can guarantee that Instrumentation
|
||||
@@ -282,14 +259,6 @@ public void shutdown() {
|
||||
return;
|
||||
}
|
||||
|
||||
- if (mcf != null) {
|
||||
- try {
|
||||
- mcf.destroy();
|
||||
- } catch (IOException ex) {
|
||||
- LOG.log(Level.SEVERE, "STOP_CONNECTOR_FAILURE_MSG", new Object[] {ex});
|
||||
- }
|
||||
- }
|
||||
-
|
||||
//Using the array to hold the busMBeans to avoid the CurrentModificationException
|
||||
Object[] mBeans = busMBeans.toArray();
|
||||
for (Object name : mBeans) {
|
||||
@@ -400,12 +369,7 @@ private void readJMXProperties(Bus b) {
|
||||
getBusProperty(b, "bus.jmx.serverName", mbeanServerName);
|
||||
usePlatformMBeanServer =
|
||||
getBusProperty(b, "bus.jmx.usePlatformMBeanServer", usePlatformMBeanServer);
|
||||
- createMBServerConnectorFactory =
|
||||
- getBusProperty(b, "bus.jmx.createMBServerConnectorFactory", createMBServerConnectorFactory);
|
||||
- daemon = getBusProperty(b, "bus.jmx.daemon", daemon);
|
||||
- threaded = getBusProperty(b, "bus.jmx.threaded", threaded);
|
||||
enabled = getBusProperty(b, "bus.jmx.enabled", enabled);
|
||||
- jmxServiceURL = getBusProperty(b, "bus.jmx.JMXServiceURL", jmxServiceURL);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/rt/management/src/main/java/org/apache/cxf/management/jmx/MBServerConnectorFactory.java b/rt/management/src/main/java/org/apache/cxf/management/jmx/MBServerConnectorFactory.java
|
||||
deleted file mode 100644
|
||||
index 5eb7059b8fb..00000000000
|
||||
--- a/rt/management/src/main/java/org/apache/cxf/management/jmx/MBServerConnectorFactory.java
|
||||
+++ /dev/null
|
||||
@@ -1,260 +0,0 @@
|
||||
-/**
|
||||
- * 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.cxf.management.jmx;
|
||||
-
|
||||
-import java.io.IOException;
|
||||
-import java.net.URI;
|
||||
-import java.net.URISyntaxException;
|
||||
-import java.rmi.AccessException;
|
||||
-import java.rmi.AlreadyBoundException;
|
||||
-import java.rmi.NotBoundException;
|
||||
-import java.rmi.Remote;
|
||||
-import java.rmi.RemoteException;
|
||||
-import java.util.Map;
|
||||
-import java.util.logging.Level;
|
||||
-import java.util.logging.Logger;
|
||||
-
|
||||
-import javax.management.MBeanServer;
|
||||
-import javax.management.MBeanServerFactory;
|
||||
-import javax.management.remote.JMXConnectorServer;
|
||||
-import javax.management.remote.JMXServiceURL;
|
||||
-import javax.management.remote.rmi.RMIConnectorServer;
|
||||
-import javax.management.remote.rmi.RMIJRMPServerImpl;
|
||||
-
|
||||
-import org.apache.cxf.common.logging.LogUtils;
|
||||
-
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Deal with the MBeanServer Connections
|
||||
- *
|
||||
- */
|
||||
-public final class MBServerConnectorFactory {
|
||||
-
|
||||
- public static final String DEFAULT_SERVICE_URL = "service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi";
|
||||
-
|
||||
- private static final Logger LOG = LogUtils.getL7dLogger(MBServerConnectorFactory.class);
|
||||
-
|
||||
- private static MBeanServer server;
|
||||
-
|
||||
- private static String serviceUrl = DEFAULT_SERVICE_URL;
|
||||
-
|
||||
- private static Map<String, ?> environment;
|
||||
-
|
||||
- private static boolean threaded;
|
||||
-
|
||||
- private static boolean daemon;
|
||||
-
|
||||
- private static JMXConnectorServer connectorServer;
|
||||
-
|
||||
- private static Remote remoteServerStub;
|
||||
-
|
||||
- private static RMIJRMPServerImpl rmiServer;
|
||||
-
|
||||
- private static class MBServerConnectorFactoryHolder {
|
||||
- private static final MBServerConnectorFactory INSTANCE =
|
||||
- new MBServerConnectorFactory();
|
||||
- }
|
||||
-
|
||||
- private static class MBeanServerHolder {
|
||||
- private static final MBeanServer INSTANCE =
|
||||
- MBeanServerFactory.createMBeanServer();
|
||||
- }
|
||||
-
|
||||
- private MBServerConnectorFactory() {
|
||||
-
|
||||
- }
|
||||
-
|
||||
- static int getServerPort(final String url) {
|
||||
- int portStart = url.indexOf("localhost") + 10;
|
||||
- int portEnd;
|
||||
- int port = 0;
|
||||
- if (portStart > 0) {
|
||||
- portEnd = indexNotOfNumber(url, portStart);
|
||||
- if (portEnd > portStart) {
|
||||
- final String portString = url.substring(portStart, portEnd);
|
||||
- port = Integer.parseInt(portString);
|
||||
- }
|
||||
- }
|
||||
- return port;
|
||||
- }
|
||||
-
|
||||
- private static int indexNotOfNumber(String str, int index) {
|
||||
- int i = 0;
|
||||
- for (i = index; i < str.length(); i++) {
|
||||
- if (str.charAt(i) < '0' || str.charAt(i) > '9') {
|
||||
- return i;
|
||||
- }
|
||||
- }
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- public static MBServerConnectorFactory getInstance() {
|
||||
- return MBServerConnectorFactoryHolder.INSTANCE;
|
||||
- }
|
||||
-
|
||||
- public void setMBeanServer(MBeanServer ms) {
|
||||
- server = ms;
|
||||
- }
|
||||
-
|
||||
- public void setServiceUrl(String url) {
|
||||
- serviceUrl = url;
|
||||
- }
|
||||
-
|
||||
- public void setEnvironment(Map<String, ?> env) {
|
||||
- environment = env;
|
||||
- }
|
||||
-
|
||||
- public void setThreaded(boolean fthread) {
|
||||
- threaded = fthread;
|
||||
- }
|
||||
-
|
||||
- public void setDaemon(boolean fdaemon) {
|
||||
- daemon = fdaemon;
|
||||
- }
|
||||
-
|
||||
-
|
||||
- public void createConnector() throws IOException {
|
||||
-
|
||||
- if (server == null) {
|
||||
- server = MBeanServerHolder.INSTANCE;
|
||||
- }
|
||||
-
|
||||
- // Create the JMX service URL.
|
||||
- final JMXServiceURL url = new JMXServiceURL(serviceUrl);
|
||||
-
|
||||
- // if the URL is localhost, start up an Registry
|
||||
- if (serviceUrl.indexOf("localhost") > -1
|
||||
- && url.getProtocol().compareToIgnoreCase("rmi") == 0) {
|
||||
- try {
|
||||
- int port = getRegistryPort(serviceUrl);
|
||||
- new JmxRegistry(port, getBindingName(url));
|
||||
-
|
||||
- } catch (Exception ex) {
|
||||
- LOG.log(Level.SEVERE, "CREATE_REGISTRY_FAULT_MSG", new Object[]{ex});
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- rmiServer = new RMIJRMPServerImpl(getServerPort(serviceUrl), null, null, environment);
|
||||
-
|
||||
- // Create the connector server now.
|
||||
- connectorServer = new RMIConnectorServer(url, environment, rmiServer, server);
|
||||
-
|
||||
- if (threaded) {
|
||||
- // Start the connector server asynchronously (in a separate thread).
|
||||
- Thread connectorThread = new Thread() {
|
||||
- public void run() {
|
||||
- try {
|
||||
- connectorServer.start();
|
||||
- remoteServerStub = rmiServer.toStub();
|
||||
- } catch (IOException ex) {
|
||||
- LOG.log(Level.SEVERE, "START_CONNECTOR_FAILURE_MSG", new Object[]{ex});
|
||||
- }
|
||||
- }
|
||||
- };
|
||||
-
|
||||
- connectorThread.setName("JMX Connector Thread [" + serviceUrl + "]");
|
||||
- connectorThread.setDaemon(daemon);
|
||||
- connectorThread.start();
|
||||
- } else {
|
||||
- // Start the connector server in the same thread.
|
||||
- connectorServer.start();
|
||||
- remoteServerStub = rmiServer.toStub();
|
||||
- }
|
||||
-
|
||||
- if (LOG.isLoggable(Level.INFO)) {
|
||||
- LOG.info("JMX connector server started: " + connectorServer);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- static int getRegistryPort(final String url) {
|
||||
- int serverStart = url.indexOf("/jndi/rmi://");
|
||||
- final String serverPart = url.substring(serverStart + 12);
|
||||
- int portStart = serverPart.indexOf(':') + 1;
|
||||
-
|
||||
- int portEnd;
|
||||
- int port = 0;
|
||||
- if (portStart > 0) {
|
||||
- portEnd = indexNotOfNumber(serverPart, portStart);
|
||||
- if (portEnd > portStart) {
|
||||
- final String portString = serverPart.substring(portStart, portEnd);
|
||||
- port = Integer.parseInt(portString);
|
||||
- }
|
||||
- }
|
||||
- return port;
|
||||
- }
|
||||
-
|
||||
- protected static String getBindingName(final JMXServiceURL jmxServiceURL) {
|
||||
- final String urlPath = jmxServiceURL.getURLPath();
|
||||
-
|
||||
- try {
|
||||
- if (urlPath.startsWith("/jndi/")) {
|
||||
- return new URI(urlPath.substring(6)).getPath()
|
||||
- .replaceAll("^/+", "").replaceAll("/+$", "");
|
||||
- }
|
||||
- } catch (URISyntaxException e) {
|
||||
- // ignore
|
||||
- }
|
||||
-
|
||||
- return "jmxrmi"; // use the default
|
||||
- }
|
||||
-
|
||||
- public void destroy() throws IOException {
|
||||
- connectorServer.stop();
|
||||
- if (LOG.isLoggable(Level.INFO)) {
|
||||
- LOG.info("JMX connector server stopped: " + connectorServer);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Better to use the internal API than re-invent the wheel.
|
||||
- */
|
||||
- @SuppressWarnings("restriction")
|
||||
- private class JmxRegistry extends sun.rmi.registry.RegistryImpl {
|
||||
- private final String lookupName;
|
||||
-
|
||||
- JmxRegistry(final int port, final String lookupName) throws RemoteException {
|
||||
- super(port);
|
||||
- this.lookupName = lookupName;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public Remote lookup(String s) throws RemoteException, NotBoundException {
|
||||
- return lookupName.equals(s) ? remoteServerStub : null;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void bind(String s, Remote remote) throws RemoteException, AlreadyBoundException, AccessException {
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void unbind(String s) throws RemoteException, NotBoundException, AccessException {
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public void rebind(String s, Remote remote) throws RemoteException, AccessException {
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public String[] list() throws RemoteException {
|
||||
- return new String[] {lookupName};
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
diff --git a/rt/management/src/main/java/org/apache/cxf/management/utils/ManagementConsole.java b/rt/management/src/main/java/org/apache/cxf/management/utils/ManagementConsole.java
|
||||
index 3fa2fe2891c..3739ffaa915 100644
|
||||
--- a/rt/management/src/main/java/org/apache/cxf/management/utils/ManagementConsole.java
|
||||
+++ b/rt/management/src/main/java/org/apache/cxf/management/utils/ManagementConsole.java
|
||||
@@ -42,7 +42,7 @@
|
||||
public final class ManagementConsole {
|
||||
private static MBeanServerConnection mbsc;
|
||||
private static final String DEFAULT_JMXSERVICE_URL =
|
||||
- "service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi";
|
||||
+ "service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi";
|
||||
private static final Logger LOG = LogUtils.getL7dLogger(ManagementConsole.class);
|
||||
|
||||
String jmxServerURL;
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/InstrumentationManagerTest.java b/rt/management/src/test/java/org/apache/cxf/management/InstrumentationManagerTest.java
|
||||
index 9ebc7ca4fe2..c505835d10a 100644
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/InstrumentationManagerTest.java
|
||||
+++ b/rt/management/src/test/java/org/apache/cxf/management/InstrumentationManagerTest.java
|
||||
@@ -158,7 +158,6 @@ public void testInstrumentBusWithBusProperties() {
|
||||
assertNotNull("Instrumentation Manager of cxf1 should not be null", im1);
|
||||
|
||||
assertTrue(im1.isEnabled());
|
||||
- assertEquals("service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi", im1.getJMXServiceURL());
|
||||
|
||||
cxf2 = (Bus)context.getBean("cxf2");
|
||||
InstrumentationManagerImpl im2 =
|
||||
@@ -166,7 +165,6 @@ public void testInstrumentBusWithBusProperties() {
|
||||
assertNotNull("Instrumentation Manager of cxf2 should not be null", im2);
|
||||
|
||||
assertFalse(im2.isEnabled());
|
||||
- assertEquals("service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi", im2.getJMXServiceURL());
|
||||
|
||||
} finally {
|
||||
if (cxf1 != null) {
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/jmx/BusRegistrationTest.java b/rt/management/src/test/java/org/apache/cxf/management/jmx/BusRegistrationTest.java
|
||||
index e9f9308289a..6c458f3085b 100644
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/jmx/BusRegistrationTest.java
|
||||
+++ b/rt/management/src/test/java/org/apache/cxf/management/jmx/BusRegistrationTest.java
|
||||
@@ -64,12 +64,6 @@ public void tearDown() throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
- @Test
|
||||
- public void testRegisterMultipleBuses() throws Exception {
|
||||
- // classic external IM-bean
|
||||
- testRegisterMultipleBuses("managed-spring.xml");
|
||||
- }
|
||||
-
|
||||
@Test
|
||||
public void testRegisterMultipleBuses2() throws Exception {
|
||||
// integrated IM configuration in bus
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/jmx/JMXManagedComponentManagerTest.java b/rt/management/src/test/java/org/apache/cxf/management/jmx/JMXManagedComponentManagerTest.java
|
||||
index d516da39c06..20a7b091435 100644
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/jmx/JMXManagedComponentManagerTest.java
|
||||
+++ b/rt/management/src/test/java/org/apache/cxf/management/jmx/JMXManagedComponentManagerTest.java
|
||||
@@ -28,7 +28,6 @@
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.cxf.management.jmx.export.AnnotationTestInstrumentation;
|
||||
-import org.apache.cxf.testutil.common.TestUtil;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -38,17 +37,13 @@
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class JMXManagedComponentManagerTest {
|
||||
- private static final String PORT = TestUtil.getPortNumber(JMXManagedComponentManagerTest.class);
|
||||
private static final String NAME_ATTRIBUTE = "Name";
|
||||
private InstrumentationManagerImpl manager;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
manager = new InstrumentationManagerImpl();
|
||||
- manager.setDaemon(false);
|
||||
- manager.setThreaded(true);
|
||||
manager.setEnabled(true);
|
||||
- manager.setJMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + PORT + "/jmxrmi");
|
||||
manager.init();
|
||||
//Wait for MBeanServer connector to be initialized on separate thread.
|
||||
Thread.sleep(2000);
|
||||
@@ -61,10 +56,6 @@ public void tearDown() throws Exception {
|
||||
|
||||
@Test
|
||||
public void testRegisterInstrumentation() throws Exception {
|
||||
- //manager.setDaemon(false);
|
||||
- //manager.setThreaded(false);
|
||||
- //manager.setJMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi");
|
||||
- //manager.init();
|
||||
|
||||
AnnotationTestInstrumentation im = new AnnotationTestInstrumentation();
|
||||
ObjectName name = new ObjectName("org.apache.cxf:type=foo,name=bar");
|
||||
@@ -128,13 +119,7 @@ public void testBusLifecycleListener() throws Exception {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
|
||||
this.manager = new InstrumentationManagerImpl();
|
||||
- this.manager.setDaemon(false);
|
||||
- // Turn threading off so that we get the exception in this thread
|
||||
- // and the manager is set into a failed state if the connector
|
||||
- // cannot be created.
|
||||
- this.manager.setThreaded(false);
|
||||
this.manager.setEnabled(true);
|
||||
- this.manager.setJMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + PORT + "/jmxrmi");
|
||||
this.manager.setServer(server);
|
||||
this.manager.init();
|
||||
|
||||
@@ -161,13 +146,7 @@ public void testBusLifecycleListener() throws Exception {
|
||||
}
|
||||
|
||||
this.manager = new InstrumentationManagerImpl();
|
||||
- this.manager.setDaemon(false);
|
||||
- // Turn threading off so that we get the exception in this thread
|
||||
- // and the manager is set into a failed state if the connector
|
||||
- // cannot be created.
|
||||
- this.manager.setThreaded(false);
|
||||
this.manager.setEnabled(true);
|
||||
- this.manager.setJMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:" + PORT + "/jmxrmi");
|
||||
this.manager.setServer(server);
|
||||
this.manager.init();
|
||||
|
||||
@@ -183,4 +162,4 @@ private ObjectName registerStandardMBean(String name) throws Exception {
|
||||
this.manager.register(hw, oName);
|
||||
return oName;
|
||||
}
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorFactoryTest.java b/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorFactoryTest.java
|
||||
deleted file mode 100644
|
||||
index 468ec0cbfaf..00000000000
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorFactoryTest.java
|
||||
+++ /dev/null
|
||||
@@ -1,55 +0,0 @@
|
||||
-/**
|
||||
- * 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.cxf.management.jmx;
|
||||
-
|
||||
-import javax.management.remote.JMXServiceURL;
|
||||
-
|
||||
-import org.junit.Assert;
|
||||
-import org.junit.Test;
|
||||
-
|
||||
-
|
||||
-public class MBServerConnectorFactoryTest {
|
||||
-
|
||||
- @Test
|
||||
- public void testGetServerPort() throws Exception {
|
||||
- Assert.assertEquals(9914, MBServerConnectorFactory.getServerPort(
|
||||
- "service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"));
|
||||
-
|
||||
- Assert.assertEquals(10002, MBServerConnectorFactory.getServerPort(
|
||||
- "service:jmx:rmi://localhost:10002/jndi/rmi://localhost:10001/jmxrmi"));
|
||||
- }
|
||||
-
|
||||
- @Test
|
||||
- public void testGetRegistryPort() throws Exception {
|
||||
- Assert.assertEquals(9914, MBServerConnectorFactory.getRegistryPort(
|
||||
- "service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"));
|
||||
-
|
||||
- Assert.assertEquals(10001, MBServerConnectorFactory.getRegistryPort(
|
||||
- "service:jmx:rmi://localhost:10002/jndi/rmi://localhost:10001/jmxrmi"));
|
||||
- }
|
||||
-
|
||||
- @Test
|
||||
- public void testGetBindingName() throws Exception {
|
||||
- Assert.assertEquals("jmxrmi", MBServerConnectorFactory.getBindingName(
|
||||
- new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi")));
|
||||
-
|
||||
- Assert.assertEquals("cxf-jmxrmi", MBServerConnectorFactory.getBindingName(
|
||||
- new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9913/cxf-jmxrmi")));
|
||||
- }
|
||||
-}
|
||||
\ No newline at end of file
|
||||
diff --git a/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorTest.java b/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorTest.java
|
||||
deleted file mode 100644
|
||||
index c01e10fc6f2..00000000000
|
||||
--- a/rt/management/src/test/java/org/apache/cxf/management/jmx/MBServerConnectorTest.java
|
||||
+++ /dev/null
|
||||
@@ -1,57 +0,0 @@
|
||||
-/**
|
||||
- * 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.cxf.management.jmx;
|
||||
-
|
||||
-
|
||||
-
|
||||
-import javax.management.MBeanServer;
|
||||
-import javax.management.MBeanServerFactory;
|
||||
-
|
||||
-import org.apache.cxf.testutil.common.TestUtil;
|
||||
-
|
||||
-import org.junit.Test;
|
||||
-
|
||||
-import static org.junit.Assert.fail;
|
||||
-
|
||||
-
|
||||
-public class MBServerConnectorTest {
|
||||
- private static final String PORT = TestUtil.getPortNumber(MBServerConnectorTest.class);
|
||||
-
|
||||
- @Test
|
||||
- public void testMBServerConnector() {
|
||||
- MBServerConnectorFactory mcf;
|
||||
- MBeanServer mbs;
|
||||
- mbs = MBeanServerFactory.createMBeanServer("test");
|
||||
- mcf = MBServerConnectorFactory.getInstance();
|
||||
- mcf.setMBeanServer(mbs);
|
||||
- mcf.setThreaded(true);
|
||||
- mcf.setDaemon(true);
|
||||
- mcf.setServiceUrl("service:jmx:rmi:///jndi/rmi://localhost:" + PORT + "/jmxrmi");
|
||||
- try {
|
||||
- mcf.createConnector();
|
||||
- Thread.sleep(1000);
|
||||
- mcf.destroy();
|
||||
- } catch (Exception ex) {
|
||||
- ex.printStackTrace();
|
||||
- fail("Some Exception happened to MBServerConnectorTest");
|
||||
- }
|
||||
- }
|
||||
-
|
||||
-}
|
||||
diff --git a/rt/management/src/test/resources/managed-spring.xml b/rt/management/src/test/resources/managed-spring.xml
|
||||
index 81808a54a5a..683c1b3ab32 100644
|
||||
--- a/rt/management/src/test/resources/managed-spring.xml
|
||||
+++ b/rt/management/src/test/resources/managed-spring.xml
|
||||
@@ -24,11 +24,7 @@
|
||||
xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
<cxf:bus id="CXF-Test-Bus" bus="cxf"/>
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
- <property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="threaded" value="false"/>
|
||||
- <property name="daemon" value="false"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
</bean>
|
||||
<cxf:workqueue name="default" highWaterMark="15" lowWaterMark="5"/>
|
||||
<cxf:workqueue name="test-wq" highWaterMark="10" lowWaterMark="2"/>
|
||||
diff --git a/rt/management/src/test/resources/managed-spring3.xml b/rt/management/src/test/resources/managed-spring3.xml
|
||||
index 83add997fe0..57009b7cf40 100644
|
||||
--- a/rt/management/src/test/resources/managed-spring3.xml
|
||||
+++ b/rt/management/src/test/resources/managed-spring3.xml
|
||||
@@ -26,9 +26,5 @@
|
||||
<!-- the bus setting at the end should not interfer with the other props -->
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="threaded" value="false"/>
|
||||
- <property name="daemon" value="false"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
- <property name="bus" ref="cxf"/>
|
||||
</bean>
|
||||
</beans>
|
||||
\ No newline at end of file
|
||||
diff --git a/rt/management/src/test/resources/no-connector-spring.xml b/rt/management/src/test/resources/no-connector-spring.xml
|
||||
index f6c197d9a2c..565d92dffe0 100644
|
||||
--- a/rt/management/src/test/resources/no-connector-spring.xml
|
||||
+++ b/rt/management/src/test/resources/no-connector-spring.xml
|
||||
@@ -24,6 +24,5 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="createMBServerConnectorFactory" value="false"/>
|
||||
</bean>
|
||||
</beans>
|
||||
\ No newline at end of file
|
||||
diff --git a/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/managed-manager-bean.xml b/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/managed-manager-bean.xml
|
||||
index 8e01539b360..7571a48693d 100644
|
||||
--- a/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/managed-manager-bean.xml
|
||||
+++ b/rt/ws/rm/src/test/java/org/apache/cxf/ws/rm/managed-manager-bean.xml
|
||||
@@ -26,9 +26,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="threaded" value="false"/>
|
||||
- <property name="daemon" value="false"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
</bean>
|
||||
<cxf:bus>
|
||||
<cxf:features>
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/ManagedBusTest.java b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/ManagedBusTest.java
|
||||
index dbde562570a..a40c61d394c 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/ManagedBusTest.java
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/ManagedBusTest.java
|
||||
@@ -98,8 +98,6 @@ public void testManagedSpringBus() throws Exception {
|
||||
assertNotNull(im);
|
||||
|
||||
InstrumentationManagerImpl imi = (InstrumentationManagerImpl)im;
|
||||
- assertEquals("service:jmx:rmi:///jndi/rmi://localhost:9913/jmxrmi",
|
||||
- imi.getJMXServiceURL());
|
||||
assertFalse(imi.isEnabled());
|
||||
assertNull(imi.getMBeanServer());
|
||||
|
||||
@@ -127,8 +125,6 @@ private void doManagedBusTest(Bus bus, String expect, String reject, int port) t
|
||||
InstrumentationManager im = bus.getExtension(InstrumentationManager.class);
|
||||
assertNotNull(im);
|
||||
InstrumentationManagerImpl imi = (InstrumentationManagerImpl)im;
|
||||
- assertEquals("service:jmx:rmi:///jndi/rmi://localhost:" + port + "/jmxrmi",
|
||||
- imi.getJMXServiceURL());
|
||||
assertTrue(imi.isEnabled());
|
||||
assertNotNull(imi.getMBeanServer());
|
||||
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/counter-spring.xml b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/counter-spring.xml
|
||||
index e5cc90f9a17..b3d516022d9 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/counter-spring.xml
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/counter-spring.xml
|
||||
@@ -24,7 +24,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:${testutil.ports.CountersClientServerTest.1}/jmxrmi"/>
|
||||
</bean>
|
||||
<bean id="org.apache.cxf.management.counters.CounterRepository" class="org.apache.cxf.management.counters.CounterRepository">
|
||||
<property name="bus" ref="cxf"/>
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-bus.xml b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-bus.xml
|
||||
index 7304a399d39..fed391b4a60 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-bus.xml
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-bus.xml
|
||||
@@ -24,7 +24,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:${testutil.ports.ManagedBusTest.1}/jmxrmi"/>
|
||||
</bean>
|
||||
<bean id="wq" class="org.apache.cxf.workqueue.AutomaticWorkQueueImpl">
|
||||
<property name="name" value="testQueue"/>
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-spring.xml b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-spring.xml
|
||||
index 4beb120a457..fed391b4a60 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-spring.xml
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/managed-spring.xml
|
||||
@@ -24,7 +24,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:${testutil.ports.ManagedClientServerTest.1}/jmxrmi"/>
|
||||
</bean>
|
||||
<bean id="wq" class="org.apache.cxf.workqueue.AutomaticWorkQueueImpl">
|
||||
<property name="name" value="testQueue"/>
|
||||
diff --git a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/persistent-id.xml b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/persistent-id.xml
|
||||
index 118abfe7978..9219b56bcf3 100644
|
||||
--- a/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/persistent-id.xml
|
||||
+++ b/systests/uncategorized/src/test/java/org/apache/cxf/systest/management/persistent-id.xml
|
||||
@@ -24,7 +24,6 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:${testutil.ports.ManagedBusTest.3}/jmxrmi"/>
|
||||
<property name="persistentBusId" value="cxf:managed,bus=test"/>
|
||||
</bean>
|
||||
<bean id="wq" class="org.apache.cxf.workqueue.AutomaticWorkQueueImpl">
|
||||
diff --git a/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-client.xml b/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-client.xml
|
||||
index c0cd5b2700a..514038f02b8 100644
|
||||
--- a/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-client.xml
|
||||
+++ b/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-client.xml
|
||||
@@ -43,7 +43,5 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="createMBServerConnectorFactory" value="false"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
</bean>
|
||||
-</beans>
|
||||
\ No newline at end of file
|
||||
+</beans>
|
||||
diff --git a/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-server.xml b/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-server.xml
|
||||
index 823d8f0622e..1ee90cfbae4 100644
|
||||
--- a/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-server.xml
|
||||
+++ b/systests/ws-rm/src/test/java/org/apache/cxf/systest/ws/rm/managed-server.xml
|
||||
@@ -43,6 +43,5 @@
|
||||
<bean id="org.apache.cxf.management.InstrumentationManager" class="org.apache.cxf.management.jmx.InstrumentationManagerImpl">
|
||||
<property name="bus" ref="cxf"/>
|
||||
<property name="enabled" value="true"/>
|
||||
- <property name="JMXServiceURL" value="service:jmx:rmi:///jndi/rmi://localhost:9914/jmxrmi"/>
|
||||
</bean>
|
||||
-</beans>
|
||||
\ No newline at end of file
|
||||
+</beans>
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
diff -r fcd3ed3394f6 -r 135bdcb88b8d coders/wpg.c
|
||||
--- a/coders/wpg.c Sun Nov 05 01:11:09 2017 +0100
|
||||
+++ b/coders/wpg.c Sun Nov 05 01:35:28 2017 +0100
|
||||
@@ -340,12 +340,15 @@
|
||||
|
||||
|
||||
if(RetVal==MagickFail)
|
||||
+ {
|
||||
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"ImportImagePixelArea failed for row: %ld, bpp: %d", y, bpp);
|
||||
+ return MagickFail;
|
||||
+ }
|
||||
|
||||
- if (!SyncImagePixels(image))
|
||||
+ if(!SyncImagePixels(image))
|
||||
{
|
||||
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"SyncImagePixels failed for row: %ld, bpp: %d", y, bpp);
|
||||
- RetVal = MagickFail;
|
||||
+ return MagickFail;
|
||||
}
|
||||
|
||||
return RetVal;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
Index: src/java/test/org/apache/zookeeper/test/ACLTest.java
|
||||
===================================================================
|
||||
--- src/java/test/org/apache/zookeeper/test/ACLTest.java (revision 1510080)
|
||||
+++ src/java/test/org/apache/zookeeper/test/ACLTest.java (working copy)
|
||||
@@ -28,6 +28,7 @@
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.apache.zookeeper.CreateMode;
|
||||
+import org.apache.zookeeper.KeeperException;
|
||||
import org.apache.zookeeper.PortAssignment;
|
||||
import org.apache.zookeeper.WatchedEvent;
|
||||
import org.apache.zookeeper.Watcher;
|
||||
@@ -35,8 +36,10 @@
|
||||
import org.apache.zookeeper.ZooKeeper;
|
||||
import org.apache.zookeeper.Watcher.Event.KeeperState;
|
||||
import org.apache.zookeeper.ZooDefs.Ids;
|
||||
+import org.apache.zookeeper.ZooDefs.Perms;
|
||||
import org.apache.zookeeper.data.ACL;
|
||||
import org.apache.zookeeper.data.Id;
|
||||
+import org.apache.zookeeper.data.Stat;
|
||||
import org.apache.zookeeper.server.ServerCnxnFactory;
|
||||
import org.apache.zookeeper.server.SyncRequestProcessor;
|
||||
import org.apache.zookeeper.server.ZooKeeperServer;
|
||||
@@ -77,6 +80,48 @@
|
||||
ClientBase.CONNECTION_TIMEOUT));
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Verify that getAcl should fail when there is not
|
||||
+ * read permission to that node
|
||||
+ */
|
||||
+ @Test
|
||||
+ public void testAclReadPermission() throws Exception {
|
||||
+ File tmpDir = ClientBase.createTmpDir();
|
||||
+ ClientBase.setupTestEnv();
|
||||
+ ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
|
||||
+ SyncRequestProcessor.setSnapCount(1000);
|
||||
+ final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
|
||||
+ ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
|
||||
+ f.startup(zks);
|
||||
+ ZooKeeper zk;
|
||||
+ String path = "/node1";
|
||||
+ boolean readPermLimitWorks = false;
|
||||
+ try {
|
||||
+ LOG.info("starting up the zookeeper server .. waiting");
|
||||
+ Assert.assertTrue("waiting for server being up",
|
||||
+ ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT));
|
||||
+ zk = new ZooKeeper(HOSTPORT, CONNECTION_TIMEOUT, this);
|
||||
+ Id id = new Id("ip", "127.0.0.1");
|
||||
+ ArrayList<ACL> acl = new ArrayList<ACL>(); // Not set read permission
|
||||
+ acl.add(new ACL(Perms.CREATE, id));
|
||||
+ acl.add(new ACL(Perms.DELETE, id));
|
||||
+ acl.add(new ACL(Perms.WRITE, id));
|
||||
+ acl.add(new ACL(Perms.ADMIN, id));
|
||||
+ zk.create(path, path.getBytes(), acl, CreateMode.PERSISTENT);
|
||||
+ Stat stat = new Stat();
|
||||
+ zk.getACL(path, stat); // Should cause exception without read permission
|
||||
+ } catch (KeeperException.NoAuthException e) {
|
||||
+ readPermLimitWorks = true;
|
||||
+ } finally {
|
||||
+ f.shutdown();
|
||||
+ Assert.assertTrue("waiting for server down",
|
||||
+ ClientBase.waitForServerDown(HOSTPORT, CONNECTION_TIMEOUT));
|
||||
+ }
|
||||
+ if (!readPermLimitWorks) {
|
||||
+ Assert.fail("Should not reach here as ACL has no read permission");
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/**
|
||||
* Verify that acl optimization of storing just
|
||||
Index: src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java
|
||||
===================================================================
|
||||
--- src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java (revision 1510080)
|
||||
+++ src/java/main/org/apache/zookeeper/server/FinalRequestProcessor.java (working copy)
|
||||
@@ -324,6 +324,17 @@
|
||||
GetACLRequest getACLRequest = new GetACLRequest();
|
||||
ByteBufferInputStream.byteBuffer2Record(request.request,
|
||||
getACLRequest);
|
||||
+ DataNode n = zks.getZKDatabase().getNode(getACLRequest.getPath());
|
||||
+ if (n == null) {
|
||||
+ throw new KeeperException.NoNodeException();
|
||||
+ }
|
||||
+ Long aclL;
|
||||
+ synchronized(n) {
|
||||
+ aclL = n.acl;
|
||||
+ }
|
||||
+ PrepRequestProcessor.checkACL(zks, zks.getZKDatabase().convertLong(aclL),
|
||||
+ ZooDefs.Perms.READ,
|
||||
+ request.authInfo);
|
||||
Stat stat = new Stat();
|
||||
List<ACL> acl =
|
||||
zks.getZKDatabase().getACL(getACLRequest.getPath(), stat);
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a.txt
|
||||
+++ a1.txt
|
||||
@@ -8,7 +8,7 @@
|
||||
<Setting>
|
||||
<Setting a>
|
||||
<setting b>
|
||||
- <value>23</value>
|
||||
+ <value>24</value>
|
||||
</setting b>
|
||||
<setting c>
|
||||
<value>1</value>
|
||||
@@ -1,7 +1,7 @@
|
||||
handlers=java.util.logging.ConsoleHandler
|
||||
|
||||
.level=INFO
|
||||
com.github.difflib.unifieddiff.level=FINE
|
||||
com.github.difflib.unifieddiff.level=INFO
|
||||
|
||||
java.util.logging.ConsoleHandler.level=INFO
|
||||
#java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
|
||||
6
pom.xml
6
pom.xml
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>io.github.java-diff-utils</groupId>
|
||||
<artifactId>java-diff-utils-parent</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.12</version>
|
||||
<name>java-diff-utils-parent</name>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
@@ -29,7 +29,7 @@
|
||||
<connection>scm:git:https://github.com/java-diff-utils/java-diff-utils.git</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com:java-diff-utils/java-diff-utils.git</developerConnection>
|
||||
<url>https://github.com/java-diff-utils/java-diff-utils.git</url>
|
||||
<tag>java-diff-utils-parent-4.10</tag>
|
||||
<tag>java-diff-utils-parent-4.12</tag>
|
||||
</scm>
|
||||
<issueManagement>
|
||||
<system>GitHub Issues</system>
|
||||
@@ -199,7 +199,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
|
||||
Reference in New Issue
Block a user