Removed duplicate code from Spring and Roo
This commit is contained in:
committed by
Mark Pollack
parent
7acc0db4de
commit
8620061363
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -22,25 +22,26 @@ import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.shell.core.AbstractShell;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@Component
|
||||
public class ResourceBundleHintOperations implements HintOperations {
|
||||
|
||||
private static ResourceBundle bundle = ResourceBundle.getBundle(HintCommands.class.getName());
|
||||
|
||||
|
||||
public String hint(String topic) {
|
||||
if (StringUtils.isBlank(topic)) {
|
||||
if (!StringUtils.hasText(topic)) {
|
||||
topic = determineTopic();
|
||||
}
|
||||
try {
|
||||
String message = bundle.getString(topic);
|
||||
return message.replace("\r", StringUtils.LINE_SEPARATOR).replace("${completion_key}", AbstractShell.completionKeys);
|
||||
return message.replace("\r", OsUtils.LINE_SEPARATOR).replace("${completion_key}", AbstractShell.completionKeys);
|
||||
} catch (MissingResourceException exception) {
|
||||
return "Cannot find topic '" + topic + "'";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public SortedSet<String> getCurrentTopics() {
|
||||
@@ -56,7 +57,7 @@ public class ResourceBundleHintOperations implements HintOperations {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private String determineTopic() {
|
||||
return "start";
|
||||
//return "general";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -21,8 +21,8 @@ import java.util.List;
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.FileUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Converter} for {@link File}.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -24,8 +24,8 @@ import java.util.Map;
|
||||
import org.springframework.shell.core.Completion;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.core.MethodTarget;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A simple {@link Converter} for those classes which provide public static fields to represent possible
|
||||
@@ -60,7 +60,7 @@ public class StaticFieldConverterImpl implements StaticFieldConverter {
|
||||
}
|
||||
|
||||
public Object convertFromText(final String value, final Class<?> requiredType, final String optionContext) {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
Map<String,Field> ffields = fields.get(requiredType);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.shell.core;
|
||||
|
||||
import static org.springframework.shell.support.util.StringUtils.LINE_SEPARATOR;
|
||||
import static org.springframework.shell.support.util.OsUtils.LINE_SEPARATOR;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
@@ -43,11 +43,11 @@ import org.springframework.shell.event.ParseResult;
|
||||
import org.springframework.shell.event.ShellStatus;
|
||||
import org.springframework.shell.event.ShellStatus.Status;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.IOUtils;
|
||||
import org.springframework.shell.support.util.MathUtils;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.shell.support.util.VersionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Provides a base {@link Shell} implementation.
|
||||
@@ -58,7 +58,7 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
|
||||
|
||||
// Constants
|
||||
private static final String MY_SLOT = AbstractShell.class.getName();
|
||||
|
||||
|
||||
//TODO Abstract out to make configurable.
|
||||
protected static final String ROO_PROMPT = "spring> ";
|
||||
|
||||
@@ -74,7 +74,7 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
|
||||
|
||||
/**
|
||||
* Returns any classpath resources with the given path
|
||||
*
|
||||
*
|
||||
* @param path the path for which to search (never null)
|
||||
* @return <code>null</code> if the search can't be performed
|
||||
* @since 1.2.0
|
||||
@@ -89,7 +89,7 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
|
||||
|
||||
@CliCommand(value = { "script" }, help = "Parses the specified resource file and executes its commands")
|
||||
public void script(
|
||||
@CliOption(key = { "", "file" }, help = "The file to locate and execute", mandatory = true) final File script,
|
||||
@CliOption(key = { "", "file" }, help = "The file to locate and execute", mandatory = true) final File script,
|
||||
@CliOption(key = "lineNumbers", mandatory = false, specifiedDefaultValue = "true", unspecifiedDefaultValue = "false", help = "Display line numbers when executing the script") final boolean lineNumbers) {
|
||||
|
||||
Assert.notNull(script, "Script file to parse is required");
|
||||
@@ -129,7 +129,7 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
|
||||
|
||||
/**
|
||||
* Opens the given script for reading
|
||||
*
|
||||
*
|
||||
* @param script the script to read (required)
|
||||
* @return a non-<code>null</code> input stream
|
||||
*/
|
||||
@@ -301,7 +301,7 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
|
||||
|
||||
/**
|
||||
* Default implementation of {@link Shell#setPromptPath(String, boolean))} method to satisfy STS compatibility.
|
||||
*
|
||||
*
|
||||
* @param path to set (can be null or empty)
|
||||
* @param overrideStyle
|
||||
*/
|
||||
@@ -460,15 +460,15 @@ public abstract class AbstractShell extends AbstractShellStatusPublisher impleme
|
||||
logger.log(level, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles the result of execution of a command. Given <i>result</i> is
|
||||
* expected to be not <code>null</code>. If <i>result</i> is a
|
||||
* {@link java.lang.Iterable} object, it will be iterated through to print
|
||||
* the output of <i>toString</i>. For other type of objects, simply output
|
||||
* the output of <i>toString</i>. For other type of objects, simply output
|
||||
* of <i>toString</i> is shown. Subclasses can alter this implementation
|
||||
* to handle the <i>result</i> differently.
|
||||
*
|
||||
*
|
||||
* @param result not <code>null</code> result of execution of a command.
|
||||
*/
|
||||
protected void handleExecutionResult(Object result) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -16,7 +16,7 @@
|
||||
package org.springframework.shell.core;
|
||||
|
||||
import org.springframework.shell.support.util.AnsiEscapeCode;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class Completion {
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -20,7 +20,7 @@ import java.util.List;
|
||||
|
||||
import jline.Completor;
|
||||
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An implementation of JLine's {@link Completor} interface that delegates to a {@link Parser}.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.shell.core;
|
||||
|
||||
import static org.springframework.shell.support.util.OsUtils.LINE_SEPARATOR;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.logging.Formatter;
|
||||
@@ -25,10 +27,9 @@ import java.util.logging.LogRecord;
|
||||
import jline.ANSIBuffer;
|
||||
import jline.ConsoleReader;
|
||||
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.IOUtils;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* JDK logging {@link Handler} that emits log messages to a JLine {@link ConsoleReader}.
|
||||
@@ -67,7 +68,7 @@ public class JLineLogHandler extends Handler {
|
||||
public String format(final LogRecord record) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
if (record.getMessage() != null) {
|
||||
sb.append(record.getMessage()).append(StringUtils.LINE_SEPARATOR);
|
||||
sb.append(record.getMessage()).append(LINE_SEPARATOR);
|
||||
}
|
||||
if (record.getThrown() != null) {
|
||||
PrintWriter pw = null;
|
||||
@@ -173,7 +174,7 @@ public class JLineLogHandler extends Handler {
|
||||
lineSeparatorAndIndentingString.append(" ");
|
||||
}
|
||||
|
||||
eventString = " " + getFormatter().format(event).replace(StringUtils.LINE_SEPARATOR, StringUtils.LINE_SEPARATOR + lineSeparatorAndIndentingString.toString());
|
||||
eventString = " " + getFormatter().format(event).replace(LINE_SEPARATOR, LINE_SEPARATOR + lineSeparatorAndIndentingString.toString());
|
||||
if (eventString.endsWith(lineSeparatorAndIndentingString.toString())) {
|
||||
eventString = eventString.substring(0, eventString.length() - lineSeparatorAndIndentingString.length());
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -46,13 +46,13 @@ import org.apache.commons.io.input.ReversedLinesFileReader;
|
||||
import org.springframework.shell.event.ShellStatus;
|
||||
import org.springframework.shell.event.ShellStatus.Status;
|
||||
import org.springframework.shell.event.ShellStatusListener;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.ClassUtils;
|
||||
import org.springframework.shell.support.util.IOUtils;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.shell.support.util.VersionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
@@ -93,7 +93,7 @@ public abstract class JLineShell extends AbstractShell implements CommandMarker,
|
||||
|
||||
public void run() {
|
||||
reader = createConsoleReader();
|
||||
|
||||
|
||||
setPromptPath(null);
|
||||
|
||||
JLineLogHandler handler = new JLineLogHandler(reader, this);
|
||||
@@ -161,12 +161,12 @@ public abstract class JLineShell extends AbstractShell implements CommandMarker,
|
||||
}
|
||||
|
||||
/**
|
||||
* read history commands from history log. the history size if determined by --histsize options.
|
||||
*
|
||||
* read history commands from history log. the history size if determined by --histsize options.
|
||||
*
|
||||
* @return history commands
|
||||
*/
|
||||
private String[] filterLogEntry() {
|
||||
ArrayList<String> entries = new ArrayList<String>();
|
||||
ArrayList<String> entries = new ArrayList<String>();
|
||||
try {
|
||||
ReversedLinesFileReader reader = new ReversedLinesFileReader(
|
||||
new File(getHistoryFileName()),4096,Charset.forName("UTF-8"));
|
||||
@@ -189,13 +189,13 @@ public abstract class JLineShell extends AbstractShell implements CommandMarker,
|
||||
Collections.reverse(entries);
|
||||
return entries.toArray(new String[0]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates new jline ConsoleReader. On Windows if jansi is available, uses
|
||||
* Creates new jline ConsoleReader. On Windows if jansi is available, uses
|
||||
* createAnsiWindowsReader(). Otherwise, always creates a default ConsoleReader.
|
||||
* Sub-classes of this class can plug in their version of ConsoleReader
|
||||
* by overriding this method, if required.
|
||||
*
|
||||
* Sub-classes of this class can plug in their version of ConsoleReader
|
||||
* by overriding this method, if required.
|
||||
*
|
||||
* @return a jline ConsoleReader instance
|
||||
*/
|
||||
protected ConsoleReader createConsoleReader() {
|
||||
@@ -340,7 +340,7 @@ public abstract class JLineShell extends AbstractShell implements CommandMarker,
|
||||
if (Shell.WINDOW_TITLE_SLOT.equals(slot)) {
|
||||
if (reader != null && reader.getTerminal().isANSISupported()) {
|
||||
// We can probably update the window title, as requested
|
||||
if (StringUtils.isBlank(message)) {
|
||||
if (!StringUtils.hasText(message)) {
|
||||
System.out.println("No text");
|
||||
}
|
||||
|
||||
@@ -573,31 +573,31 @@ public abstract class JLineShell extends AbstractShell implements CommandMarker,
|
||||
}
|
||||
|
||||
/**
|
||||
* get history file name from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
*
|
||||
* @return history file name
|
||||
* get history file name from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
*
|
||||
* @return history file name
|
||||
*/
|
||||
abstract protected String getHistoryFileName();
|
||||
|
||||
/**
|
||||
* get prompt text from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
*
|
||||
* get prompt text from provider. The provider has highest order
|
||||
* <link>org.springframework.core.Ordered.getOder</link> will win.
|
||||
*
|
||||
* @return prompt text
|
||||
*/
|
||||
abstract protected String getPromptText();
|
||||
|
||||
|
||||
/**
|
||||
* get product name
|
||||
*
|
||||
*
|
||||
* @return Product Name
|
||||
*/
|
||||
abstract protected String getProductName();
|
||||
|
||||
|
||||
/**
|
||||
* get version information
|
||||
*
|
||||
*
|
||||
* @return Version
|
||||
*/
|
||||
protected String getVersion() {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -17,10 +17,10 @@ package org.springframework.shell.core;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.shell.support.style.ToStringCreator;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.ObjectUtils;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A method that can be executed via a shell command.
|
||||
@@ -36,7 +36,7 @@ public class MethodTarget {
|
||||
private final Object target;
|
||||
private final String remainingBuffer;
|
||||
private final String key;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for a <code>null remainingBuffer</code> and <code>key</code>
|
||||
*
|
||||
@@ -60,9 +60,9 @@ public class MethodTarget {
|
||||
public MethodTarget(final Method method, final Object target, final String remainingBuffer, final String key) {
|
||||
Assert.notNull(method, "Method is required");
|
||||
Assert.notNull(target, "Target is required");
|
||||
this.key = StringUtils.trimToEmpty(key);
|
||||
this.key = StringUtils.trimWhitespace(key);
|
||||
this.method = method;
|
||||
this.remainingBuffer = StringUtils.trimToEmpty(remainingBuffer);
|
||||
this.remainingBuffer = StringUtils.trimWhitespace(remainingBuffer);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@@ -77,10 +77,10 @@ public class MethodTarget {
|
||||
final MethodTarget otherMethodTarget = (MethodTarget) other;
|
||||
return this.method.equals(otherMethodTarget.getMethod()) && this.target.equals(otherMethodTarget.getTarget());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(method, target);
|
||||
return ObjectUtils.nullSafeHashCode(method) + ObjectUtils.nullSafeHashCode(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -18,7 +18,7 @@ package org.springframework.shell.core;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utilities for parsing.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -19,14 +19,14 @@ import java.util.logging.Logger;
|
||||
|
||||
import org.springframework.shell.event.ParseResult;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.ReflectionUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Simple execution strategy for invoking a target method.
|
||||
* Supports pre/post processing to allow {@link CommandMarker}s for aop-like behavior (
|
||||
* typically used for controlling stateful objects).
|
||||
*
|
||||
* typically used for controlling stateful objects).
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Costin Leau
|
||||
*/
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -15,10 +15,6 @@
|
||||
*/
|
||||
package org.springframework.shell.core;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
@@ -30,36 +26,21 @@ import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.transform.Transformer;
|
||||
|
||||
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.shell.event.ParseResult;
|
||||
import org.springframework.shell.support.logging.HandlerUtils;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.CollectionUtils;
|
||||
import org.springframework.shell.support.util.ExceptionUtils;
|
||||
import org.springframework.shell.support.util.FileCopyUtils;
|
||||
import org.springframework.shell.support.util.NaturalOrderComparator;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.shell.support.util.VersionUtils;
|
||||
import org.springframework.shell.support.util.XmlElementBuilder;
|
||||
import org.springframework.shell.support.util.XmlUtils;
|
||||
import org.w3c.dom.CDATASection;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link Parser}.
|
||||
@@ -84,9 +65,9 @@ public class SimpleParser implements Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* get all mandatory options keys. For the options with multiple keys, the
|
||||
* get all mandatory options keys. For the options with multiple keys, the
|
||||
* keys will be in one row.
|
||||
*
|
||||
*
|
||||
* @param cliOptions options
|
||||
* @return mandatory options keys
|
||||
*/
|
||||
@@ -96,7 +77,7 @@ public class SimpleParser implements Parser {
|
||||
|
||||
/**
|
||||
* get all options key.
|
||||
*
|
||||
*
|
||||
* @param cliOptions
|
||||
* @param includeOptionalOptions
|
||||
* @return options keys
|
||||
@@ -129,7 +110,7 @@ public class SimpleParser implements Parser {
|
||||
if (matchingTargets.isEmpty()) {
|
||||
// Before we just give up, let's see if we can offer a more informative message to the user
|
||||
// by seeing the command is simply unavailable at this point in time
|
||||
CollectionUtils.populate(matchingTargets, locateTargets(input, true, false));
|
||||
matchingTargets.addAll(locateTargets(input, true, false));
|
||||
if (matchingTargets.isEmpty()) {
|
||||
commandNotFound(LOGGER, input);
|
||||
}
|
||||
@@ -199,9 +180,9 @@ public class SimpleParser implements Parser {
|
||||
}
|
||||
|
||||
// Ensure the user specified a value if the value is mandatory or
|
||||
// key and value must appear in pair
|
||||
boolean mandatory = StringUtils.isBlank(value) && cliOption.mandatory();
|
||||
boolean specifiedKey = StringUtils.isBlank(value) && options.containsKey(sourcedFrom);
|
||||
// key and value must appear in pair
|
||||
boolean mandatory = !StringUtils.hasText(value) && cliOption.mandatory();
|
||||
boolean specifiedKey = !StringUtils.hasText(value) && options.containsKey(sourcedFrom);
|
||||
boolean specifiedKeyWithoutValue = false;
|
||||
if(specifiedKey){
|
||||
value = cliOption.specifiedDefaultValue();
|
||||
@@ -327,7 +308,7 @@ public class SimpleParser implements Parser {
|
||||
boolean found = false;
|
||||
for (String key : keys) {
|
||||
if (options.containsKey(key)) {
|
||||
if (StringUtils.isBlank(options.get(key))) {
|
||||
if (!StringUtils.hasText(options.get(key))) {
|
||||
valueBuilder.append(key);
|
||||
valueBuilder.append("' for this command");
|
||||
hintForOptions = false;
|
||||
@@ -540,7 +521,7 @@ public class SimpleParser implements Parser {
|
||||
|
||||
// Replace all multiple spaces with a single space
|
||||
while (buffer.contains(" ")) {
|
||||
buffer = StringUtils.replaceFirst(buffer, " ", " ");
|
||||
buffer = buffer.replaceFirst(" ", " ");
|
||||
cursor--;
|
||||
}
|
||||
|
||||
@@ -831,7 +812,7 @@ public class SimpleParser implements Parser {
|
||||
// Only include in the candidates those results which are compatible with the present buffer
|
||||
for (Completion currentValue : allValues) {
|
||||
// We only provide a suggestion if the lastOptionValue == ""
|
||||
if (StringUtils.isBlank(lastOptionValue)) {
|
||||
if (!StringUtils.hasText(lastOptionValue)) {
|
||||
// We should add the result, as they haven't typed anything yet
|
||||
results.add(new Completion(prefix + currentValue.getValue() + suffix,
|
||||
currentValue.getFormattedValue(), currentValue.getHeading(),
|
||||
@@ -851,7 +832,7 @@ public class SimpleParser implements Parser {
|
||||
|
||||
// ROO-389: give inline options given there's multiple choices available and we want to help the user
|
||||
StringBuilder help = new StringBuilder();
|
||||
help.append(StringUtils.LINE_SEPARATOR);
|
||||
help.append(OsUtils.LINE_SEPARATOR);
|
||||
help.append(option.mandatory() ? "required --" : "optional --");
|
||||
if ("".equals(option.help())) {
|
||||
help.append(lastOptionKey).append(": ").append("No help available");
|
||||
@@ -909,7 +890,7 @@ public class SimpleParser implements Parser {
|
||||
|
||||
/**
|
||||
* populate completion for mandatory options
|
||||
*
|
||||
*
|
||||
* @param translated user's input
|
||||
* @param unspecified unspecified options
|
||||
* @param value the option key
|
||||
@@ -935,201 +916,6 @@ public class SimpleParser implements Parser {
|
||||
results.add(new Completion(strBuilder.toString()));
|
||||
}
|
||||
|
||||
public void helpReferenceGuide() {
|
||||
synchronized (mutex) {
|
||||
File f = new File(".");
|
||||
File[] existing = f.listFiles(new FileFilter() {
|
||||
public boolean accept(final File pathname) {
|
||||
return pathname.getName().startsWith("appendix_");
|
||||
}
|
||||
});
|
||||
for (File e : existing) {
|
||||
e.delete();
|
||||
}
|
||||
|
||||
// Compute the sections we'll be outputting, and get them into a nice order
|
||||
SortedMap<String, Object> sections = new TreeMap<String, Object>(COMPARATOR);
|
||||
next_target: for (Object target : commands) {
|
||||
Method[] methods = target.getClass().getMethods();
|
||||
for (Method m : methods) {
|
||||
CliCommand cmd = m.getAnnotation(CliCommand.class);
|
||||
if (cmd != null) {
|
||||
String sectionName = target.getClass().getSimpleName();
|
||||
Pattern p = Pattern.compile("[A-Z][^A-Z]*");
|
||||
Matcher matcher = p.matcher(sectionName);
|
||||
StringBuilder string = new StringBuilder();
|
||||
while (matcher.find()) {
|
||||
string.append(matcher.group()).append(" ");
|
||||
}
|
||||
sectionName = string.toString().trim();
|
||||
if (sections.containsKey(sectionName)) {
|
||||
throw new IllegalStateException("Section name '" + sectionName + "' not unique");
|
||||
}
|
||||
sections.put(sectionName, target);
|
||||
continue next_target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build each section of the appendix
|
||||
DocumentBuilder builder = XmlUtils.getDocumentBuilder();
|
||||
Document document = builder.newDocument();
|
||||
List<Element> builtSections = new ArrayList<Element>();
|
||||
|
||||
for (final Entry<String, Object> entry : sections.entrySet()) {
|
||||
final String section = entry.getKey();
|
||||
final Object target = entry.getValue();
|
||||
SortedMap<String, Element> individualCommands = new TreeMap<String, Element>(COMPARATOR);
|
||||
|
||||
Method[] methods = target.getClass().getMethods();
|
||||
for (Method m : methods) {
|
||||
CliCommand cmd = m.getAnnotation(CliCommand.class);
|
||||
if (cmd != null) {
|
||||
StringBuilder cmdSyntax = new StringBuilder();
|
||||
cmdSyntax.append(cmd.value()[0]);
|
||||
|
||||
// Build the syntax list
|
||||
|
||||
// Store the order options appear
|
||||
List<String> optionKeys = new ArrayList<String>();
|
||||
// key: option key, value: help text
|
||||
Map<String, String> optionDetails = new HashMap<String, String>();
|
||||
for (Annotation[] ann : m.getParameterAnnotations()) {
|
||||
for (Annotation a : ann) {
|
||||
if (a instanceof CliOption) {
|
||||
CliOption option = (CliOption) a;
|
||||
// Figure out which key we want to use (use first non-empty string, or make it "(default)" if needed)
|
||||
String key = option.key()[0];
|
||||
if ("".equals(key)) {
|
||||
for (String otherKey : option.key()) {
|
||||
if (!"".equals(otherKey)) {
|
||||
key = otherKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ("".equals(key)) {
|
||||
key = "[default]";
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder help = new StringBuilder();
|
||||
if ("".equals(option.help())) {
|
||||
help.append("No help available");
|
||||
}
|
||||
else {
|
||||
help.append(option.help());
|
||||
}
|
||||
if (option.specifiedDefaultValue().equals(option.unspecifiedDefaultValue())) {
|
||||
if (option.specifiedDefaultValue().equals("__NULL__")) {
|
||||
help.append("; no default value");
|
||||
}
|
||||
else {
|
||||
help.append("; default: '").append(option.specifiedDefaultValue()).append(
|
||||
"'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!"".equals(option.specifiedDefaultValue())
|
||||
&& !"__NULL__".equals(option.specifiedDefaultValue())) {
|
||||
help.append("; default if option present: '").append(
|
||||
option.specifiedDefaultValue()).append("'");
|
||||
}
|
||||
if (!"".equals(option.unspecifiedDefaultValue())
|
||||
&& !"__NULL__".equals(option.unspecifiedDefaultValue())) {
|
||||
help.append("; default if option not present: '").append(
|
||||
option.unspecifiedDefaultValue()).append("'");
|
||||
}
|
||||
}
|
||||
help.append(option.mandatory() ? " (mandatory) " : "");
|
||||
|
||||
// Store details for later
|
||||
key = "--" + key;
|
||||
optionKeys.add(key);
|
||||
optionDetails.put(key, help.toString());
|
||||
|
||||
// Include it in the mandatory syntax
|
||||
if (option.mandatory()) {
|
||||
cmdSyntax.append(" ").append(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make a variable list element
|
||||
Element variableListElement = document.createElement("variablelist");
|
||||
boolean anyVars = false;
|
||||
for (String optionKey : optionKeys) {
|
||||
anyVars = true;
|
||||
String help = optionDetails.get(optionKey);
|
||||
variableListElement.appendChild(new XmlElementBuilder("varlistentry", document).addChild(
|
||||
new XmlElementBuilder("term", document).setText(optionKey).build()).addChild(
|
||||
new XmlElementBuilder("listitem", document).addChild(
|
||||
new XmlElementBuilder("para", document).setText(help).build()).build()).build());
|
||||
}
|
||||
|
||||
if (!anyVars) {
|
||||
variableListElement = new XmlElementBuilder("para", document).setText(
|
||||
"This command does not accept any options.").build();
|
||||
}
|
||||
|
||||
// Now we've figured out the options, store this individual command
|
||||
CDATASection progList = document.createCDATASection(cmdSyntax.toString());
|
||||
String safeName = cmd.value()[0].replace("\\", "BCK").replace("/", "FWD").replace("*", "ASX");
|
||||
Element element = new XmlElementBuilder("section", document).addAttribute("xml:id",
|
||||
"command-index-" + safeName.toLowerCase().replace(' ', '-')).addChild(
|
||||
new XmlElementBuilder("title", document).setText(cmd.value()[0]).build()).addChild(
|
||||
new XmlElementBuilder("para", document).setText(cmd.help()).build()).addChild(
|
||||
new XmlElementBuilder("programlisting", document).addChild(progList).build()).addChild(
|
||||
variableListElement).build();
|
||||
|
||||
individualCommands.put(cmdSyntax.toString(), element);
|
||||
}
|
||||
}
|
||||
|
||||
Element topSection = document.createElement("section");
|
||||
topSection.setAttribute("xml:id", "command-index-" + section.toLowerCase().replace(' ', '-'));
|
||||
topSection.appendChild(new XmlElementBuilder("title", document).setText(section).build());
|
||||
topSection.appendChild(new XmlElementBuilder("para", document).setText(
|
||||
section + " are contained in " + target.getClass().getName() + ".").build());
|
||||
|
||||
for (final Element value : individualCommands.values()) {
|
||||
topSection.appendChild(value);
|
||||
}
|
||||
|
||||
builtSections.add(topSection);
|
||||
}
|
||||
|
||||
Element appendix = document.createElement("appendix");
|
||||
appendix.setAttribute("xmlns", "http://docbook.org/ns/docbook");
|
||||
appendix.setAttribute("version", "5.0");
|
||||
appendix.setAttribute("xml:id", "command-index");
|
||||
appendix.appendChild(new XmlElementBuilder("title", document).setText("Command Index").build());
|
||||
appendix.appendChild(new XmlElementBuilder("para", document).setText(
|
||||
"This appendix was automatically built from Roo " + VersionUtils.versionInfo() + ".").build());
|
||||
appendix.appendChild(new XmlElementBuilder("para", document).setText(
|
||||
"Commands are listed in alphabetic order, and are shown in monospaced font with any mandatory options you must specify when using the command. Most commands accept a large number of options, and all of the possible options for each command are presented in this appendix.").build());
|
||||
|
||||
for (Element section : builtSections) {
|
||||
appendix.appendChild(section);
|
||||
}
|
||||
document.appendChild(appendix);
|
||||
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
|
||||
Transformer transformer = XmlUtils.createIndentingTransformer();
|
||||
// Causes an "Error reported by XML parser: Multiple notations were used which had the name 'linespecific', but which were not determined to be duplicates." when creating the DocBook
|
||||
// transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//OASIS//DTD DocBook XML V4.5//EN");
|
||||
// transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd");
|
||||
|
||||
XmlUtils.writeXml(transformer, byteArrayOutputStream, document);
|
||||
try {
|
||||
File output = new File(f, "appendix-command-index.xml");
|
||||
FileCopyUtils.copy(byteArrayOutputStream.toByteArray(), output);
|
||||
} catch (IOException ioe) {
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void obtainHelp(@CliOption(key = { "", "command" }, optionContext = "availableCommands", help = "Command name to provide help for") String buffer) {
|
||||
synchronized (mutex) {
|
||||
@@ -1153,10 +939,10 @@ public class SimpleParser implements Parser {
|
||||
Assert.notNull(cmd, "CliCommand not found");
|
||||
|
||||
for (String value : cmd.value()) {
|
||||
sb.append("Keyword: ").append(value).append(StringUtils.LINE_SEPARATOR);
|
||||
sb.append("Keyword: ").append(value).append(OsUtils.LINE_SEPARATOR);
|
||||
}
|
||||
|
||||
sb.append("Description: ").append(cmd.help()).append(StringUtils.LINE_SEPARATOR);
|
||||
sb.append("Description: ").append(cmd.help()).append(OsUtils.LINE_SEPARATOR);
|
||||
|
||||
for (Annotation[] annotations : parameterAnnotations) {
|
||||
CliOption cliOption = null;
|
||||
@@ -1169,18 +955,18 @@ public class SimpleParser implements Parser {
|
||||
key = "** default **";
|
||||
}
|
||||
sb.append(" Keyword: ").append(key).append(
|
||||
StringUtils.LINE_SEPARATOR);
|
||||
OsUtils.LINE_SEPARATOR);
|
||||
}
|
||||
|
||||
sb.append(" Help: ").append(cliOption.help()).append(
|
||||
StringUtils.LINE_SEPARATOR);
|
||||
OsUtils.LINE_SEPARATOR);
|
||||
sb.append(" Mandatory: ").append(cliOption.mandatory()).append(
|
||||
StringUtils.LINE_SEPARATOR);
|
||||
OsUtils.LINE_SEPARATOR);
|
||||
sb.append(" Default if specified: '").append(cliOption.specifiedDefaultValue()).append(
|
||||
"'").append(StringUtils.LINE_SEPARATOR);
|
||||
"'").append(OsUtils.LINE_SEPARATOR);
|
||||
sb.append(" Default if unspecified: '").append(cliOption.unspecifiedDefaultValue()).append(
|
||||
"'").append(StringUtils.LINE_SEPARATOR);
|
||||
sb.append(StringUtils.LINE_SEPARATOR);
|
||||
"'").append(OsUtils.LINE_SEPARATOR);
|
||||
sb.append(OsUtils.LINE_SEPARATOR);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1207,7 +993,7 @@ public class SimpleParser implements Parser {
|
||||
}
|
||||
|
||||
for (String s : result) {
|
||||
sb.append(s).append(StringUtils.LINE_SEPARATOR);
|
||||
sb.append(s).append(OsUtils.LINE_SEPARATOR);
|
||||
}
|
||||
|
||||
LOGGER.info(sb.toString());
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -19,7 +19,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.springframework.shell.event.ShellStatus.Status;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Provides a convenience superclass for those shells wishing to publish status messages.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -18,10 +18,10 @@ package org.springframework.shell.event;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.shell.core.Converter;
|
||||
import org.springframework.shell.support.style.ToStringCreator;
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Immutable representation of the outcome of parsing a given shell line.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -19,14 +19,13 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.shell.plugin.BannerProvider;
|
||||
import org.springframework.shell.support.util.FileUtils;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.shell.support.util.VersionUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.springframework.shell.support.util.StringUtils.*;
|
||||
|
||||
/**
|
||||
* Default Banner provider.
|
||||
*
|
||||
*
|
||||
* @author Jarred Li
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@@ -37,8 +36,8 @@ public class DefaultBannerProvider implements BannerProvider {
|
||||
public String getBanner() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(FileUtils.readBanner(DefaultBannerProvider.class, "banner.txt"));
|
||||
sb.append(getVersion()).append(LINE_SEPARATOR);
|
||||
sb.append(LINE_SEPARATOR);
|
||||
sb.append(getVersion()).append(OsUtils.LINE_SEPARATOR);
|
||||
sb.append(OsUtils.LINE_SEPARATOR);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -22,7 +22,7 @@ import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Defers the publication of JDK {@link LogRecord} instances until a target {@link Handler} is registered.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -24,8 +24,8 @@ import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.shell.support.util.OsUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility methods for dealing with {@link Handler} objects.
|
||||
@@ -90,7 +90,7 @@ public abstract class HandlerUtils {
|
||||
consoleHandler.setFormatter(new Formatter() {
|
||||
@Override
|
||||
public String format(final LogRecord record) {
|
||||
return record.getMessage() + StringUtils.LINE_SEPARATOR;
|
||||
return record.getMessage() + OsUtils.LINE_SEPARATOR;
|
||||
}
|
||||
});
|
||||
newHandlers.add(new DeferredLogHandler(consoleHandler, fallbackSeverity));
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -22,8 +22,8 @@ import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.IOUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Wraps an {@link OutputStream} and automatically passes each line to the {@link Logger}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -21,8 +21,8 @@ import java.io.InputStreamReader;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.springframework.shell.support.util.FileCopyUtils;
|
||||
import org.springframework.shell.support.util.IOUtils;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* Retrieves text files from the classloader and displays them on-screen.
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.style;
|
||||
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
import org.springframework.shell.support.util.ClassUtils;
|
||||
import org.springframework.shell.support.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Spring's default <code>toString()</code> styler.
|
||||
*
|
||||
* <p>This class is used by {@link ToStringCreator} to style <code>toString()</code>
|
||||
* output in a consistent manner according to Spring conventions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.2
|
||||
*/
|
||||
public class DefaultToStringStyler implements ToStringStyler {
|
||||
|
||||
// Fields
|
||||
private final ValueStyler valueStyler;
|
||||
|
||||
/**
|
||||
* Create a new DefaultToStringStyler.
|
||||
* @param valueStyler the ValueStyler to use
|
||||
*/
|
||||
public DefaultToStringStyler(final ValueStyler valueStyler) {
|
||||
Assert.notNull(valueStyler, "ValueStyler must not be null");
|
||||
this.valueStyler = valueStyler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ValueStyler used by this ToStringStyler.
|
||||
*/
|
||||
protected final ValueStyler getValueStyler() {
|
||||
return this.valueStyler;
|
||||
}
|
||||
|
||||
public void styleStart(final StringBuilder buffer, final Object obj) {
|
||||
if (!obj.getClass().isArray()) {
|
||||
buffer.append('[').append(ClassUtils.getShortName(obj.getClass()));
|
||||
styleIdentityHashCode(buffer, obj);
|
||||
}
|
||||
else {
|
||||
buffer.append('[');
|
||||
styleIdentityHashCode(buffer, obj);
|
||||
buffer.append(' ');
|
||||
styleValue(buffer, obj);
|
||||
}
|
||||
}
|
||||
|
||||
private void styleIdentityHashCode(final StringBuilder buffer, final Object obj) {
|
||||
buffer.append('@');
|
||||
buffer.append(ObjectUtils.getIdentityHexString(obj));
|
||||
}
|
||||
|
||||
public void styleEnd(final StringBuilder buffer, final Object o) {
|
||||
buffer.append(']');
|
||||
}
|
||||
|
||||
public void styleField(final StringBuilder buffer, final String fieldName, final Object value) {
|
||||
styleFieldStart(buffer, fieldName);
|
||||
styleValue(buffer, value);
|
||||
styleFieldEnd(buffer, fieldName);
|
||||
}
|
||||
|
||||
protected void styleFieldStart(final StringBuilder buffer, final String fieldName) {
|
||||
buffer.append(' ').append(fieldName).append(" = ");
|
||||
}
|
||||
|
||||
protected void styleFieldEnd(final StringBuilder buffer, final String fieldName) {
|
||||
}
|
||||
|
||||
public void styleValue(final StringBuilder buffer, final Object value) {
|
||||
buffer.append(this.valueStyler.style(value));
|
||||
}
|
||||
|
||||
public void styleFieldSeparator(final StringBuilder buffer) {
|
||||
buffer.append(',');
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.style;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.shell.support.util.ClassUtils;
|
||||
import org.springframework.shell.support.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Converts objects to String form, generally for debugging purposes,
|
||||
* using Spring's <code>toString</code> styling conventions.
|
||||
*
|
||||
* <p>Uses the reflective visitor pattern underneath the hood to nicely
|
||||
* encapsulate styling algorithms for each type of styled object.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.2
|
||||
*/
|
||||
public class DefaultValueStyler implements ValueStyler {
|
||||
private static final String EMPTY = "[empty]";
|
||||
private static final String NULL = "[null]";
|
||||
private static final String COLLECTION = "collection";
|
||||
private static final String SET = "set";
|
||||
private static final String LIST = "list";
|
||||
private static final String MAP = "map";
|
||||
private static final String ARRAY = "array";
|
||||
|
||||
public String style(final Object value) {
|
||||
if (value == null) {
|
||||
return NULL;
|
||||
} else if (value instanceof String) {
|
||||
return "\'" + value + "\'";
|
||||
} else if (value instanceof Class<?>) {
|
||||
return ClassUtils.getShortName((Class<?>) value);
|
||||
} else if (value instanceof Method) {
|
||||
Method method = (Method) value;
|
||||
return method.getName() + "@" + ClassUtils.getShortName(method.getDeclaringClass());
|
||||
} else if (value instanceof Map<?, ?>) {
|
||||
return style((Map<?, ?>) value);
|
||||
} else if (value instanceof Map.Entry<?, ?>) {
|
||||
return style((Map.Entry<?, ?>) value);
|
||||
} else if (value instanceof Collection<?>) {
|
||||
return style((Collection<?>) value);
|
||||
} else if (value.getClass().isArray()) {
|
||||
return styleArray(ObjectUtils.toObjectArray(value));
|
||||
} else {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
}
|
||||
|
||||
private String style(final Map<?, ?> value) {
|
||||
StringBuilder result = new StringBuilder(value.size() * 8 + 16);
|
||||
result.append(MAP + "[");
|
||||
for (Iterator<?> it = value.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next();
|
||||
result.append(style(entry));
|
||||
if (it.hasNext()) {
|
||||
result.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
if (value.isEmpty()) {
|
||||
result.append(EMPTY);
|
||||
}
|
||||
result.append("]");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String style(final Map.Entry<?, ?> value) {
|
||||
return style(value.getKey()) + " -> " + style(value.getValue());
|
||||
}
|
||||
|
||||
private String style(final Collection<?> value) {
|
||||
StringBuilder result = new StringBuilder(value.size() * 8 + 16);
|
||||
result.append(getCollectionTypeString(value)).append('[');
|
||||
for (Iterator<?> i = value.iterator(); i.hasNext();) {
|
||||
result.append(style(i.next()));
|
||||
if (i.hasNext()) {
|
||||
result.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
if (value.isEmpty()) {
|
||||
result.append(EMPTY);
|
||||
}
|
||||
result.append("]");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String getCollectionTypeString(final Collection<?> value) {
|
||||
if (value instanceof List<?>) {
|
||||
return LIST;
|
||||
} else if (value instanceof Set<?>) {
|
||||
return SET;
|
||||
} else {
|
||||
return COLLECTION;
|
||||
}
|
||||
}
|
||||
|
||||
private String styleArray(final Object[] array) {
|
||||
StringBuilder result = new StringBuilder(array.length * 8 + 16);
|
||||
result.append(ARRAY + "<").append(ClassUtils.getShortName(array.getClass().getComponentType())).append(">[");
|
||||
for (int i = 0; i < array.length - 1; i++) {
|
||||
result.append(style(array[i]));
|
||||
result.append(',').append(' ');
|
||||
}
|
||||
if (array.length > 0) {
|
||||
result.append(style(array[array.length - 1]));
|
||||
} else {
|
||||
result.append(EMPTY);
|
||||
}
|
||||
result.append("]");
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.style;
|
||||
|
||||
/**
|
||||
* Simple utility class to allow for convenient access to value
|
||||
* styling logic, mainly to support descriptive logging messages.
|
||||
*
|
||||
* <p>For more sophisticated needs, use the {@link ValueStyler} abstraction
|
||||
* directly. This class simply uses a shared {@link DefaultValueStyler}
|
||||
* instance underneath.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 1.2.2
|
||||
* @see ValueStyler
|
||||
* @see DefaultValueStyler
|
||||
*/
|
||||
public abstract class StylerUtils {
|
||||
|
||||
/**
|
||||
* Default ValueStyler instance used by the <code>style</code> method.
|
||||
* Also available for the {@link ToStringCreator} class in this package.
|
||||
*/
|
||||
static final ValueStyler DEFAULT_VALUE_STYLER = new DefaultValueStyler();
|
||||
|
||||
/**
|
||||
* Style the specified value according to default conventions.
|
||||
* @param value the Object value to style
|
||||
* @return the styled String
|
||||
* @see DefaultValueStyler
|
||||
*/
|
||||
public static String style(final Object value) {
|
||||
return DEFAULT_VALUE_STYLER.style(value);
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.style;
|
||||
|
||||
import org.springframework.shell.support.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility class that builds pretty-printing <code>toString()</code> methods
|
||||
* with pluggable styling conventions. By default, ToStringCreator adheres
|
||||
* to Spring's <code>toString()</code> styling conventions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.2
|
||||
*/
|
||||
public class ToStringCreator {
|
||||
|
||||
/**
|
||||
* Default ToStringStyler instance used by this ToStringCreator.
|
||||
*/
|
||||
private static final ToStringStyler DEFAULT_TO_STRING_STYLER = new DefaultToStringStyler(StylerUtils.DEFAULT_VALUE_STYLER);
|
||||
|
||||
// Fields
|
||||
private final StringBuilder buffer = new StringBuilder(512);
|
||||
private final ToStringStyler styler;
|
||||
private final Object object;
|
||||
|
||||
private boolean styledFirstField;
|
||||
|
||||
/**
|
||||
* Create a ToStringCreator for the given object.
|
||||
*
|
||||
* @param obj the object to be stringified
|
||||
*/
|
||||
public ToStringCreator(final Object obj) {
|
||||
this(obj, (ToStringStyler) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ToStringCreator for the given object, using the provided style.
|
||||
*
|
||||
* @param obj the object to be stringified
|
||||
* @param styler the ValueStyler encapsulating pretty-print instructions
|
||||
*/
|
||||
public ToStringCreator(final Object obj, final ValueStyler styler) {
|
||||
this(obj, new DefaultToStringStyler(styler != null ? styler : StylerUtils.DEFAULT_VALUE_STYLER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ToStringCreator for the given object, using the provided style.
|
||||
*
|
||||
* @param obj the object to be stringified
|
||||
* @param styler the ToStringStyler encapsulating pretty-print instructions
|
||||
*/
|
||||
public ToStringCreator(final Object obj, final ToStringStyler styler) {
|
||||
Assert.notNull(obj, "The object to be styled must not be null");
|
||||
this.object = obj;
|
||||
this.styler = (styler != null ? styler : DEFAULT_TO_STRING_STYLER);
|
||||
this.styler.styleStart(this.buffer, this.object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a byte field value.
|
||||
*
|
||||
* @param fieldName the name of the field, usually the member variable name
|
||||
* @param value the field value
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public ToStringCreator append(final String fieldName, final byte value) {
|
||||
return append(fieldName, Byte.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a short field value.
|
||||
*
|
||||
* @param fieldName the name of the field, usually the member variable name
|
||||
* @param value the field value
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public ToStringCreator append(final String fieldName, final short value) {
|
||||
return append(fieldName, Short.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a integer field value.
|
||||
*
|
||||
* @param fieldName the name of the field, usually the member variable name
|
||||
* @param value the field value
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public ToStringCreator append(final String fieldName, final int value) {
|
||||
return append(fieldName, Integer.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a long field value.
|
||||
*
|
||||
* @param fieldName the name of the field, usually the member variable name
|
||||
* @param value the field value
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public ToStringCreator append(final String fieldName, final long value) {
|
||||
return append(fieldName, Long.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a float field value.
|
||||
*
|
||||
* @param fieldName the name of the field, usually the member variable name
|
||||
* @param value the field value
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public ToStringCreator append(final String fieldName, final float value) {
|
||||
return append(fieldName, new Float(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a double field value.
|
||||
*
|
||||
* @param fieldName the name of the field, usually the member variable name
|
||||
* @param value the field value
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public ToStringCreator append(final String fieldName, final double value) {
|
||||
return append(fieldName, new Double(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a boolean field value.
|
||||
*
|
||||
* @param fieldName the name of the field, usually the member variable name
|
||||
* @param value the field value
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public ToStringCreator append(final String fieldName, final boolean value) {
|
||||
return append(fieldName, Boolean.valueOf(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a field value.
|
||||
*
|
||||
* @param fieldName the name of the field, usually the member variable name
|
||||
* @param value the field value; can be <code>null</code>
|
||||
* @return this, to support call-chaining
|
||||
*/
|
||||
public ToStringCreator append(final String fieldName, final Object value) {
|
||||
printFieldSeparatorIfNecessary();
|
||||
this.styler.styleField(this.buffer, fieldName, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void printFieldSeparatorIfNecessary() {
|
||||
if (this.styledFirstField) {
|
||||
this.styler.styleFieldSeparator(this.buffer);
|
||||
}
|
||||
else {
|
||||
this.styledFirstField = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the provided value.
|
||||
*
|
||||
* @param value The value to append
|
||||
* @return this, to support call-chaining.
|
||||
*/
|
||||
public ToStringCreator append(final Object value) {
|
||||
this.styler.styleValue(this.buffer, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the String representation that this ToStringCreator built.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
this.styler.styleEnd(this.buffer, this.object);
|
||||
return this.buffer.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.style;
|
||||
|
||||
/**
|
||||
* A strategy interface for pretty-printing <code>toString()</code> methods.
|
||||
* Encapsulates the print algorithms; some other object such as a builder
|
||||
* should provide the workflow.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 1.2.2
|
||||
*/
|
||||
public interface ToStringStyler {
|
||||
|
||||
/**
|
||||
* Style a <code>toString()</code>'ed object before its fields are styled.
|
||||
*
|
||||
* @param buffer the buffer to print to
|
||||
* @param obj the object to style; can be <code>null</code>
|
||||
*/
|
||||
void styleStart(StringBuilder buffer, Object obj);
|
||||
|
||||
/**
|
||||
* Style a <code>toString()</code>'ed object after it's fields are styled.
|
||||
*
|
||||
* @param buffer the buffer to print to
|
||||
* @param obj the object to style; can be <code>null</code>
|
||||
*/
|
||||
void styleEnd(StringBuilder buffer, Object obj);
|
||||
|
||||
/**
|
||||
* Style a field value as a string.
|
||||
*
|
||||
* @param buffer the buffer to print to
|
||||
* @param fieldName the he name of the field
|
||||
* @param value the field value; can be <code>null</code>
|
||||
*/
|
||||
void styleField(StringBuilder buffer, String fieldName, Object value);
|
||||
|
||||
/**
|
||||
* Style the given value.
|
||||
*
|
||||
* @param buffer the buffer to print to
|
||||
* @param value the field value; can be <code>null</code>
|
||||
*/
|
||||
void styleValue(StringBuilder buffer, Object value);
|
||||
|
||||
/**
|
||||
* Style the field separator.
|
||||
*
|
||||
* @param buffer buffer to print to
|
||||
*/
|
||||
void styleFieldSeparator(StringBuilder buffer);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.style;
|
||||
|
||||
/**
|
||||
* Strategy that encapsulates value String styling algorithms
|
||||
* according to Spring conventions.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 1.2.2
|
||||
*/
|
||||
public interface ValueStyler {
|
||||
|
||||
/**
|
||||
* Style the given value, returning a String representation.
|
||||
* @param value the Object value to style
|
||||
* @return the styled String
|
||||
*/
|
||||
String style(Object value);
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Package-protected helper class for {@link AntPathMatcher}. Tests whether or not a string matches against a pattern.
|
||||
* The pattern may contain special characters:<br> '*' means zero or more characters<br> '?' means one and only one
|
||||
* character, '{' and '}' indicate a uri template pattern
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
*/
|
||||
class AntPatchStringMatcher {
|
||||
|
||||
// Fields
|
||||
private final char[] patArr;
|
||||
private final char[] strArr;
|
||||
private int patIdxStart = 0;
|
||||
private int patIdxEnd;
|
||||
private int strIdxStart = 0;
|
||||
private int strIdxEnd;
|
||||
private char ch;
|
||||
private final Map<String, String> uriTemplateVariables;
|
||||
|
||||
/** Constructs a new instance of the <code>AntPatchStringMatcher</code>. */
|
||||
AntPatchStringMatcher(final String pattern, final String str, final Map<String, String> uriTemplateVariables) {
|
||||
patArr = pattern.toCharArray();
|
||||
strArr = str.toCharArray();
|
||||
this.uriTemplateVariables = uriTemplateVariables;
|
||||
patIdxEnd = patArr.length - 1;
|
||||
strIdxEnd = strArr.length - 1;
|
||||
}
|
||||
|
||||
private void addTemplateVariable(final int curlyIdxStart, final int curlyIdxEnd, final int valIdxStart, final int valIdxEnd) {
|
||||
if (uriTemplateVariables != null) {
|
||||
String varName = new String(patArr, curlyIdxStart + 1, curlyIdxEnd - curlyIdxStart - 1);
|
||||
String varValue = new String(strArr, valIdxStart, valIdxEnd - valIdxStart + 1);
|
||||
uriTemplateVariables.put(varName, varValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point.
|
||||
*
|
||||
* @return <code>true</code> if the string matches against the pattern, or <code>false</code> otherwise.
|
||||
*/
|
||||
boolean matchStrings() {
|
||||
if (shortcutPossible()) {
|
||||
return doShortcut();
|
||||
}
|
||||
if (patternContainsOnlyStar()) {
|
||||
return true;
|
||||
}
|
||||
if (patternContainsOneTemplateVariable()) {
|
||||
addTemplateVariable(0, patIdxEnd, 0, strIdxEnd);
|
||||
return true;
|
||||
}
|
||||
if (!matchBeforeFirstStarOrCurly()) {
|
||||
return false;
|
||||
}
|
||||
if (allCharsUsed()) {
|
||||
return onlyStarsLeft();
|
||||
}
|
||||
if (!matchAfterLastStarOrCurly()) {
|
||||
return false;
|
||||
}
|
||||
if (allCharsUsed()) {
|
||||
return onlyStarsLeft();
|
||||
}
|
||||
// Process pattern between stars. padIdxStart and patIdxEnd point always to a '*'.
|
||||
while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
|
||||
int patIdxTmp;
|
||||
if (patArr[patIdxStart] == '{') {
|
||||
patIdxTmp = findClosingCurly();
|
||||
addTemplateVariable(patIdxStart, patIdxTmp, strIdxStart, strIdxEnd);
|
||||
patIdxStart = patIdxTmp + 1;
|
||||
strIdxStart = strIdxEnd + 1;
|
||||
continue;
|
||||
}
|
||||
patIdxTmp = findNextStarOrCurly();
|
||||
if (consecutiveStars(patIdxTmp)) {
|
||||
continue;
|
||||
}
|
||||
// Find the pattern between padIdxStart & padIdxTmp in str between strIdxStart & strIdxEnd
|
||||
int patLength = (patIdxTmp - patIdxStart - 1);
|
||||
int strLength = (strIdxEnd - strIdxStart + 1);
|
||||
int foundIdx = -1;
|
||||
strLoop:
|
||||
for (int i = 0; i <= strLength - patLength; i++) {
|
||||
for (int j = 0; j < patLength; j++) {
|
||||
ch = patArr[patIdxStart + j + 1];
|
||||
if (ch != '?') {
|
||||
if (ch != strArr[strIdxStart + i + j]) {
|
||||
continue strLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foundIdx = strIdxStart + i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (foundIdx == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
patIdxStart = patIdxTmp;
|
||||
strIdxStart = foundIdx + patLength;
|
||||
}
|
||||
|
||||
return onlyStarsLeft();
|
||||
}
|
||||
|
||||
private boolean consecutiveStars(final int patIdxTmp) {
|
||||
if (patIdxTmp == patIdxStart + 1 && patArr[patIdxStart] == '*' && patArr[patIdxTmp] == '*') {
|
||||
// Two stars next to each other, skip the first one.
|
||||
patIdxStart++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int findNextStarOrCurly() {
|
||||
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
|
||||
if (patArr[i] == '*' || patArr[i] == '{') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int findClosingCurly() {
|
||||
for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
|
||||
if (patArr[i] == '}') {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private boolean onlyStarsLeft() {
|
||||
for (int i = patIdxStart; i <= patIdxEnd; i++) {
|
||||
if (patArr[i] != '*') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean allCharsUsed() {
|
||||
return strIdxStart > strIdxEnd;
|
||||
}
|
||||
|
||||
private boolean shortcutPossible() {
|
||||
for (char ch : patArr) {
|
||||
if (ch == '*' || ch == '{' || ch == '}') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean doShortcut() {
|
||||
if (patIdxEnd != strIdxEnd) {
|
||||
return false; // Pattern and string do not have the same size
|
||||
}
|
||||
for (int i = 0; i <= patIdxEnd; i++) {
|
||||
ch = patArr[i];
|
||||
if (ch != '?') {
|
||||
if (ch != strArr[i]) {
|
||||
return false;// Character mismatch
|
||||
}
|
||||
}
|
||||
}
|
||||
return true; // String matches against pattern
|
||||
}
|
||||
|
||||
private boolean patternContainsOnlyStar() {
|
||||
return (patIdxEnd == 0 && patArr[0] == '*');
|
||||
}
|
||||
|
||||
private boolean patternContainsOneTemplateVariable() {
|
||||
if ((patIdxEnd >= 2 && patArr[0] == '{' && patArr[patIdxEnd] == '}')) {
|
||||
for (int i = 1; i < patIdxEnd; i++) {
|
||||
if (patArr[i] == '}') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchBeforeFirstStarOrCurly() {
|
||||
while ((ch = patArr[patIdxStart]) != '*' && ch != '{' && strIdxStart <= strIdxEnd) {
|
||||
if (ch != '?') {
|
||||
if (ch != strArr[strIdxStart]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
patIdxStart++;
|
||||
strIdxStart++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean matchAfterLastStarOrCurly() {
|
||||
while ((ch = patArr[patIdxEnd]) != '*' && ch != '}' && strIdxStart <= strIdxEnd) {
|
||||
if (ch != '?') {
|
||||
if (ch != strArr[strIdxEnd]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
patIdxEnd--;
|
||||
strIdxEnd--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* PathMatcher implementation for Ant-style path patterns.
|
||||
* Examples are provided below.
|
||||
*
|
||||
* @author Alef Arendsen
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @since 16.07.2003
|
||||
*/
|
||||
public class AntPathMatcher implements PathMatcher {
|
||||
|
||||
/** Default path separator: "/" */
|
||||
public static final String DEFAULT_PATH_SEPARATOR = "/";
|
||||
|
||||
private String pathSeparator = DEFAULT_PATH_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Set the path separator to use for pattern parsing.
|
||||
* Default is "/", as in Ant.
|
||||
*/
|
||||
public void setPathSeparator(final String pathSeparator) {
|
||||
this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
public boolean isPattern(final String path) {
|
||||
return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
|
||||
}
|
||||
|
||||
public boolean match(final String pattern, final String path) {
|
||||
return doMatch(pattern, path, true, null);
|
||||
}
|
||||
|
||||
public boolean matchStart(final String pattern, final String path) {
|
||||
return doMatch(pattern, path, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually match the given <code>path</code> against the given <code>pattern</code>.
|
||||
* @param pattern the pattern to match against
|
||||
* @param path the path String to test
|
||||
* @param fullMatch whether a full pattern match is required
|
||||
* (else a pattern match as far as the given base path goes is sufficient)
|
||||
* @return <code>true</code> if the supplied <code>path</code> matched,
|
||||
* <code>false</code> if it didn't
|
||||
*/
|
||||
protected boolean doMatch(final String pattern, final String path, final boolean fullMatch, final Map<String, String> uriTemplateVariables) {
|
||||
if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
|
||||
String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator);
|
||||
|
||||
int pattIdxStart = 0;
|
||||
int pattIdxEnd = pattDirs.length - 1;
|
||||
int pathIdxStart = 0;
|
||||
int pathIdxEnd = pathDirs.length - 1;
|
||||
|
||||
// Match all elements up to the first **
|
||||
while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
|
||||
String patDir = pattDirs[pattIdxStart];
|
||||
if ("**".equals(patDir)) {
|
||||
break;
|
||||
}
|
||||
if (!matchStrings(patDir, pathDirs[pathIdxStart], uriTemplateVariables)) {
|
||||
return false;
|
||||
}
|
||||
pattIdxStart++;
|
||||
pathIdxStart++;
|
||||
}
|
||||
|
||||
if (pathIdxStart > pathIdxEnd) {
|
||||
// Path is exhausted, only match if rest of pattern is * or **'s
|
||||
if (pattIdxStart > pattIdxEnd) {
|
||||
return (pattern.endsWith(this.pathSeparator) ? path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator));
|
||||
}
|
||||
if (!fullMatch) {
|
||||
return true;
|
||||
}
|
||||
if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") && path.endsWith(this.pathSeparator)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
|
||||
if (!pattDirs[i].equals("**")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (pattIdxStart > pattIdxEnd) {
|
||||
// String not exhausted, but pattern is. Failure.
|
||||
return false;
|
||||
} else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) {
|
||||
// Path start definitely matches due to "**" part in pattern.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Up to last '**'
|
||||
while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
|
||||
String patDir = pattDirs[pattIdxEnd];
|
||||
if (patDir.equals("**")) {
|
||||
break;
|
||||
}
|
||||
if (!matchStrings(patDir, pathDirs[pathIdxEnd], uriTemplateVariables)) {
|
||||
return false;
|
||||
}
|
||||
pattIdxEnd--;
|
||||
pathIdxEnd--;
|
||||
}
|
||||
if (pathIdxStart > pathIdxEnd) {
|
||||
// String is exhausted
|
||||
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
|
||||
if (!pattDirs[i].equals("**")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
|
||||
int patIdxTmp = -1;
|
||||
for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
|
||||
if (pattDirs[i].equals("**")) {
|
||||
patIdxTmp = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (patIdxTmp == pattIdxStart + 1) {
|
||||
// '**/**' situation, so skip one
|
||||
pattIdxStart++;
|
||||
continue;
|
||||
}
|
||||
// Find the pattern between padIdxStart & padIdxTmp in str between strIdxStart & strIdxEnd
|
||||
int patLength = (patIdxTmp - pattIdxStart - 1);
|
||||
int strLength = (pathIdxEnd - pathIdxStart + 1);
|
||||
int foundIdx = -1;
|
||||
|
||||
strLoop: for (int i = 0; i <= strLength - patLength; i++) {
|
||||
for (int j = 0; j < patLength; j++) {
|
||||
String subPat = pattDirs[pattIdxStart + j + 1];
|
||||
String subStr = pathDirs[pathIdxStart + i + j];
|
||||
if (!matchStrings(subPat, subStr, uriTemplateVariables)) {
|
||||
continue strLoop;
|
||||
}
|
||||
}
|
||||
foundIdx = pathIdxStart + i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (foundIdx == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pattIdxStart = patIdxTmp;
|
||||
pathIdxStart = foundIdx + patLength;
|
||||
}
|
||||
|
||||
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
|
||||
if (!pattDirs[i].equals("**")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not a string matches against a pattern.
|
||||
* The pattern may contain two special characters:<br>
|
||||
* '*' means zero or more characters<br>
|
||||
* '?' means one and only one character
|
||||
* @param pattern pattern to match against.
|
||||
* Must not be <code>null</code>.
|
||||
* @param str string which must be matched against the pattern.
|
||||
* Must not be <code>null</code>.
|
||||
* @return <code>true</code> if the string matches against the
|
||||
* pattern, or <code>false</code> otherwise.
|
||||
*/
|
||||
private boolean matchStrings(final String pattern, final String str, final Map<String, String> uriTemplateVariables) {
|
||||
AntPatchStringMatcher matcher = new AntPatchStringMatcher(pattern, str, uriTemplateVariables);
|
||||
return matcher.matchStrings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a pattern and a full path, determine the pattern-mapped part.
|
||||
* <p>For example:
|
||||
* <ul>
|
||||
* <li>'<code>/docs/cvs/commit.html</code>' and '<code>/docs/cvs/commit.html</code> -> ''</li>
|
||||
* <li>'<code>/docs/*</code>' and '<code>/docs/cvs/commit</code> -> '<code>cvs/commit</code>'</li>
|
||||
* <li>'<code>/docs/cvs/*.html</code>' and '<code>/docs/cvs/commit.html</code> -> '<code>commit.html</code>'</li>
|
||||
* <li>'<code>/docs/**</code>' and '<code>/docs/cvs/commit</code> -> '<code>cvs/commit</code>'</li>
|
||||
* <li>'<code>/docs/**\/*.html</code>' and '<code>/docs/cvs/commit.html</code> -> '<code>cvs/commit.html</code>'</li>
|
||||
* <li>'<code>/*.html</code>' and '<code>/docs/cvs/commit.html</code> -> '<code>docs/cvs/commit.html</code>'</li>
|
||||
* <li>'<code>*.html</code>' and '<code>/docs/cvs/commit.html</code> -> '<code>/docs/cvs/commit.html</code>'</li>
|
||||
* <li>'<code>*</code>' and '<code>/docs/cvs/commit.html</code> -> '<code>/docs/cvs/commit.html</code>'</li>
|
||||
* </ul>
|
||||
* <p>Assumes that {@link #match} returns <code>true</code> for '<code>pattern</code>'
|
||||
* and '<code>path</code>', but does <strong>not</strong> enforce this.
|
||||
*/
|
||||
public String extractPathWithinPattern(final String pattern, final String path) {
|
||||
String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
|
||||
String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
// Add any path parts that have a wildcarded pattern part.
|
||||
int puts = 0;
|
||||
for (int i = 0; i < patternParts.length; i++) {
|
||||
String patternPart = patternParts[i];
|
||||
if ((patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) && pathParts.length >= i + 1) {
|
||||
if (puts > 0 || (i == 0 && !pattern.startsWith(this.pathSeparator))) {
|
||||
builder.append(this.pathSeparator);
|
||||
}
|
||||
builder.append(pathParts[i]);
|
||||
puts++;
|
||||
}
|
||||
}
|
||||
|
||||
// Append any trailing path parts.
|
||||
for (int i = patternParts.length; i < pathParts.length; i++) {
|
||||
if (puts > 0 || i > 0) {
|
||||
builder.append(this.pathSeparator);
|
||||
}
|
||||
builder.append(pathParts[i]);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public Map<String, String> extractUriTemplateVariables(final String pattern, final String path) {
|
||||
Map<String, String> variables = new LinkedHashMap<String, String>();
|
||||
boolean result = doMatch(pattern, path, true, variables);
|
||||
Assert.state(result, "Pattern \"" + pattern + "\" is not a match for \"" + path + "\"");
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
@@ -1,412 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Assertion utility class that assists in validating arguments.
|
||||
* Useful for identifying programmer errors early and clearly at runtime.
|
||||
*
|
||||
* <p>For example, if the contract of a public method states it does not
|
||||
* allow <code>null</code> arguments, Assert can be used to validate that
|
||||
* contract. Doing this clearly indicates a contract violation when it
|
||||
* occurs and protects the class's invariants.
|
||||
*
|
||||
* <p>Typically used to validate method arguments rather than configuration
|
||||
* properties, to check for cases that are usually programmer errors rather than
|
||||
* configuration errors. In contrast to config initialization code, there is
|
||||
* usally no point in falling back to defaults in such methods.
|
||||
*
|
||||
* <p>This class is similar to JUnit's assertion library. If an argument value is
|
||||
* deemed invalid, an {@link IllegalArgumentException} is thrown (typically).
|
||||
* For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* Assert.notNull(clazz, "The class must not be null");
|
||||
* Assert.isTrue(i > 0, "The value must be greater than zero");</pre>
|
||||
*
|
||||
* Mainly for internal use within the framework; consider Jakarta's Commons Lang
|
||||
* >= 2.0 for a more comprehensive suite of assertion utilities.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @author Colin Sampaleanu
|
||||
* @author Rob Harrop
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public abstract class Assert {
|
||||
|
||||
/**
|
||||
* Assert a boolean expression, throwing <code>IllegalArgumentException</code>
|
||||
* if the test result is <code>false</code>.
|
||||
* <pre class="code">Assert.isTrue(i > 0, "The value must be greater than zero");</pre>
|
||||
* @param expression a boolean expression
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @throws IllegalArgumentException if expression is <code>false</code>
|
||||
*/
|
||||
public static void isTrue(final boolean expression, final String message) {
|
||||
if (!expression) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a boolean expression, throwing <code>IllegalArgumentException</code>
|
||||
* if the test result is <code>false</code>.
|
||||
* <pre class="code">Assert.isTrue(i > 0);</pre>
|
||||
* @param expression a boolean expression
|
||||
* @throws IllegalArgumentException if expression is <code>false</code>
|
||||
*/
|
||||
public static void isTrue(final boolean expression) {
|
||||
isTrue(expression, "[Assertion failed] - this expression must be true");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an object is <code>null</code> .
|
||||
* <pre class="code">Assert.isNull(value, "The value must be null");</pre>
|
||||
* @param object the object to check
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @throws IllegalArgumentException if the object is not <code>null</code>
|
||||
*/
|
||||
public static void isNull(final Object object, final String message) {
|
||||
if (object != null) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an object is <code>null</code> .
|
||||
* <pre class="code">Assert.isNull(value);</pre>
|
||||
* @param object the object to check
|
||||
* @throws IllegalArgumentException if the object is not <code>null</code>
|
||||
*/
|
||||
public static void isNull(final Object object) {
|
||||
isNull(object, "[Assertion failed] - the object argument must be null");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an object is not <code>null</code> .
|
||||
* <pre class="code">Assert.notNull(clazz, "The class must not be null");</pre>
|
||||
* @param object the object to check
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @throws IllegalArgumentException if the object is <code>null</code>
|
||||
*/
|
||||
public static void notNull(final Object object, final String message) {
|
||||
if (object == null) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an object is not <code>null</code> .
|
||||
* <pre class="code">Assert.notNull(clazz);</pre>
|
||||
* @param object the object to check
|
||||
* @throws IllegalArgumentException if the object is <code>null</code>
|
||||
*/
|
||||
public static void notNull(final Object object) {
|
||||
notNull(object, "[Assertion failed] - this argument is required; it must not be null");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given String is not empty; that is,
|
||||
* it must not be <code>null</code> and not the empty String.
|
||||
* <pre class="code">Assert.hasLength(name, "Name must not be empty");</pre>
|
||||
* @param text the String to check
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @see StringUtils#hasLength
|
||||
*/
|
||||
public static void hasLength(final String text, final String message) {
|
||||
if (!StringUtils.hasLength(text)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given String is not empty; that is,
|
||||
* it must not be <code>null</code> and not the empty String.
|
||||
* <pre class="code">Assert.hasLength(name);</pre>
|
||||
* @param text the String to check
|
||||
* @see StringUtils#hasLength
|
||||
*/
|
||||
public static void hasLength(final String text) {
|
||||
hasLength(text,
|
||||
"[Assertion failed] - this String argument must have length; it must not be null or empty");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given String has valid text content; that is, it must not
|
||||
* be <code>null</code> and must contain at least one non-whitespace character.
|
||||
* <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre>
|
||||
* @param text the String to check
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @see StringUtils#hasText
|
||||
*/
|
||||
public static void hasText(final String text, final String message) {
|
||||
if (StringUtils.isBlank(text)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given String has valid text content; that is, it must not
|
||||
* be <code>null</code> and must contain at least one non-whitespace character.
|
||||
* <pre class="code">Assert.hasText(name, "'name' must not be empty");</pre>
|
||||
* @param text the String to check
|
||||
* @see StringUtils#hasText
|
||||
*/
|
||||
public static void hasText(final String text) {
|
||||
hasText(text,
|
||||
"[Assertion failed] - this String argument must have text; it must not be null, empty, or blank");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given text does not contain the given substring.
|
||||
* <pre class="code">Assert.doesNotContain(name, "rod", "Name must not contain 'rod'");</pre>
|
||||
* @param textToSearch the text to search
|
||||
* @param substring the substring to find within the text
|
||||
* @param message the exception message to use if the assertion fails
|
||||
*/
|
||||
public static void doesNotContain(final String textToSearch, final String substring, final String message) {
|
||||
if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
|
||||
textToSearch.indexOf(substring) != -1) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the given text does not contain the given substring.
|
||||
* <pre class="code">Assert.doesNotContain(name, "rod");</pre>
|
||||
* @param textToSearch the text to search
|
||||
* @param substring the substring to find within the text
|
||||
*/
|
||||
public static void doesNotContain(final String textToSearch, final String substring) {
|
||||
doesNotContain(textToSearch, substring,
|
||||
"[Assertion failed] - this String argument must not contain the substring [" + substring + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an array has elements; that is, it must not be
|
||||
* <code>null</code> and must have at least one element.
|
||||
* <pre class="code">Assert.notEmpty(array, "The array must have elements");</pre>
|
||||
* @param array the array to check
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @throws IllegalArgumentException if the object array is <code>null</code> or has no elements
|
||||
*/
|
||||
public static void notEmpty(final Object[] array, final String message) {
|
||||
if (ObjectUtils.isEmpty(array)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an array has elements; that is, it must not be
|
||||
* <code>null</code> and must have at least one element.
|
||||
* <pre class="code">Assert.notEmpty(array);</pre>
|
||||
* @param array the array to check
|
||||
* @throws IllegalArgumentException if the object array is <code>null</code> or has no elements
|
||||
*/
|
||||
public static void notEmpty(final Object[] array) {
|
||||
notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an array has no null elements.
|
||||
* Note: Does not complain if the array is empty!
|
||||
* <pre class="code">Assert.noNullElements(array, "The array must have non-null elements");</pre>
|
||||
* @param array the array to check
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @throws IllegalArgumentException if the object array contains a <code>null</code> element
|
||||
*/
|
||||
public static void noNullElements(final Object[] array, final String message) {
|
||||
if (array != null) {
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
if (array[i] == null) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an array has no null elements.
|
||||
* Note: Does not complain if the array is empty!
|
||||
* <pre class="code">Assert.noNullElements(array);</pre>
|
||||
* @param array the array to check
|
||||
* @throws IllegalArgumentException if the object array contains a <code>null</code> element
|
||||
*/
|
||||
public static void noNullElements(final Object[] array) {
|
||||
noNullElements(array, "[Assertion failed] - this array must not contain any null elements");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a collection has elements; that is, it must not be
|
||||
* <code>null</code> and must have at least one element.
|
||||
* <pre class="code">Assert.notEmpty(collection, "Collection must have elements");</pre>
|
||||
* @param collection the collection to check
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @throws IllegalArgumentException if the collection is <code>null</code> or has no elements
|
||||
*/
|
||||
public static void notEmpty(final Collection<?> collection, final String message) {
|
||||
if (CollectionUtils.isEmpty(collection)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a collection has elements; that is, it must not be
|
||||
* <code>null</code> and must have at least one element.
|
||||
* <pre class="code">Assert.notEmpty(collection, "Collection must have elements");</pre>
|
||||
* @param collection the collection to check
|
||||
* @throws IllegalArgumentException if the collection is <code>null</code> or has no elements
|
||||
*/
|
||||
public static void notEmpty(final Collection<?> collection) {
|
||||
notEmpty(collection,
|
||||
"[Assertion failed] - this collection must not be empty: it must contain at least 1 element");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a Map has entries; that is, it must not be <code>null</code>
|
||||
* and must have at least one entry.
|
||||
* <pre class="code">Assert.notEmpty(map, "Map must have entries");</pre>
|
||||
* @param map the map to check
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @throws IllegalArgumentException if the map is <code>null</code> or has no entries
|
||||
*/
|
||||
public static void notEmpty(final Map<?, ?> map, final String message) {
|
||||
if (CollectionUtils.isEmpty(map)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a Map has entries; that is, it must not be <code>null</code>
|
||||
* and must have at least one entry.
|
||||
* <pre class="code">Assert.notEmpty(map);</pre>
|
||||
* @param map the map to check
|
||||
* @throws IllegalArgumentException if the map is <code>null</code> or has no entries
|
||||
*/
|
||||
public static void notEmpty(final Map<?, ?> map) {
|
||||
notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the provided object is an instance of the provided class.
|
||||
* <pre class="code">Assert.instanceOf(Foo.class, foo);</pre>
|
||||
* @param clazz the required class
|
||||
* @param obj the object to check
|
||||
* @throws IllegalArgumentException if the object is not an instance of clazz
|
||||
* @see Class#isInstance
|
||||
*/
|
||||
public static void isInstanceOf(final Class<?> clazz, final Object obj) {
|
||||
isInstanceOf(clazz, obj, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the provided object is an instance of the provided class.
|
||||
* <pre class="code">Assert.instanceOf(Foo.class, foo);</pre>
|
||||
* @param type the type to check against
|
||||
* @param obj the object to check
|
||||
* @param message a message which will be prepended to the message produced by
|
||||
* the function itself, and which may be used to provide context. It should
|
||||
* normally end in a ": " or ". " so that the function generate message looks
|
||||
* ok when prepended to it.
|
||||
* @throws IllegalArgumentException if the object is not an instance of clazz
|
||||
* @see Class#isInstance
|
||||
*/
|
||||
public static void isInstanceOf(final Class<?> type, final Object obj, final String message) {
|
||||
notNull(type, "Type to check against must not be null");
|
||||
if (!type.isInstance(obj)) {
|
||||
throw new IllegalArgumentException(message +
|
||||
"Object of class [" + (obj != null ? obj.getClass().getName() : "null") +
|
||||
"] must be an instance of " + type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>.
|
||||
* <pre class="code">Assert.isAssignable(Number.class, myClass);</pre>
|
||||
* @param superType the super type to check
|
||||
* @param subType the sub type to check
|
||||
* @throws IllegalArgumentException if the classes are not assignable
|
||||
*/
|
||||
public static void isAssignable(final Class<?> superType, final Class<?> subType) {
|
||||
isAssignable(superType, subType, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that <code>superType.isAssignableFrom(subType)</code> is <code>true</code>.
|
||||
* <pre class="code">Assert.isAssignable(Number.class, myClass);</pre>
|
||||
* @param superType the super type to check against
|
||||
* @param subType the sub type to check
|
||||
* @param message a message which will be prepended to the message produced by
|
||||
* the function itself, and which may be used to provide context. It should
|
||||
* normally end in a ": " or ". " so that the function generate message looks
|
||||
* ok when prepended to it.
|
||||
* @throws IllegalArgumentException if the classes are not assignable
|
||||
*/
|
||||
public static void isAssignable(final Class<?> superType, final Class<?> subType, final String message) {
|
||||
notNull(superType, "Type to check against must not be null");
|
||||
if (subType == null || !superType.isAssignableFrom(subType)) {
|
||||
throw new IllegalArgumentException(message + subType + " is not assignable to " + superType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a boolean expression, throwing <code>IllegalStateException</code>
|
||||
* if the test result is <code>false</code>. Call isTrue if you wish to
|
||||
* throw IllegalArgumentException on an assertion failure.
|
||||
* <pre class="code">Assert.state(id == null, "The id property must not already be initialized");</pre>
|
||||
* @param expression a boolean expression
|
||||
* @param message the exception message to use if the assertion fails
|
||||
* @throws IllegalStateException if expression is <code>false</code>
|
||||
*/
|
||||
public static void state(final boolean expression, final String message) {
|
||||
if (!expression) {
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert a boolean expression, throwing {@link IllegalStateException}
|
||||
* if the test result is <code>false</code>.
|
||||
* <p>Call {@link #isTrue(boolean)} if you wish to
|
||||
* throw {@link IllegalArgumentException} on an assertion failure.
|
||||
* <pre class="code">Assert.state(id == null);</pre>
|
||||
* @param expression a boolean expression
|
||||
* @throws IllegalStateException if the supplied expression is <code>false</code>
|
||||
*/
|
||||
public static void state(final boolean expression) {
|
||||
state(expression, "[Assertion failed] - this state invariant must be true");
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,366 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Miscellaneous collection utility methods.
|
||||
* Mainly for internal use within the framework.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Andrew Swan
|
||||
* @since 1.1.3
|
||||
*/
|
||||
public final class CollectionUtils {
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if the supplied Collection is <code>null</code>
|
||||
* or empty. Otherwise, return <code>false</code>.
|
||||
*
|
||||
* @param collection the Collection to check
|
||||
* @return whether the given Collection is empty
|
||||
*/
|
||||
public static boolean isEmpty(final Collection<?> collection) {
|
||||
return (collection == null || collection.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if the supplied Map is <code>null</code>
|
||||
* or empty. Otherwise, return <code>false</code>.
|
||||
*
|
||||
* @param map the Map to check
|
||||
* @return whether the given Map is empty
|
||||
*/
|
||||
public static boolean isEmpty(final Map<?, ?> map) {
|
||||
return (map == null || map.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the supplied array into a List. A primitive array gets
|
||||
* converted into a List of the appropriate wrapper type.
|
||||
* <p>A <code>null</code> source value will be converted to an
|
||||
* empty List.
|
||||
*
|
||||
* @param source the (potentially primitive) array
|
||||
* @return the converted List result
|
||||
* @see ObjectUtils#toObjectArray(Object)
|
||||
*/
|
||||
public static List<?> arrayToList(final Object source) {
|
||||
return Arrays.asList(ObjectUtils.toObjectArray(source));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the given array into the given Collection.
|
||||
*
|
||||
* @param array the array to merge (may be <code>null</code>)
|
||||
* @param collection the target Collection to merge the array into
|
||||
*/
|
||||
public static void mergeArrayIntoCollection(final Object array, final Collection<Object> collection) {
|
||||
if (collection == null) {
|
||||
throw new IllegalArgumentException("Collection must not be null");
|
||||
}
|
||||
final Object[] arr = ObjectUtils.toObjectArray(array);
|
||||
for (final Object elem : arr) {
|
||||
collection.add(elem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the given Properties instance into the given Map,
|
||||
* copying all properties (key-value pairs) over.
|
||||
* <p>Uses <code>Properties.propertyNames()</code> to even catch
|
||||
* default properties linked into the original Properties instance.
|
||||
*
|
||||
* @param props the Properties instance to merge (may be <code>null</code>)
|
||||
* @param map the target Map to merge the properties into
|
||||
*/
|
||||
public static void mergePropertiesIntoMap(final Properties props, final Map<String, String> map) {
|
||||
if (map == null) {
|
||||
throw new IllegalArgumentException("Map must not be null");
|
||||
}
|
||||
if (props != null) {
|
||||
for (final Enumeration<?> en = props.propertyNames(); en.hasMoreElements();) {
|
||||
final String key = (String) en.nextElement();
|
||||
map.put(key, props.getProperty(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given Iterator contains the given element.
|
||||
*
|
||||
* @param iterator the Iterator to check
|
||||
* @param element the element to look for
|
||||
* @return <code>true</code> if found, <code>false</code> else
|
||||
*/
|
||||
public static boolean contains(final Iterator<?> iterator, final Object element) {
|
||||
if (iterator != null) {
|
||||
while (iterator.hasNext()) {
|
||||
final Object candidate = iterator.next();
|
||||
if (ObjectUtils.nullSafeEquals(candidate, element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given Enumeration contains the given element.
|
||||
*
|
||||
* @param enumeration the Enumeration to check
|
||||
* @param element the element to look for
|
||||
* @return <code>true</code> if found, <code>false</code> else
|
||||
*/
|
||||
public static boolean contains(final Enumeration<?> enumeration, final Object element) {
|
||||
if (enumeration != null) {
|
||||
while (enumeration.hasMoreElements()) {
|
||||
final Object candidate = enumeration.nextElement();
|
||||
if (ObjectUtils.nullSafeEquals(candidate, element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given Collection contains the given element instance.
|
||||
* <p>Enforces the given instance to be present, rather than returning
|
||||
* <code>true</code> for an equal element as well.
|
||||
*
|
||||
* @param collection the Collection to check
|
||||
* @param element the element to look for
|
||||
* @return <code>true</code> if found, <code>false</code> else
|
||||
*/
|
||||
public static boolean containsInstance(final Collection<?> collection, final Object element) {
|
||||
if (collection != null) {
|
||||
for (final Object candidate : collection) {
|
||||
if (candidate == element) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if any element in '<code>candidates</code>' is
|
||||
* contained in '<code>source</code>'; otherwise returns <code>false</code>.
|
||||
*
|
||||
* @param source the source Collection
|
||||
* @param candidates the candidates to search for
|
||||
* @return whether any of the candidates has been found
|
||||
*/
|
||||
public static boolean containsAny(final Collection<?> source, final Collection<?> candidates) {
|
||||
if (isEmpty(source) || isEmpty(candidates)) {
|
||||
return false;
|
||||
}
|
||||
for (final Object candidate : candidates) {
|
||||
if (source.contains(candidate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first element in '<code>candidates</code>' that is contained in
|
||||
* '<code>source</code>'. If no element in '<code>candidates</code>' is present in
|
||||
* '<code>source</code>' returns <code>null</code>. Iteration order is
|
||||
* {@link Collection} implementation specific.
|
||||
*
|
||||
* @param source the source Collection
|
||||
* @param candidates the candidates to search for
|
||||
* @return the first present object, or <code>null</code> if not found
|
||||
*/
|
||||
public static Object findFirstMatch(final Collection<?> source, final Collection<?> candidates) {
|
||||
if (isEmpty(source) || isEmpty(candidates)) {
|
||||
return null;
|
||||
}
|
||||
for (final Object candidate : candidates) {
|
||||
if (source.contains(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a single value of the given type in the given Collection.
|
||||
*
|
||||
* @param collection the Collection to search
|
||||
* @param type the type to look for
|
||||
* @return a value of the given type found if there is a clear match,
|
||||
* or <code>null</code> if none or more than one such value found
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T findValueOfType(final Collection<?> collection, final Class<T> type) {
|
||||
if (isEmpty(collection)) {
|
||||
return null;
|
||||
}
|
||||
T value = null;
|
||||
for (final Object element : collection) {
|
||||
if (type == null || type.isInstance(element)) {
|
||||
if (value != null) {
|
||||
// More than one value found... no clear single value.
|
||||
return null;
|
||||
}
|
||||
value = (T) element;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a single value of one of the given types in the given Collection:
|
||||
* searching the Collection for a value of the first type, then
|
||||
* searching for a value of the second type, etc.
|
||||
*
|
||||
* @param collection the collection to search
|
||||
* @param types the types to look for, in prioritized order
|
||||
* @return a value of one of the given types found if there is a clear match,
|
||||
* or <code>null</code> if none or more than one such value found
|
||||
*/
|
||||
public static Object findValueOfType(final Collection<?> collection, final Class<?>... types) {
|
||||
if (isEmpty(collection) || ObjectUtils.isEmpty(types)) {
|
||||
return null;
|
||||
}
|
||||
for (final Class<?> type : types) {
|
||||
final Object value = findValueOfType(collection, type);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given Collection only contains a single unique object.
|
||||
*
|
||||
* @param collection the Collection to check
|
||||
* @return <code>true</code> if the collection contains a single reference or
|
||||
* multiple references to the same instance, <code>false</code> else
|
||||
*/
|
||||
public static boolean hasUniqueObject(final Collection<?> collection) {
|
||||
if (isEmpty(collection)) {
|
||||
return false;
|
||||
}
|
||||
boolean hasCandidate = false;
|
||||
Object candidate = null;
|
||||
for (final Iterator<?> it = collection.iterator(); it.hasNext();) {
|
||||
final Object elem = it.next();
|
||||
if (!hasCandidate) {
|
||||
hasCandidate = true;
|
||||
candidate = elem;
|
||||
}
|
||||
else if (candidate != elem) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters (removes elements from) the given {@link Iterable} using the
|
||||
* given filter.
|
||||
*
|
||||
* @param <T> the type of object being filtered
|
||||
* @param unfiltered the iterable to filter; can be <code>null</code>
|
||||
* @param filter the filter to apply; can be <code>null</code> for none
|
||||
* @return a non-<code>null</code> list
|
||||
*/
|
||||
public static <T> List<T> filter(final Iterable<? extends T> unfiltered, final Filter<T> filter) {
|
||||
final List<T> filtered = new ArrayList<T>();
|
||||
if (unfiltered != null) {
|
||||
for (final T element : unfiltered) {
|
||||
if (filter == null || filter.include(element)) {
|
||||
filtered.add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given items to the given collection
|
||||
*
|
||||
* @param <T> the type of item in the collection being updated
|
||||
* @param newItems the items being added; can be <code>null</code> for none
|
||||
* @param existingItems the items being added to; must be modifiable
|
||||
* @return <code>true</code> if the existing collection was modified
|
||||
* @throws UnsupportedOperationException if there are items to add and the
|
||||
* existing collection is not modifiable
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static <T> boolean addAll(final Collection<? extends T> newItems, final Collection<T> existingItems) {
|
||||
if (existingItems != null && newItems != null) {
|
||||
return existingItems.addAll(newItems);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the given collection by replacing any existing contents with
|
||||
* the given elements, in a null-safe way.
|
||||
*
|
||||
* @param <T> the type of element in the collection
|
||||
* @param collection the collection to populate (can be <code>null</code>)
|
||||
* @param items the items with which to populate the collection (can be
|
||||
* <code>null</code> or empty for none)
|
||||
* @return the given collection (useful if it was anonymous)
|
||||
*/
|
||||
public static <T> Collection<T> populate(final Collection<T> collection, final Collection<? extends T> items) {
|
||||
if (collection != null) {
|
||||
collection.clear();
|
||||
if (items != null) {
|
||||
collection.addAll(items);
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first element of the given collection
|
||||
*
|
||||
* @param <T>
|
||||
* @param collection
|
||||
* @return <code>null</code> if the first element is <code>null</code> or
|
||||
* the collection is <code>null</code> or empty
|
||||
*/
|
||||
public static <T> T firstElementOf(final Collection<? extends T> collection) {
|
||||
if (isEmpty(collection)) {
|
||||
return null;
|
||||
}
|
||||
return collection.iterator().next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
private CollectionUtils() {}
|
||||
}
|
||||
@@ -1,310 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.CharacterData;
|
||||
import org.w3c.dom.Comment;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.EntityReference;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Convenience methods for working with the DOM API,
|
||||
* in particular for working with DOM Nodes and DOM Elements.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Costin Leau
|
||||
* @author Alan Stewart
|
||||
* @since 1.2.0
|
||||
* @see org.w3c.dom.Node
|
||||
* @see org.w3c.dom.Element
|
||||
*/
|
||||
public final class DomUtils {
|
||||
|
||||
/**
|
||||
* Retrieve all child elements of the given DOM element that match any of
|
||||
* the given element names. Only look at the direct child level of the
|
||||
* given element; do not go into further depth (in contrast to the
|
||||
* DOM API's <code>getElementsByTagName</code> method).
|
||||
*
|
||||
* @param element the DOM element to analyze
|
||||
* @param childElementNames the child element names to look for
|
||||
* @return a List of child <code>org.w3c.dom.Element</code> instances
|
||||
* @see org.w3c.dom.Element
|
||||
* @see org.w3c.dom.Element#getElementsByTagName
|
||||
*/
|
||||
public static List<Element> getChildElementsByTagName(final Element element, final String[] childElementNames) {
|
||||
Assert.notNull(element, "Element must not be null");
|
||||
Assert.notNull(childElementNames, "Element names collection must not be null");
|
||||
List<String> childEleNameList = Arrays.asList(childElementNames);
|
||||
NodeList nl = element.getChildNodes();
|
||||
List<Element> childEles = new ArrayList<Element>();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameMatch(node, childEleNameList)) {
|
||||
childEles.add((Element) node);
|
||||
}
|
||||
}
|
||||
return childEles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all child elements of the given DOM element that match
|
||||
* the given element name. Only look at the direct child level of the
|
||||
* given element; do not go into further depth (in contrast to the
|
||||
* DOM API's <code>getElementsByTagName</code> method).
|
||||
*
|
||||
* @param element the DOM element to analyze
|
||||
* @param childEleName the child element name to look for
|
||||
* @return a List of child <code>org.w3c.dom.Element</code> instances
|
||||
* @see org.w3c.dom.Element
|
||||
* @see org.w3c.dom.Element#getElementsByTagName
|
||||
*/
|
||||
public static List<Element> getChildElementsByTagName(final Element element, final String childEleName) {
|
||||
return getChildElementsByTagName(element, new String[] {childEleName});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first child element identified by its name.
|
||||
*
|
||||
* @param element the DOM element to analyze
|
||||
* @param childElementName the child element name to look for
|
||||
* @return the <code>org.w3c.dom.Element</code> instance,
|
||||
* or <code>null</code> if none found
|
||||
*/
|
||||
public static Element getChildElementByTagName(final Element element, final String childElementName) {
|
||||
Assert.notNull(element, "Element must not be null");
|
||||
Assert.notNull(childElementName, "Element name must not be null");
|
||||
NodeList nl = element.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node node = nl.item(i);
|
||||
if (node instanceof Element && nodeNameMatch(node, childElementName)) {
|
||||
return (Element) node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first child element value identified by its name.
|
||||
*
|
||||
* @param element the DOM element to analyze
|
||||
* @param childElementName the child element name to look for
|
||||
* @return the extracted text value,
|
||||
* or <code>null</code> if no child element found
|
||||
*/
|
||||
public static String getChildElementValueByTagName(final Element element, final String childElementName) {
|
||||
Element child = getChildElementByTagName(element, childElementName);
|
||||
return (child != null ? getTextValue(child) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the text value from the given DOM element, ignoring XML comments.
|
||||
* <p>Appends all CharacterData nodes and EntityReference nodes
|
||||
* into a single String value, excluding Comment nodes.
|
||||
*
|
||||
* @see CharacterData
|
||||
* @see EntityReference
|
||||
* @see Comment
|
||||
*/
|
||||
public static String getTextValue(final Element valueElement) {
|
||||
Assert.notNull(valueElement, "Element must not be null");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
NodeList nl = valueElement.getChildNodes();
|
||||
for (int i = 0; i < nl.getLength(); i++) {
|
||||
Node item = nl.item(i);
|
||||
if ((item instanceof CharacterData && !(item instanceof Comment)) || item instanceof EntityReference) {
|
||||
sb.append(item.getNodeValue());
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Namespace-aware equals comparison. Returns <code>true</code> if either
|
||||
* {@link Node#getLocalName} or {@link Node#getNodeName} equals <code>desiredName</code>,
|
||||
* otherwise returns <code>false</code>.
|
||||
*
|
||||
* @param node (required)
|
||||
* @param desiredName (required)
|
||||
* @return
|
||||
*/
|
||||
public static boolean nodeNameEquals(final Node node, final String desiredName) {
|
||||
Assert.notNull(node, "Node must not be null");
|
||||
Assert.notNull(desiredName, "Desired name must not be null");
|
||||
return nodeNameMatch(node, desiredName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the given node's name and local name against the given desired name.
|
||||
*
|
||||
* @param node
|
||||
* @param desiredName
|
||||
* @return
|
||||
*/
|
||||
private static boolean nodeNameMatch(final Node node, final String desiredName) {
|
||||
return (desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the given node's name and local name against the given desired names.
|
||||
*
|
||||
* @param node
|
||||
* @param desiredNames
|
||||
* @return
|
||||
*/
|
||||
private static boolean nodeNameMatch(final Node node, final Collection<?> desiredNames) {
|
||||
return (desiredNames.contains(node.getNodeName()) || desiredNames.contains(node.getLocalName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes empty text nodes from the specified node.
|
||||
*
|
||||
* @param node the element where empty text nodes will be removed
|
||||
*/
|
||||
public static void removeTextNodes(final Node node) {
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final NodeList children = node.getChildNodes();
|
||||
for (int i = children.getLength() - 1; i >= 0; i--) {
|
||||
final Node child = children.item(i);
|
||||
switch (child.getNodeType()) {
|
||||
case Node.ELEMENT_NODE:
|
||||
removeTextNodes(child);
|
||||
break;
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
case Node.TEXT_NODE:
|
||||
if (StringUtils.isBlank(child.getNodeValue())) {
|
||||
node.removeChild(child);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text content of the given {@link Node}, null safe.
|
||||
*
|
||||
* @param node can be <code>null</code>
|
||||
* @param defaultValue the value to return if the node is <code>null</code>
|
||||
* @return the given default value if the node is <code>null</code>
|
||||
* @see Node#getTextContent()
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static String getTextContent(final Node node, final String defaultValue) {
|
||||
if (node == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return node.getTextContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a child element with the given name and parent. Avoids the type
|
||||
* of bug whereby the developer calls {@link Document#createElement(String)}
|
||||
* but forgets to append it to the relevant parent.
|
||||
*
|
||||
* @param tagName the name of the new child (required)
|
||||
* @param parent the parent node (required)
|
||||
* @param document the document to which the parent and child belong (required)
|
||||
* @return the created element
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static Element createChildElement(final String tagName, final Node parent, final Document document) {
|
||||
final Element child = document.createElement(tagName);
|
||||
parent.appendChild(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child node with the given tag name, creating it if it does
|
||||
* not exist.
|
||||
*
|
||||
* @param tagName the child tag to look for and possibly create (required)
|
||||
* @param parent the parent in which to look for the child (required)
|
||||
* @param document the document containing the parent (required)
|
||||
* @return the existing or created child (never <code>null</code>)
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static Element createChildIfNotExists(final String tagName, final Node parent, final Document document) {
|
||||
final Element existingChild = XmlUtils.findFirstElement(tagName, parent);
|
||||
if (existingChild != null) {
|
||||
return existingChild;
|
||||
}
|
||||
// No such child; add it
|
||||
return createChildElement(tagName, parent, document);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text content of the first child of the given parent that has
|
||||
* the given tag name, if any.
|
||||
*
|
||||
* @param parent the parent in which to search (required)
|
||||
* @param child the child name for which to search (required)
|
||||
* @return <code>null</code> if there is no such child, otherwise the first
|
||||
* such child's text content
|
||||
*/
|
||||
public static String getChildTextContent(final Element parent, final String child) {
|
||||
final List<Element> children = XmlUtils.findElements(child, parent);
|
||||
if (children.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return getTextContent(children.get(0), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks in under a given root element whether it can find a child element
|
||||
* which matches the name supplied. Returns {@link Element} if exists.
|
||||
*
|
||||
* @param name the Element name (required)
|
||||
* @param root the parent DOM element (required)
|
||||
* @return the Element if discovered
|
||||
*/
|
||||
public static Element findFirstElementByName(final String name, final Element root) {
|
||||
Assert.hasText(name, "Element name required");
|
||||
Assert.notNull(root, "Root element required");
|
||||
return (Element) root.getElementsByTagName(name).item(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any elements matching the given XPath expression, relative to
|
||||
* the given Element
|
||||
*
|
||||
* @param xPath the XPath of the element(s) to remove (can be blank)
|
||||
* @param searchBase the element to which the XPath expression is relative
|
||||
*/
|
||||
public static void removeElements(final String xPath, final Element searchBase) {
|
||||
for (final Element elementToDelete : XmlUtils.findElements(xPath, searchBase)) {
|
||||
final Node parentNode = elementToDelete.getParentNode();
|
||||
parentNode.removeChild(elementToDelete);
|
||||
removeTextNodes(parentNode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private DomUtils() {}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.shell.support.util;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Methods for working with exceptions.
|
||||
*
|
||||
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Simple utility methods for file and stream copying. All copy methods use a block size of 4096 bytes, and close all affected streams when done.
|
||||
*
|
||||
* <p>
|
||||
* Mainly for use within the framework, but also useful for application code.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.0
|
||||
*/
|
||||
public final class FileCopyUtils {
|
||||
|
||||
public static final int BUFFER_SIZE = 4096;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Copy methods for java.io.File
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Copy the contents of the given input File to the given output File.
|
||||
*
|
||||
* @param in the file to copy from
|
||||
* @param out the file to copy to
|
||||
* @return the number of bytes copied
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static int copy(final File in, final File out) throws IOException {
|
||||
Assert.notNull(in, "No input File specified");
|
||||
Assert.notNull(out, "No output File specified");
|
||||
return copy(new BufferedInputStream(new FileInputStream(in)), new BufferedOutputStream(new FileOutputStream(out)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given byte array to the given output File.
|
||||
*
|
||||
* @param bytes the byte array to copy from
|
||||
* @param file the file to copy to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static void copy(final byte[] bytes, final File file) throws IOException {
|
||||
Assert.notNull(bytes, "No input byte array specified");
|
||||
Assert.notNull(file, "No output File specified");
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(bytes);
|
||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
|
||||
copy(in, out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given input File into a new byte array.
|
||||
*
|
||||
* @param in the file to copy from
|
||||
* @return the new byte array that has been copied to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static byte[] copyToByteArray(final File in) throws IOException {
|
||||
Assert.notNull(in, "No input File specified");
|
||||
return copyToByteArray(new BufferedInputStream(new FileInputStream(in)));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Copy methods for java.io.InputStream / java.io.OutputStream
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Copy the contents of the given InputStream to the given OutputStream. Closes both streams when done.
|
||||
*
|
||||
* @param in the stream to copy from
|
||||
* @param out the stream to copy to
|
||||
* @return the number of bytes copied
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static int copy(InputStream in, OutputStream out) throws IOException {
|
||||
Assert.notNull(in, "No InputStream specified");
|
||||
Assert.notNull(out, "No OutputStream specified");
|
||||
if (!(in instanceof BufferedInputStream)) {
|
||||
in = new BufferedInputStream(in);
|
||||
}
|
||||
if (!(out instanceof BufferedOutputStream)) {
|
||||
out = new BufferedOutputStream(out);
|
||||
}
|
||||
try {
|
||||
int byteCount = 0;
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
int bytesRead = -1;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
byteCount += bytesRead;
|
||||
}
|
||||
out.flush();
|
||||
return byteCount;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in, out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given byte array to the given OutputStream. Closes the stream when done.
|
||||
*
|
||||
* @param bytes the byte array to copy from
|
||||
* @param out the OutputStream to copy to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static void copy(final byte[] bytes, final OutputStream out) throws IOException {
|
||||
Assert.notNull(bytes, "No input byte array specified");
|
||||
Assert.notNull(out, "No OutputStream specified");
|
||||
try {
|
||||
out.write(bytes);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given InputStream into a new byte array. Closes the stream when done.
|
||||
*
|
||||
* @param in the stream to copy from
|
||||
* @return the new byte array that has been copied to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static byte[] copyToByteArray(final InputStream in) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
|
||||
copy(in, out);
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Copy methods for java.io.Reader / java.io.Writer
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Copy the contents of the given Reader to the given Writer. Closes both when done.
|
||||
*
|
||||
* @param in the Reader to copy from
|
||||
* @param out the Writer to copy to
|
||||
* @return the number of characters copied
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static int copy(Reader in, Writer out) throws IOException {
|
||||
Assert.notNull(in, "No Reader specified");
|
||||
Assert.notNull(out, "No Writer specified");
|
||||
if (!(in instanceof BufferedReader)) {
|
||||
in = new BufferedReader(in);
|
||||
}
|
||||
if (!(out instanceof BufferedWriter)) {
|
||||
out = new BufferedWriter(out);
|
||||
}
|
||||
try {
|
||||
int byteCount = 0;
|
||||
char[] buffer = new char[BUFFER_SIZE];
|
||||
int bytesRead = -1;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
byteCount += bytesRead;
|
||||
}
|
||||
out.flush();
|
||||
return byteCount;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in, out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given String to the given output Writer. Closes the writer when done.
|
||||
*
|
||||
* @param in the String to copy from
|
||||
* @param out the Writer to copy to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static void copy(final String in, Writer out) throws IOException {
|
||||
Assert.notNull(in, "No input String specified");
|
||||
Assert.notNull(out, "No Writer specified");
|
||||
if (!(out instanceof BufferedWriter)) {
|
||||
out = new BufferedWriter(out);
|
||||
}
|
||||
try {
|
||||
out.write(in);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given Reader into a String. Closes the reader when done.
|
||||
*
|
||||
* @param in the reader to copy from
|
||||
* @return the String that has been copied to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static String copyToString(final Reader in) throws IOException {
|
||||
StringWriter out = new StringWriter();
|
||||
copy(in, out);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the given File as a String.
|
||||
* <p>
|
||||
* Consider using {@link FileUtils#read(File)} instead if any
|
||||
* {@link IOException}s would be unrecoverable.
|
||||
*
|
||||
* @param file the file to read from
|
||||
* @return the contents
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static String copyToString(final File file) throws IOException {
|
||||
return copyToString(new BufferedReader(new FileReader(file)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private FileCopyUtils() {}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -17,6 +17,7 @@ package org.springframework.shell.support.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -27,6 +28,12 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Utilities for handling {@link File} instances.
|
||||
@@ -157,8 +164,8 @@ public final class FileUtils {
|
||||
/**
|
||||
* Returns the part of the given path that represents a directory, in other
|
||||
* words the given path if it's already a directory, or the parent directory
|
||||
* if it's a file.
|
||||
*
|
||||
* if it's a file.
|
||||
*
|
||||
* @param fileIdentifier the path to parse (required)
|
||||
* @return see above
|
||||
* @since 1.2.0
|
||||
@@ -173,7 +180,7 @@ public final class FileUtils {
|
||||
|
||||
/**
|
||||
* Returns the given file system path minus its last element
|
||||
*
|
||||
*
|
||||
* @param fileIdentifier
|
||||
* @return
|
||||
* @since 1.2.0
|
||||
@@ -186,21 +193,21 @@ public final class FileUtils {
|
||||
|
||||
/**
|
||||
* Removes any trailing {@link File#separator}s from the given path
|
||||
*
|
||||
*
|
||||
* @param path the path to modify (can be <code>null</code>)
|
||||
* @return the modified path
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static String removeTrailingSeparator(String path) {
|
||||
while (path != null && path.endsWith(File.separator)) {
|
||||
path = StringUtils.removeSuffix(path, File.separator);
|
||||
path = path.substring(0, path.length() - File.separator.length());
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the given canonical path matches the given Ant-style pattern
|
||||
*
|
||||
*
|
||||
* @param antPattern the pattern to check against (can't be blank)
|
||||
* @param canonicalPath the path to check (can't be blank)
|
||||
* @return see above
|
||||
@@ -214,27 +221,27 @@ public final class FileUtils {
|
||||
|
||||
/**
|
||||
* Removes any leading or trailing {@link File#separator}s from the given path.
|
||||
*
|
||||
*
|
||||
* @param path the path to modify (can be <code>null</code>)
|
||||
* @return the path, modified as above, or <code>null</code> if <code>null</code> was given
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static String removeLeadingAndTrailingSeparators(String path) {
|
||||
if (StringUtils.isBlank(path)) {
|
||||
if (!StringUtils.hasText(path)) {
|
||||
return path;
|
||||
}
|
||||
while (path.endsWith(File.separator)) {
|
||||
path = StringUtils.removeSuffix(path, File.separator);
|
||||
path = path.substring(0, path.length() - File.separator.length());
|
||||
}
|
||||
while (path.startsWith(File.separator)) {
|
||||
path = StringUtils.removePrefix(path, File.separator);
|
||||
path = path.substring(File.separator.length());
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the given path has exactly one trailing {@link File#separator}
|
||||
*
|
||||
*
|
||||
* @param path the path to modify (can't be <code>null</code>)
|
||||
* @return the normalised path
|
||||
* @since 1.2.0
|
||||
@@ -247,7 +254,7 @@ public final class FileUtils {
|
||||
/**
|
||||
* Returns an operating-system-dependent path consisting of the given
|
||||
* elements, separated by {@link File#separator}.
|
||||
*
|
||||
*
|
||||
* @param pathElements the path elements from uppermost downwards (can't be empty)
|
||||
* @return a non-blank string
|
||||
* @since 1.2.0
|
||||
@@ -259,7 +266,7 @@ public final class FileUtils {
|
||||
/**
|
||||
* Returns an operating-system-dependent path consisting of the given
|
||||
* elements, separated by {@link File#separator}.
|
||||
*
|
||||
*
|
||||
* @param pathElements the path elements from uppermost downwards (can't be empty)
|
||||
* @return a non-blank string
|
||||
* @since 1.2.0
|
||||
@@ -289,7 +296,7 @@ public final class FileUtils {
|
||||
|
||||
/**
|
||||
* Returns the platform-specific file separator as a regular expression.
|
||||
*
|
||||
*
|
||||
* @return a non-blank regex
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@@ -352,13 +359,13 @@ public final class FileUtils {
|
||||
|
||||
/**
|
||||
* Reads a banner from the given resource. Performs conversion of any line separator contained by the source to that of the running platform.
|
||||
*
|
||||
*
|
||||
* @return platform-compatible banner as a String
|
||||
*/
|
||||
public static String readBanner(Reader reader) {
|
||||
try {
|
||||
String content = FileCopyUtils.copyToString(new BufferedReader(reader));
|
||||
return content.replaceAll("(\\r|\\n)+", StringUtils.LINE_SEPARATOR);
|
||||
return content.replaceAll("(\\r|\\n)+", OsUtils.LINE_SEPARATOR);
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("Cannot read stream", ex);
|
||||
}
|
||||
@@ -366,7 +373,7 @@ public final class FileUtils {
|
||||
|
||||
/**
|
||||
* Reads a banner from the given resource. Performs conversion of any line separator contained by the source to that of the running platform.
|
||||
*
|
||||
*
|
||||
* @return platform-compatible banner as a String
|
||||
*/
|
||||
public static String readBanner(final Class<?> loadingClass, String resourceName) {
|
||||
@@ -383,7 +390,7 @@ public final class FileUtils {
|
||||
*/
|
||||
public static String read(final File file) {
|
||||
try {
|
||||
return FileCopyUtils.copyToString(file);
|
||||
return FileCopyUtils.copyToString(new FileReader(file));
|
||||
} catch (final IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
@@ -391,7 +398,7 @@ public final class FileUtils {
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
private FileUtils() {
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
/**
|
||||
* Allows filtering of objects of type T.
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
* @param <T> the type of object to be filtered
|
||||
*/
|
||||
public interface Filter<T> {
|
||||
|
||||
/**
|
||||
* Indicates whether to include the given instance in the filtered results
|
||||
*
|
||||
* @param type the type to evaluate; can be <code>null</code>
|
||||
* @return <code>false</code> to exclude the given type
|
||||
*/
|
||||
boolean include(T instance);
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
/**
|
||||
* Encodes a given byte array as hex.
|
||||
*
|
||||
* <p>
|
||||
* Most methods in this class were obtained from the Spring Security class,
|
||||
* org.springframework.security.core.codec.Hex. Spring Security is licensed
|
||||
* under the Apache Software License version 2.0 and the following code is used
|
||||
* pursuant to that license.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @author Ben Alex
|
||||
* @since 1.1.1
|
||||
*/
|
||||
public abstract class HexUtils {
|
||||
|
||||
public static String toHex(final byte[] bytes) {
|
||||
return new String(encode(bytes));
|
||||
}
|
||||
|
||||
private static final char[] HEX = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
|
||||
};
|
||||
|
||||
public static char[] encode(final byte[] bytes) {
|
||||
final int nBytes = bytes.length;
|
||||
char[] result = new char[2 * nBytes];
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < nBytes; i++) {
|
||||
// Char for top 4 bits
|
||||
result[j++] = HEX[(0xF0 & bytes[i]) >>> 4];
|
||||
|
||||
// Bottom 4
|
||||
result[j++] = HEX[(0x0F & bytes[i])];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Provides extra functionality for Java Number classes.
|
||||
*
|
||||
* @author Alan Stewart
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public final class NumberUtils {
|
||||
|
||||
/**
|
||||
* Returns the minimum value in the array.
|
||||
*
|
||||
* @param array an array of Numbers (can be <code>null</code>)
|
||||
* @return the minimum value in the array, or null if all the elements are null
|
||||
*/
|
||||
public static BigDecimal min(final Number... array) {
|
||||
return minOrMax(true, array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum value in the array.
|
||||
*
|
||||
* @param array an array of Numbers (can be <code>null</code>)
|
||||
* @return the maximum value in the array, or null if all the elements are null
|
||||
*/
|
||||
public static BigDecimal max(final Number... array) {
|
||||
return minOrMax(false, array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the minimum or maxiumum value contained in the given array,
|
||||
* ignoring any <code>null</code> elements
|
||||
*
|
||||
* @param findMinimum <code>false</code> to get the maximum
|
||||
* @param numbers can be <code>null</code>, empty, or contain <code>null</code>
|
||||
* elements
|
||||
* @return <code>null</code> if the array is <code>null</code>, empty, or
|
||||
* all its elements are <code>null</code>
|
||||
*/
|
||||
private static BigDecimal minOrMax(final boolean findMinimum, final Number... numbers) {
|
||||
if (numbers == null || numbers.length == 0) {
|
||||
return null;
|
||||
}
|
||||
BigDecimal extreme = null;
|
||||
for (final Number number : numbers) {
|
||||
if (number != null) {
|
||||
final BigDecimal candidate = getBigDecimal(number);
|
||||
if (extreme == null || (findMinimum ? candidate.compareTo(extreme) < 0 : candidate.compareTo(extreme) > 0)) {
|
||||
// The non-null candidate is the new extreme
|
||||
extreme = candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
return extreme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given number to a {@link BigDecimal}
|
||||
*
|
||||
* @param number the number to convert (can be <code>null</code>)
|
||||
* @return <code>null</code> if the given number was <code>null</code>
|
||||
*/
|
||||
private static BigDecimal getBigDecimal(final Number number) {
|
||||
if (number == null || number instanceof BigDecimal) {
|
||||
return (BigDecimal) number;
|
||||
}
|
||||
if (number instanceof BigInteger) {
|
||||
return new BigDecimal((BigInteger) number);
|
||||
}
|
||||
return new BigDecimal(number.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private NumberUtils() {}
|
||||
}
|
||||
@@ -1,940 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Miscellaneous object utility methods. Mainly for internal use within the
|
||||
* framework; consider Jakarta's Commons Lang for a more comprehensive suite
|
||||
* of object utilities.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Keith Donald
|
||||
* @author Rod Johnson
|
||||
* @author Rob Harrop
|
||||
* @author Alex Ruiz
|
||||
* @see org.apache.commons.lang.ObjectUtils
|
||||
*/
|
||||
public final class ObjectUtils {
|
||||
|
||||
// Constants
|
||||
private static final int INITIAL_HASH = 7;
|
||||
private static final int MULTIPLIER = 31;
|
||||
|
||||
private static final String EMPTY_STRING = "";
|
||||
private static final String NULL_STRING = "null";
|
||||
private static final String ARRAY_START = "{";
|
||||
private static final String ARRAY_END = "}";
|
||||
private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
|
||||
private static final String ARRAY_ELEMENT_SEPARATOR = ", ";
|
||||
|
||||
/**
|
||||
* Return whether the given throwable is a checked exception:
|
||||
* that is, neither a RuntimeException nor an Error.
|
||||
*
|
||||
* @param ex the throwable to check
|
||||
* @return whether the throwable is a checked exception
|
||||
* @see java.lang.Exception
|
||||
* @see java.lang.RuntimeException
|
||||
* @see java.lang.Error
|
||||
*/
|
||||
public static boolean isCheckedException(final Throwable ex) {
|
||||
return !(ex instanceof RuntimeException || ex instanceof Error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given exception is compatible with the exceptions
|
||||
* declared in a throws clause.
|
||||
*
|
||||
* @param ex the exception to checked
|
||||
* @param declaredExceptions the exceptions declared in the throws clause
|
||||
* @return whether the given exception is compatible
|
||||
*/
|
||||
public static boolean isCompatibleWithThrowsClause(final Throwable ex, final Class<?>... declaredExceptions) {
|
||||
if (!isCheckedException(ex)) {
|
||||
return true;
|
||||
}
|
||||
if (declaredExceptions != null) {
|
||||
int i = 0;
|
||||
while (i < declaredExceptions.length) {
|
||||
if (declaredExceptions[i].isAssignableFrom(ex.getClass())) {
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given array is empty: that is, <code>null</code>
|
||||
* or of zero length.
|
||||
*
|
||||
* @param array the array to check
|
||||
* @return whether the given array is empty
|
||||
*/
|
||||
public static boolean isEmpty(final Object[] array) {
|
||||
return array == null || array.length == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given array contains the given element.
|
||||
*
|
||||
* @param array the array to check (may be <code>null</code>,
|
||||
* in which case the return value will always be <code>false</code>)
|
||||
* @param element the element to check for
|
||||
* @return whether the element has been found in the given array
|
||||
*/
|
||||
public static boolean containsElement(final Object[] array, final Object element) {
|
||||
if (array == null) {
|
||||
return false;
|
||||
}
|
||||
for (Object arrayEle : array) {
|
||||
if (nullSafeEquals(arrayEle, element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the given Object to the given array, returning a new array
|
||||
* consisting of the input array contents plus the given Object.
|
||||
*
|
||||
* @param array the array to append to (can be <code>null</code>)
|
||||
* @param obj the Object to append
|
||||
* @return the new array (of the same component type; never <code>null</code>)
|
||||
*/
|
||||
public static Object[] addObjectToArray(final Object[] array, final Object obj) {
|
||||
Class<?> compType = Object.class;
|
||||
if (array != null) {
|
||||
compType = array.getClass().getComponentType();
|
||||
}
|
||||
else if (obj != null) {
|
||||
compType = obj.getClass();
|
||||
}
|
||||
int newArrLength = (array != null ? array.length + 1 : 1);
|
||||
Object[] newArr = (Object[]) Array.newInstance(compType, newArrLength);
|
||||
if (array != null) {
|
||||
System.arraycopy(array, 0, newArr, 0, array.length);
|
||||
}
|
||||
newArr[newArr.length - 1] = obj;
|
||||
return newArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given array (which may be a primitive array) to an
|
||||
* object array (if necessary of primitive wrapper objects).
|
||||
* <p>A <code>null</code> source value will be converted to an
|
||||
* empty Object array.
|
||||
*
|
||||
* @param source the (potentially primitive) array
|
||||
* @return the corresponding object array (never <code>null</code>)
|
||||
* @throws IllegalArgumentException if the parameter is not an array
|
||||
*/
|
||||
public static Object[] toObjectArray(final Object source) {
|
||||
if (source instanceof Object[]) {
|
||||
return (Object[]) source;
|
||||
}
|
||||
if (source == null) {
|
||||
return new Object[0];
|
||||
}
|
||||
if (!source.getClass().isArray()) {
|
||||
throw new IllegalArgumentException("Source is not an array: " + source);
|
||||
}
|
||||
int length = Array.getLength(source);
|
||||
if (length == 0) {
|
||||
return new Object[0];
|
||||
}
|
||||
Class<?> wrapperType = Array.get(source, 0).getClass();
|
||||
Object[] newArray = (Object[]) Array.newInstance(wrapperType, length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
newArray[i] = Array.get(source, i);
|
||||
}
|
||||
return newArray;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Convenience methods for content-based equality/hash-code handling
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determine if the given objects are equal, returning <code>true</code>
|
||||
* if both are <code>null</code> or <code>false</code> if only one is
|
||||
* <code>null</code>.
|
||||
* <p>Compares arrays with <code>Arrays.equals</code>, performing an equality
|
||||
* check based on the array elements rather than the array reference.
|
||||
*
|
||||
* @param o1 first Object to compare
|
||||
* @param o2 second Object to compare
|
||||
* @return whether the given objects are equal
|
||||
* @see java.util.Arrays#equals
|
||||
*/
|
||||
public static boolean nullSafeEquals(final Object o1, final Object o2) {
|
||||
if (o1 == o2) {
|
||||
return true;
|
||||
}
|
||||
if (o1 == null || o2 == null) {
|
||||
return false;
|
||||
}
|
||||
if (o1.equals(o2)) {
|
||||
return true;
|
||||
}
|
||||
if (o1.getClass().isArray() && o2.getClass().isArray()) {
|
||||
if (o1 instanceof Object[] && o2 instanceof Object[]) {
|
||||
return Arrays.equals((Object[]) o1, (Object[]) o2);
|
||||
}
|
||||
if (o1 instanceof boolean[] && o2 instanceof boolean[]) {
|
||||
return Arrays.equals((boolean[]) o1, (boolean[]) o2);
|
||||
}
|
||||
if (o1 instanceof byte[] && o2 instanceof byte[]) {
|
||||
return Arrays.equals((byte[]) o1, (byte[]) o2);
|
||||
}
|
||||
if (o1 instanceof char[] && o2 instanceof char[]) {
|
||||
return Arrays.equals((char[]) o1, (char[]) o2);
|
||||
}
|
||||
if (o1 instanceof double[] && o2 instanceof double[]) {
|
||||
return Arrays.equals((double[]) o1, (double[]) o2);
|
||||
}
|
||||
if (o1 instanceof float[] && o2 instanceof float[]) {
|
||||
return Arrays.equals((float[]) o1, (float[]) o2);
|
||||
}
|
||||
if (o1 instanceof int[] && o2 instanceof int[]) {
|
||||
return Arrays.equals((int[]) o1, (int[]) o2);
|
||||
}
|
||||
if (o1 instanceof long[] && o2 instanceof long[]) {
|
||||
return Arrays.equals((long[]) o1, (long[]) o2);
|
||||
}
|
||||
if (o1 instanceof short[] && o2 instanceof short[]) {
|
||||
return Arrays.equals((short[]) o1, (short[]) o2);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return as hash code for the given object; typically the value of
|
||||
* <code>{@link Object#hashCode()}</code>. If the object is an array,
|
||||
* this method will delegate to any of the <code>nullSafeHashCode</code>
|
||||
* methods for arrays in this class. If the object is <code>null</code>,
|
||||
* this method returns 0.
|
||||
*
|
||||
* @see #nullSafeHashCode(Object[])
|
||||
* @see #nullSafeHashCode(boolean[])
|
||||
* @see #nullSafeHashCode(byte[])
|
||||
* @see #nullSafeHashCode(char[])
|
||||
* @see #nullSafeHashCode(double[])
|
||||
* @see #nullSafeHashCode(float[])
|
||||
* @see #nullSafeHashCode(int[])
|
||||
* @see #nullSafeHashCode(long[])
|
||||
* @see #nullSafeHashCode(short[])
|
||||
*/
|
||||
public static int nullSafeHashCode(final Object obj) {
|
||||
if (obj == null) {
|
||||
return 0;
|
||||
}
|
||||
if (obj.getClass().isArray()) {
|
||||
if (obj instanceof Object[]) {
|
||||
return nullSafeHashCode((Object[]) obj);
|
||||
}
|
||||
if (obj instanceof boolean[]) {
|
||||
return nullSafeHashCode((boolean[]) obj);
|
||||
}
|
||||
if (obj instanceof byte[]) {
|
||||
return nullSafeHashCode((byte[]) obj);
|
||||
}
|
||||
if (obj instanceof char[]) {
|
||||
return nullSafeHashCode((char[]) obj);
|
||||
}
|
||||
if (obj instanceof double[]) {
|
||||
return nullSafeHashCode((double[]) obj);
|
||||
}
|
||||
if (obj instanceof float[]) {
|
||||
return nullSafeHashCode((float[]) obj);
|
||||
}
|
||||
if (obj instanceof int[]) {
|
||||
return nullSafeHashCode((int[]) obj);
|
||||
}
|
||||
if (obj instanceof long[]) {
|
||||
return nullSafeHashCode((long[]) obj);
|
||||
}
|
||||
if (obj instanceof short[]) {
|
||||
return nullSafeHashCode((short[]) obj);
|
||||
}
|
||||
}
|
||||
return obj.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array the array from whose elements to calculate the hash code (can be <code>null</code>)
|
||||
* @return 0 if the array is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final Object... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
for (final Object element : array) {
|
||||
hash = MULTIPLIER * hash + nullSafeHashCode(element);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array can be <code>null</code>
|
||||
* @return 0 if <code>array</code> is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final boolean... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
int arraySize = array.length;
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
hash = MULTIPLIER * hash + hashCode(array[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array can be <code>null</code>
|
||||
* @return 0 if <code>array</code> is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final byte... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
int arraySize = array.length;
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
hash = MULTIPLIER * hash + array[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array can be <code>null</code>
|
||||
* @return 0 if <code>array</code> is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final char... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
int arraySize = array.length;
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
hash = MULTIPLIER * hash + array[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array can be <code>null</code>
|
||||
* @return 0 if <code>array</code> is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final double... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
int arraySize = array.length;
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
hash = MULTIPLIER * hash + hashCode(array[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array can be <code>null</code>
|
||||
* @return 0 if <code>array</code> is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final float... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
int arraySize = array.length;
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
hash = MULTIPLIER * hash + hashCode(array[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array can be <code>null</code>
|
||||
* @return 0 if <code>array</code> is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final int... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
int arraySize = array.length;
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
hash = MULTIPLIER * hash + array[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array can be <code>null</code>
|
||||
* @return 0 if <code>array</code> is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final long... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
int arraySize = array.length;
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
hash = MULTIPLIER * hash + hashCode(array[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash code based on the contents of the specified array.
|
||||
*
|
||||
* @param array can be <code>null</code>
|
||||
* @return 0 if <code>array</code> is <code>null</code>
|
||||
*/
|
||||
public static int nullSafeHashCode(final short... array) {
|
||||
if (array == null) {
|
||||
return 0;
|
||||
}
|
||||
int hash = INITIAL_HASH;
|
||||
int arraySize = array.length;
|
||||
for (int i = 0; i < arraySize; i++) {
|
||||
hash = MULTIPLIER * hash + array[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash code of the given boolean value.
|
||||
*
|
||||
* @param bool the boolean for which to return the hash code
|
||||
* @return see {@link Boolean#hashCode()}
|
||||
*/
|
||||
public static int hashCode(final boolean bool) {
|
||||
return Boolean.valueOf(bool).hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the same value as <code>{@link Double#hashCode()}</code>.
|
||||
*
|
||||
* @see Double#hashCode()
|
||||
*/
|
||||
public static int hashCode(final double dbl) {
|
||||
long bits = Double.doubleToLongBits(dbl);
|
||||
return hashCode(bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the same value as <code>{@link Float#hashCode()}</code>.
|
||||
*
|
||||
* @see Float#hashCode()
|
||||
*/
|
||||
public static int hashCode(final float flt) {
|
||||
return Float.floatToIntBits(flt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the same value as <code>{@link Long#hashCode()}</code>.
|
||||
*
|
||||
* @see Long#hashCode()
|
||||
*/
|
||||
public static int hashCode(final long lng) {
|
||||
return (int) (lng ^ (lng >>> 32));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Convenience methods for toString output
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return a String representation of an object's overall identity.
|
||||
*
|
||||
* @param obj the object (may be <code>null</code>)
|
||||
* @return the object's identity as String representation,
|
||||
* or an empty String if the object was <code>null</code>
|
||||
*/
|
||||
public static String identityToString(final Object obj) {
|
||||
if (obj == null) {
|
||||
return EMPTY_STRING;
|
||||
}
|
||||
return obj.getClass().getName() + "@" + getIdentityHexString(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hex String form of an object's identity hash code.
|
||||
*
|
||||
* @param obj the object
|
||||
* @return the object's identity code in hex notation
|
||||
*/
|
||||
public static String getIdentityHexString(final Object obj) {
|
||||
return Integer.toHexString(System.identityHashCode(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a content-based String representation if <code>obj</code> is
|
||||
* not <code>null</code>; otherwise returns an empty String.
|
||||
* <p>Differs from {@link #nullSafeToString(Object)} in that it returns
|
||||
* an empty String rather than "null" for a <code>null</code> value.
|
||||
*
|
||||
* @param obj the object to build a display String for
|
||||
* @return a display String representation of <code>obj</code>
|
||||
* @see #nullSafeToString(Object)
|
||||
*/
|
||||
public static String getDisplayString(final Object obj) {
|
||||
if (obj == null) {
|
||||
return EMPTY_STRING;
|
||||
}
|
||||
return nullSafeToString(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the class name for the given object.
|
||||
* <p>Returns <code>"null"</code> if <code>obj</code> is <code>null</code>.
|
||||
*
|
||||
* @param obj the object to introspect (may be <code>null</code>)
|
||||
* @return the corresponding class name
|
||||
*/
|
||||
public static String nullSafeClassName(final Object obj) {
|
||||
return (obj != null ? obj.getClass().getName() : NULL_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the specified Object.
|
||||
* <p>Builds a String representation of the contents in case of an array.
|
||||
* Returns <code>"null"</code> if <code>obj</code> is <code>null</code>.
|
||||
*
|
||||
* @param obj the object to build a String representation for
|
||||
* @return a String representation of <code>obj</code>
|
||||
*/
|
||||
public static String nullSafeToString(final Object obj) {
|
||||
if (obj == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
return (String) obj;
|
||||
}
|
||||
if (obj instanceof Object[]) {
|
||||
return nullSafeToString((Object[]) obj);
|
||||
}
|
||||
if (obj instanceof boolean[]) {
|
||||
return nullSafeToString((boolean[]) obj);
|
||||
}
|
||||
if (obj instanceof byte[]) {
|
||||
return nullSafeToString((byte[]) obj);
|
||||
}
|
||||
if (obj instanceof char[]) {
|
||||
return nullSafeToString((char[]) obj);
|
||||
}
|
||||
if (obj instanceof double[]) {
|
||||
return nullSafeToString((double[]) obj);
|
||||
}
|
||||
if (obj instanceof float[]) {
|
||||
return nullSafeToString((float[]) obj);
|
||||
}
|
||||
if (obj instanceof int[]) {
|
||||
return nullSafeToString((int[]) obj);
|
||||
}
|
||||
if (obj instanceof long[]) {
|
||||
return nullSafeToString((long[]) obj);
|
||||
}
|
||||
if (obj instanceof short[]) {
|
||||
return nullSafeToString((short[]) obj);
|
||||
}
|
||||
String str = obj.toString();
|
||||
return (str != null ? str : EMPTY_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final Object... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
sb.append(String.valueOf(array[i]));
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final boolean... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
|
||||
sb.append(array[i]);
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final byte... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
sb.append(array[i]);
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final char... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
sb.append("'").append(array[i]).append("'");
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final double... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
|
||||
sb.append(array[i]);
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final float... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
|
||||
sb.append(array[i]);
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final int... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
sb.append(array[i]);
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final long... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
sb.append(array[i]);
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String representation of the contents of the specified array.
|
||||
* <p>The String representation consists of a list of the array's elements,
|
||||
* enclosed in curly braces (<code>"{}"</code>). Adjacent elements are separated
|
||||
* by the characters <code>", "</code> (a comma followed by a space). Returns
|
||||
* <code>"null"</code> if <code>array</code> is <code>null</code>.
|
||||
*
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of <code>array</code>
|
||||
*/
|
||||
public static String nullSafeToString(final short... array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
int length = array.length;
|
||||
if (length == 0) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
sb.append(ARRAY_START);
|
||||
}
|
||||
else {
|
||||
sb.append(ARRAY_ELEMENT_SEPARATOR);
|
||||
}
|
||||
sb.append(array[i]);
|
||||
}
|
||||
sb.append(ARRAY_END);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the two given objects, with <code>null</code> equivalent to
|
||||
* <code>null</code> and <code>null</code> "less than" any
|
||||
* non-<code>null</code> instance. Two non-<code>null</code> instances are
|
||||
* compared using the first one's {@link Comparable#compareTo(Object)}
|
||||
* method.
|
||||
*
|
||||
* @param <T> the type of objects being compared
|
||||
* @param one the first object being compared (can be <code>null</code>)
|
||||
* @param other the second object being compared (can be <code>null</code>)
|
||||
* @return see {@link Comparable#compareTo(Object)}
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static <T> int nullSafeComparison(final Comparable<T> one, final T other) {
|
||||
if (one == null) {
|
||||
if (other == null) {
|
||||
return 0;
|
||||
}
|
||||
// First is null, second is not
|
||||
return -1;
|
||||
}
|
||||
// If we get here, the first object is non-null
|
||||
if (other == null) {
|
||||
return 1;
|
||||
}
|
||||
return one.compareTo(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String representation of the given object, or if it's
|
||||
* <code>null</code>, the given default string
|
||||
*
|
||||
* @param object the object to represent as a String (can be <code>null</code>)
|
||||
* @param defaultValue the value to return if the given object is <code>null</code> (can itself be blank)
|
||||
* @return see above
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static String toString(final Object object, final String defaultValue) {
|
||||
if (object == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return object.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given object if not <code>null</code>, otherwise the given
|
||||
* default value
|
||||
*
|
||||
* @param <T> the type of object being defaulted
|
||||
* @param object the object to check (can be <code>null</code>)
|
||||
* @param defaultValue the default value (can be <code>null</code>)
|
||||
* @return <code>null</code> iff both values are <code>null</code>
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static <T> T defaultIfNull(final T object, final T defaultValue) {
|
||||
if (object == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private ObjectUtils() {}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -22,6 +22,9 @@ package org.springframework.shell.support.util;
|
||||
* @since 1.1.1
|
||||
*/
|
||||
public class OsUtils {
|
||||
|
||||
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||
|
||||
private static final boolean WINDOWS_OS = System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
|
||||
public static boolean isWindows() {
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
/**
|
||||
* A pair with a key of type "K" and a value of type "V". Instances are immutable.
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
* @param <K> the key type
|
||||
* @param <V> the value type
|
||||
*/
|
||||
public class Pair<K, V> {
|
||||
|
||||
// Fields
|
||||
private final K key;
|
||||
private final V value;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param key can be <code>null</code>
|
||||
* @param value can be <code>null</code>
|
||||
*/
|
||||
public Pair(final K key, final V value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key
|
||||
*
|
||||
* @return <code>null</code> if it is
|
||||
*/
|
||||
public K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value
|
||||
*
|
||||
* @return <code>null</code> if it is
|
||||
*/
|
||||
public V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof Pair)) {
|
||||
return false;
|
||||
}
|
||||
final Pair<?, ?> otherPair = (Pair<?, ?>) obj;
|
||||
return ObjectUtils.nullSafeEquals(key, otherPair.getKey()) && ObjectUtils.nullSafeEquals(value, otherPair.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ObjectUtils.nullSafeHashCode(new Object[] {getKey(), getValue()});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("key: ").append(key);
|
||||
sb.append(", value: ").append(value);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link List} of {@link Pair}s. Unlike a {@link java.util.Map}, it can have
|
||||
* duplicate and/or <code>null</code> keys.
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
* @param <K> the type of key
|
||||
* @param <V> the type of value
|
||||
*/
|
||||
public class PairList<K, V> extends ArrayList<Pair<K, V>> {
|
||||
|
||||
// For serialisation
|
||||
private static final long serialVersionUID = 5990417235907246300L;
|
||||
|
||||
/**
|
||||
* Returns the given array of pairs as a modifiable list
|
||||
*
|
||||
* @param <K> the type of key
|
||||
* @param <V> the type of value
|
||||
* @param pairs the pairs to put in a list
|
||||
* @return a non-<code>null</code> list
|
||||
*/
|
||||
public PairList(final Pair<K, V>... pairs) {
|
||||
addAll(Arrays.asList(pairs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for building a list of the given key-value pairs
|
||||
*
|
||||
* @param keys the keys (can be null)
|
||||
* @param values the values (must be null if the keys are null, otherwise
|
||||
* must be non-null and of the same size as the keys)
|
||||
*/
|
||||
public PairList(final List<? extends K> keys, final List<? extends V> values) {
|
||||
Assert.isTrue(!(keys == null ^ values == null), "Parameter types and names must either both be null or both be not null");
|
||||
if (keys == null) {
|
||||
Assert.isTrue(values == null, "Parameter names must be null if types are null");
|
||||
}
|
||||
else {
|
||||
Assert.isTrue(values != null, "Parameter names are required if types are provided");
|
||||
Assert.isTrue(keys.size() == values.size(), "Expected " + keys.size() + " values but found " + values.size());
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
add(keys.get(i), values.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an empty list of pairs
|
||||
*/
|
||||
public PairList() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the keys of each {@link Pair} in this list
|
||||
*
|
||||
* @return a non-<code>null</code> list
|
||||
*/
|
||||
public List<K> getKeys() {
|
||||
final List<K> keys = new ArrayList<K>();
|
||||
for (final Pair<K, ?> pair : this) {
|
||||
keys.add(pair.getKey());
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values of each {@link Pair} in this list
|
||||
*
|
||||
* @return a non-<code>null</code> modifiable copy of this list
|
||||
*/
|
||||
public List<V> getValues() {
|
||||
final List<V> values = new ArrayList<V>();
|
||||
for (final Pair<?, V> pair : this) {
|
||||
values.add(pair.getValue());
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new pair to this list with the given key and value
|
||||
*
|
||||
* @param key the key to add; can be <code>null</code>
|
||||
* @param value the value to add; can be <code>null</code>
|
||||
* @return true (as specified by Collection.add(E))
|
||||
*/
|
||||
public boolean add(final K key, final V value) {
|
||||
return add(new Pair<K, V>(key, value));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Pair<K, V>[] toArray() {
|
||||
return super.toArray(new Pair[size()]);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Strategy interface for <code>String</code>-based path matching.
|
||||
*
|
||||
* <p>The default implementation is {@link AntPathMatcher}, supporting the
|
||||
* Ant-style pattern syntax.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.2.0
|
||||
* @see AntPathMatcher
|
||||
*/
|
||||
public interface PathMatcher {
|
||||
|
||||
/**
|
||||
* Does the given <code>path</code> represent a pattern that can be matched
|
||||
* by an implementation of this interface?
|
||||
* <p>If the return value is <code>false</code>, then the {@link #match}
|
||||
* method does not have to be used because direct equality comparisons
|
||||
* on the static path Strings will lead to the same result.
|
||||
* @param path the path String to check
|
||||
* @return <code>true</code> if the given <code>path</code> represents a pattern
|
||||
*/
|
||||
boolean isPattern(String path);
|
||||
|
||||
/**
|
||||
* Match the given <code>path</code> against the given <code>pattern</code>,
|
||||
* according to this PathMatcher's matching strategy.
|
||||
* @param pattern the pattern to match against
|
||||
* @param path the path String to test
|
||||
* @return <code>true</code> if the supplied <code>path</code> matched,
|
||||
* <code>false</code> if it didn't
|
||||
*/
|
||||
boolean match(String pattern, String path);
|
||||
|
||||
/**
|
||||
* Match the given <code>path</code> against the corresponding part of the given
|
||||
* <code>pattern</code>, according to this PathMatcher's matching strategy.
|
||||
* <p>Determines whether the pattern at least matches as far as the given base
|
||||
* path goes, assuming that a full path may then match as well.
|
||||
* @param pattern the pattern to match against
|
||||
* @param path the path String to test
|
||||
* @return <code>true</code> if the supplied <code>path</code> matched,
|
||||
* <code>false</code> if it didn't
|
||||
*/
|
||||
boolean matchStart(String pattern, String path);
|
||||
|
||||
/**
|
||||
* Given a pattern and a full path, determine the pattern-mapped part.
|
||||
* <p>This method is supposed to find out which part of the path is matched
|
||||
* dynamically through an actual pattern, that is, it strips off a statically
|
||||
* defined leading path from the given full path, returning only the actually
|
||||
* pattern-matched part of the path.
|
||||
* <p>For example: For "myroot/*.html" as pattern and "myroot/myfile.html"
|
||||
* as full path, this method should return "myfile.html". The detailed
|
||||
* determination rules are specified to this PathMatcher's matching strategy.
|
||||
* <p>A simple implementation may return the given full path as-is in case
|
||||
* of an actual pattern, and the empty String in case of the pattern not
|
||||
* containing any dynamic parts (i.e. the <code>pattern</code> parameter being
|
||||
* a static path that wouldn't qualify as an actual {@link #isPattern pattern}).
|
||||
* A sophisticated implementation will differentiate between the static parts
|
||||
* and the dynamic parts of the given path pattern.
|
||||
* @param pattern the path pattern
|
||||
* @param path the full path to introspect
|
||||
* @return the pattern-mapped part of the given <code>path</code>
|
||||
* (never <code>null</code>)
|
||||
*/
|
||||
String extractPathWithinPattern(String pattern, String path);
|
||||
|
||||
/**
|
||||
* Given a pattern and a full path, extract the URI template variables. URI template
|
||||
* variables are expressed through curly brackets ('{' and '}').
|
||||
*
|
||||
* <p>For example: For pattern "/hotels/{hotel}" and path "/hotels/1", this method will
|
||||
* return a map containing "hotel"->"1".
|
||||
*
|
||||
* @param pattern the path pattern, possibly containing URI templates
|
||||
* @param path the full path to extract template variables from
|
||||
* @return a map, containing variable names as keys; variables values as values
|
||||
*/
|
||||
Map<String, String> extractUriTemplateVariables(String pattern, String path);
|
||||
}
|
||||
@@ -1,604 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Simple utility class for working with the reflection API and handling
|
||||
* reflection exceptions.
|
||||
*
|
||||
* <p>Only intended for internal use.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Rod Johnson
|
||||
* @author Costin Leau
|
||||
* @author Sam Brannen
|
||||
* @since 1.2.2
|
||||
*/
|
||||
public abstract class ReflectionUtils {
|
||||
|
||||
/**
|
||||
* Attempt to find a {@link Field field} on the supplied {@link Class} with
|
||||
* the supplied <code>name</code>. Searches all superclasses up to {@link Object}.
|
||||
* @param clazz the class to introspect
|
||||
* @param name the name of the field
|
||||
* @return the corresponding Field object, or <code>null</code> if not found
|
||||
*/
|
||||
public static Field findField(final Class<?> clazz, final String name) {
|
||||
return findField(clazz, name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to find a {@link Field field} on the supplied {@link Class} with
|
||||
* the supplied <code>name</code> and/or {@link Class type}. Searches all
|
||||
* superclasses up to {@link Object}.
|
||||
* @param clazz the class to introspect
|
||||
* @param name the name of the field (may be <code>null</code> if type is specified)
|
||||
* @param type the type of the field (may be <code>null</code> if name is specified)
|
||||
* @return the corresponding Field object, or <code>null</code> if not found
|
||||
*/
|
||||
public static Field findField(final Class<?> clazz, final String name, final Class<?> type) {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
Assert.isTrue(name != null || type != null, "Either name or type of the field must be specified");
|
||||
Class<?> searchType = clazz;
|
||||
while (!Object.class.equals(searchType) && searchType != null) {
|
||||
Field[] fields = searchType.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if ((name == null || name.equals(field.getName())) &&
|
||||
(type == null || type.equals(field.getType()))) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
searchType = searchType.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the field represented by the supplied {@link Field field object} on
|
||||
* the specified {@link Object target object} to the specified
|
||||
* <code>value</code>. In accordance with
|
||||
* {@link Field#set(Object, Object)} semantics, the new value is
|
||||
* automatically unwrapped if the underlying field has a primitive type.
|
||||
* <p>Thrown exceptions are handled via a call to
|
||||
* {@link #handleReflectionException(Exception)}.
|
||||
* @param field the field to set
|
||||
* @param target the target object on which to set the field
|
||||
* @param value the value to set; may be <code>null</code>
|
||||
*/
|
||||
public static void setField(final Field field, final Object target, final Object value) {
|
||||
try {
|
||||
field.set(target, value);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
handleReflectionException(ex);
|
||||
throw new IllegalStateException(
|
||||
"Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field represented by the supplied {@link Field field object} on
|
||||
* the specified {@link Object target object}. In accordance with
|
||||
* {@link Field#get(Object)} semantics, the returned value is
|
||||
* automatically wrapped if the underlying field has a primitive type.
|
||||
* <p>Thrown exceptions are handled via a call to
|
||||
* {@link #handleReflectionException(Exception)}.
|
||||
* @param field the field to get
|
||||
* @param target the target object from which to get the field
|
||||
* @return the field's current value
|
||||
*/
|
||||
public static Object getField(final Field field, final Object target) {
|
||||
try {
|
||||
return field.get(target);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
handleReflectionException(ex);
|
||||
throw new IllegalStateException(
|
||||
"Unexpected reflection exception - " + ex.getClass().getName() + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to find a {@link Method} on the supplied class with the supplied name
|
||||
* and no parameters. Searches all superclasses up to <code>Object</code>.
|
||||
* <p>Returns <code>null</code> if no {@link Method} can be found.
|
||||
* @param clazz the class to introspect
|
||||
* @param name the name of the method
|
||||
* @return the Method object, or <code>null</code> if none found
|
||||
*/
|
||||
public static Method findMethod(final Class<?> clazz, final String name) {
|
||||
return findMethod(clazz, name, new Class[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to find a {@link Method} on the supplied class with the supplied name
|
||||
* and parameter types. Searches all superclasses up to <code>Object</code>.
|
||||
* <p>Returns <code>null</code> if no {@link Method} can be found.
|
||||
* @param clazz the class to introspect
|
||||
* @param name the name of the method
|
||||
* @param parameterTypes the parameter types of the method
|
||||
* (may be <code>null</code> to indicate any signature)
|
||||
* @return the Method object, or <code>null</code> if none found
|
||||
*/
|
||||
public static Method findMethod(final Class<?> clazz, final String name, final Class<?>[] parameterTypes) {
|
||||
Assert.notNull(clazz, "Class must not be null");
|
||||
Assert.notNull(name, "Method name must not be null");
|
||||
Class<?> searchType = clazz;
|
||||
while (!Object.class.equals(searchType) && searchType != null) {
|
||||
Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods());
|
||||
for (Method method : methods) {
|
||||
if (name.equals(method.getName()) &&
|
||||
(parameterTypes == null || Arrays.equals(parameterTypes, method.getParameterTypes()))) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
searchType = searchType.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the specified {@link Method} against the supplied target object
|
||||
* with no arguments. The target object can be <code>null</code> when
|
||||
* invoking a static {@link Method}.
|
||||
* <p>Thrown exceptions are handled via a call to {@link #handleReflectionException}.
|
||||
* @param method the method to invoke
|
||||
* @param target the target object to invoke the method on
|
||||
* @return the invocation result, if any
|
||||
* @see #invokeMethod(java.lang.reflect.Method, Object, Object[])
|
||||
*/
|
||||
public static Object invokeMethod(final Method method, final Object target) {
|
||||
return invokeMethod(method, target, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the specified {@link Method} against the supplied target object
|
||||
* with the supplied arguments. The target object can be <code>null</code>
|
||||
* when invoking a static {@link Method}.
|
||||
* <p>Thrown exceptions are handled via a call to {@link #handleReflectionException}.
|
||||
* @param method the method to invoke
|
||||
* @param target the target object to invoke the method on
|
||||
* @param args the invocation arguments (may be <code>null</code>)
|
||||
* @return the invocation result, if any
|
||||
*/
|
||||
public static Object invokeMethod(final Method method, final Object target, final Object[] args) {
|
||||
try {
|
||||
return method.invoke(target, args);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
handleReflectionException(ex);
|
||||
}
|
||||
throw new IllegalStateException("Should never get here");
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the specified JDBC API {@link Method} against the supplied
|
||||
* target object with no arguments.
|
||||
* @param method the method to invoke
|
||||
* @param target the target object to invoke the method on
|
||||
* @return the invocation result, if any
|
||||
* @throws SQLException the JDBC API SQLException to rethrow (if any)
|
||||
* @see #invokeJdbcMethod(java.lang.reflect.Method, Object, Object[])
|
||||
*/
|
||||
public static Object invokeJdbcMethod(final Method method, final Object target) throws SQLException {
|
||||
return invokeJdbcMethod(method, target, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the specified JDBC API {@link Method} against the supplied
|
||||
* target object with the supplied arguments.
|
||||
* @param method the method to invoke
|
||||
* @param target the target object to invoke the method on
|
||||
* @param args the invocation arguments (may be <code>null</code>)
|
||||
* @return the invocation result, if any
|
||||
* @throws SQLException the JDBC API SQLException to rethrow (if any)
|
||||
* @see #invokeMethod(java.lang.reflect.Method, Object, Object[])
|
||||
*/
|
||||
public static Object invokeJdbcMethod(final Method method, final Object target, final Object[] args) throws SQLException {
|
||||
try {
|
||||
return method.invoke(target, args);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
handleReflectionException(ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
if (ex.getTargetException() instanceof SQLException) {
|
||||
throw (SQLException) ex.getTargetException();
|
||||
}
|
||||
handleInvocationTargetException(ex);
|
||||
}
|
||||
throw new IllegalStateException("Should never get here");
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the given reflection exception. Should only be called if
|
||||
* no checked exception is expected to be thrown by the target method.
|
||||
* <p>Throws the underlying RuntimeException or Error in case of an
|
||||
* InvocationTargetException with such a root cause. Throws an
|
||||
* IllegalStateException with an appropriate message else.
|
||||
* @param ex the reflection exception to handle
|
||||
*/
|
||||
public static void handleReflectionException(final Exception ex) {
|
||||
if (ex instanceof NoSuchMethodException) {
|
||||
throw new IllegalStateException("Method not found: " + ex.getMessage());
|
||||
}
|
||||
if (ex instanceof IllegalAccessException) {
|
||||
throw new IllegalStateException("Could not access method: " + ex.getMessage());
|
||||
}
|
||||
if (ex instanceof InvocationTargetException) {
|
||||
handleInvocationTargetException((InvocationTargetException) ex);
|
||||
}
|
||||
if (ex instanceof RuntimeException) {
|
||||
throw (RuntimeException) ex;
|
||||
}
|
||||
handleUnexpectedException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the given invocation target exception. Should only be called if
|
||||
* no checked exception is expected to be thrown by the target method.
|
||||
* <p>Throws the underlying RuntimeException or Error in case of such
|
||||
* a root cause. Throws an IllegalStateException else.
|
||||
* @param ex the invocation target exception to handle
|
||||
*/
|
||||
public static void handleInvocationTargetException(final InvocationTargetException ex) {
|
||||
rethrowRuntimeException(ex.getTargetException());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rethrow the given {@link Throwable exception}, which is presumably the
|
||||
* <em>target exception</em> of an {@link InvocationTargetException}.
|
||||
* Should only be called if no checked exception is expected to be thrown by
|
||||
* the target method.
|
||||
* <p>Rethrows the underlying exception cast to an {@link RuntimeException}
|
||||
* or {@link Error} if appropriate; otherwise, throws an
|
||||
* {@link IllegalStateException}.
|
||||
* @param ex the exception to rethrow
|
||||
* @throws RuntimeException the rethrown exception
|
||||
*/
|
||||
public static void rethrowRuntimeException(final Throwable ex) {
|
||||
if (ex instanceof RuntimeException) {
|
||||
throw (RuntimeException) ex;
|
||||
}
|
||||
if (ex instanceof Error) {
|
||||
throw (Error) ex;
|
||||
}
|
||||
handleUnexpectedException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rethrow the given {@link Throwable exception}, which is presumably the
|
||||
* <em>target exception</em> of an {@link InvocationTargetException}.
|
||||
* Should only be called if no checked exception is expected to be thrown by
|
||||
* the target method.
|
||||
* <p>Rethrows the underlying exception cast to an {@link Exception} or
|
||||
* {@link Error} if appropriate; otherwise, throws an
|
||||
* {@link IllegalStateException}.
|
||||
* @param ex the exception to rethrow
|
||||
* @throws Exception the rethrown exception (in case of a checked exception)
|
||||
*/
|
||||
public static void rethrowException(final Throwable ex) throws Exception {
|
||||
if (ex instanceof Exception) {
|
||||
throw (Exception) ex;
|
||||
}
|
||||
if (ex instanceof Error) {
|
||||
throw (Error) ex;
|
||||
}
|
||||
handleUnexpectedException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an IllegalStateException with the given exception as root cause.
|
||||
* @param ex the unexpected exception
|
||||
*/
|
||||
private static void handleUnexpectedException(final Throwable ex) {
|
||||
throw new IllegalStateException("Unexpected exception thrown", ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given method explicitly declares the given exception
|
||||
* or one of its superclasses, which means that an exception of that type
|
||||
* can be propagated as-is within a reflective invocation.
|
||||
* @param method the declaring method
|
||||
* @param exceptionType the exception to throw
|
||||
* @return <code>true</code> if the exception can be thrown as-is;
|
||||
* <code>false</code> if it needs to be wrapped
|
||||
*/
|
||||
public static boolean declaresException(final Method method, final Class<?> exceptionType) {
|
||||
Assert.notNull(method, "Method must not be null");
|
||||
Class<?>[] declaredExceptions = method.getExceptionTypes();
|
||||
for (Class<?> declaredException : declaredExceptions) {
|
||||
if (declaredException.isAssignableFrom(exceptionType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given field is a "public static final" constant.
|
||||
* @param field the field to check
|
||||
*/
|
||||
public static boolean isPublicStaticFinal(final Field field) {
|
||||
int modifiers = field.getModifiers();
|
||||
return (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given method is an "equals" method.
|
||||
* @see java.lang.Object#equals
|
||||
*/
|
||||
public static boolean isEqualsMethod(final Method method) {
|
||||
if (method == null || !method.getName().equals("equals")) {
|
||||
return false;
|
||||
}
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
return (parameterTypes.length == 1 && parameterTypes[0] == Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given method is a "hashCode" method.
|
||||
* @see java.lang.Object#hashCode
|
||||
*/
|
||||
public static boolean isHashCodeMethod(final Method method) {
|
||||
return (method != null && method.getName().equals("hashCode") &&
|
||||
method.getParameterTypes().length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given method is a "toString" method.
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public static boolean isToStringMethod(final Method method) {
|
||||
return (method != null && method.getName().equals("toString") &&
|
||||
method.getParameterTypes().length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given field accessible, explicitly setting it accessible if necessary.
|
||||
* The <code>setAccessible(true)</code> method is only called when actually necessary,
|
||||
* to avoid unnecessary conflicts with a JVM SecurityManager (if active).
|
||||
* @param field the field to make accessible
|
||||
* @see java.lang.reflect.Field#setAccessible
|
||||
*/
|
||||
public static void makeAccessible(final Field field) {
|
||||
if (!Modifier.isPublic(field.getModifiers()) ||
|
||||
!Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given method accessible, explicitly setting it accessible if necessary.
|
||||
* The <code>setAccessible(true)</code> method is only called when actually necessary,
|
||||
* to avoid unnecessary conflicts with a JVM SecurityManager (if active).
|
||||
* @param method the method to make accessible
|
||||
* @see java.lang.reflect.Method#setAccessible
|
||||
*/
|
||||
public static void makeAccessible(final Method method) {
|
||||
if (!Modifier.isPublic(method.getModifiers()) ||
|
||||
!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
|
||||
method.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given constructor accessible, explicitly setting it accessible if necessary.
|
||||
* The <code>setAccessible(true)</code> method is only called when actually necessary,
|
||||
* to avoid unnecessary conflicts with a JVM SecurityManager (if active).
|
||||
* @param ctor the constructor to make accessible
|
||||
* @see java.lang.reflect.Constructor#setAccessible
|
||||
*/
|
||||
public static void makeAccessible(final Constructor<?> ctor) {
|
||||
if (!Modifier.isPublic(ctor.getModifiers()) ||
|
||||
!Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) {
|
||||
ctor.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the given callback operation on all matching methods of the
|
||||
* given class and superclasses.
|
||||
* <p>The same named method occurring on subclass and superclass will
|
||||
* appear twice, unless excluded by a {@link MethodFilter}.
|
||||
* @param targetClass class to start looking at
|
||||
* @param mc the callback to invoke for each method
|
||||
* @see #doWithMethods(Class, MethodCallback, MethodFilter)
|
||||
*/
|
||||
public static void doWithMethods(final Class<?> targetClass, final MethodCallback mc) throws IllegalArgumentException {
|
||||
doWithMethods(targetClass, mc, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the given callback operation on all matching methods of the
|
||||
* given class and superclasses.
|
||||
* <p>The same named method occurring on subclass and superclass will
|
||||
* appear twice, unless excluded by the specified {@link MethodFilter}.
|
||||
* @param targetClass class to start looking at
|
||||
* @param mc the callback to invoke for each method
|
||||
* @param mf the filter that determines the methods to apply the callback to
|
||||
*/
|
||||
public static void doWithMethods(Class<?> targetClass, final MethodCallback mc, final MethodFilter mf) throws IllegalArgumentException {
|
||||
// Keep backing up the inheritance hierarchy.
|
||||
do {
|
||||
Method[] methods = targetClass.getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
if (mf != null && !mf.matches(method)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
mc.doWith(method);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Shouldn't be illegal to access method '" + method.getName() + "': " + ex);
|
||||
}
|
||||
}
|
||||
targetClass = targetClass.getSuperclass();
|
||||
}
|
||||
while (targetClass != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all declared methods on the leaf class and all superclasses.
|
||||
* Leaf class methods are included first.
|
||||
*/
|
||||
public static Method[] getAllDeclaredMethods(final Class<?> leafClass) throws IllegalArgumentException {
|
||||
final List<Method> methods = new ArrayList<Method>(32);
|
||||
doWithMethods(leafClass, new MethodCallback() {
|
||||
public void doWith(final Method method) {
|
||||
methods.add(method);
|
||||
}
|
||||
});
|
||||
return methods.toArray(new Method[methods.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the given callback on all fields in the target class,
|
||||
* going up the class hierarchy to get all declared fields.
|
||||
* @param targetClass the target class to analyze
|
||||
* @param fc the callback to invoke for each field
|
||||
*/
|
||||
public static void doWithFields(final Class<?> targetClass, final FieldCallback fc) throws IllegalArgumentException {
|
||||
doWithFields(targetClass, fc, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the given callback on all fields in the target class,
|
||||
* going up the class hierarchy to get all declared fields.
|
||||
* @param targetClass the target class to analyze
|
||||
* @param fc the callback to invoke for each field
|
||||
* @param ff the filter that determines the fields to apply the callback to
|
||||
*/
|
||||
public static void doWithFields(Class<?> targetClass, final FieldCallback fc, final FieldFilter ff) throws IllegalArgumentException {
|
||||
// Keep backing up the inheritance hierarchy.
|
||||
do {
|
||||
// Copy each field declared on this class unless it's static or file.
|
||||
Field[] fields = targetClass.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
// Skip static and final fields.
|
||||
if (ff != null && !ff.matches(field)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
fc.doWith(field);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Shouldn't be illegal to access field '" + field.getName() + "': " + ex);
|
||||
}
|
||||
}
|
||||
targetClass = targetClass.getSuperclass();
|
||||
}
|
||||
while (targetClass != null && targetClass != Object.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the source object and the destination, which must be the same class
|
||||
* or a subclass, copy all fields, including inherited fields. Designed to
|
||||
* work on objects with public no-arg constructors.
|
||||
* @throws IllegalArgumentException if the arguments are incompatible
|
||||
*/
|
||||
public static void shallowCopyFieldState(final Object src, final Object dest) throws IllegalArgumentException {
|
||||
if (src == null) {
|
||||
throw new IllegalArgumentException("Source for field copy cannot be null");
|
||||
}
|
||||
if (dest == null) {
|
||||
throw new IllegalArgumentException("Destination for field copy cannot be null");
|
||||
}
|
||||
if (!src.getClass().isAssignableFrom(dest.getClass())) {
|
||||
throw new IllegalArgumentException("Destination class [" + dest.getClass().getName() +
|
||||
"] must be same or subclass as source class [" + src.getClass().getName() + "]");
|
||||
}
|
||||
doWithFields(src.getClass(), new FieldCallback() {
|
||||
public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException {
|
||||
makeAccessible(field);
|
||||
Object srcValue = field.get(src);
|
||||
field.set(dest, srcValue);
|
||||
}
|
||||
}, COPYABLE_FIELDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to take on each method.
|
||||
*/
|
||||
public static interface MethodCallback {
|
||||
|
||||
/**
|
||||
* Perform an operation using the given method.
|
||||
* @param method the method to operate on
|
||||
*/
|
||||
void doWith(Method method) throws IllegalArgumentException, IllegalAccessException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback optionally used to method fields to be operated on by a method callback.
|
||||
*/
|
||||
public static interface MethodFilter {
|
||||
|
||||
/**
|
||||
* Determine whether the given method matches.
|
||||
* @param method the method to check
|
||||
*/
|
||||
boolean matches(Method method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback interface invoked on each field in the hierarchy.
|
||||
*/
|
||||
public static interface FieldCallback {
|
||||
|
||||
/**
|
||||
* Perform an operation using the given field.
|
||||
* @param field the field to operate on
|
||||
*/
|
||||
void doWith(Field field) throws IllegalArgumentException, IllegalAccessException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback optionally used to filter fields to be operated on by a field callback.
|
||||
*/
|
||||
public static interface FieldFilter {
|
||||
|
||||
/**
|
||||
* Determine whether the given field matches.
|
||||
* @param field the field to check
|
||||
*/
|
||||
boolean matches(Field field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-built FieldFilter that matches all non-static, non-final fields.
|
||||
*/
|
||||
public static FieldFilter COPYABLE_FIELDS = new FieldFilter() {
|
||||
public boolean matches(final Field field) {
|
||||
return !(Modifier.isStatic(field.getModifiers()) ||
|
||||
Modifier.isFinal(field.getModifiers()));
|
||||
}
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Utilities for dealing with "templates", which are commonly used by ROO add-ons.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @since 1.0
|
||||
*/
|
||||
public final class TemplateUtils {
|
||||
|
||||
/**
|
||||
* Determines the path to the requested template.
|
||||
*
|
||||
* @param clazz which owns the template (required)
|
||||
* @param templateFilename the filename of the template (required)
|
||||
* @return the full classloader-specific path to the template (never null)
|
||||
* @deprecated use {@link FileUtils#getPath(Class, String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static String getTemplatePath(final Class<?> loadingClass, final String relativeFilename) {
|
||||
return FileUtils.getPath(loadingClass, relativeFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires an {@link InputStream} to the requested classloader-derived template.
|
||||
*
|
||||
* @param clazz which owns the template (required)
|
||||
* @param templateFilename the filename of the template (required)
|
||||
* @return the input stream (never null; an exception is thrown if cannot be found)
|
||||
* @deprecated use {@link FileUtils#getInputStream(Class, String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static InputStream getTemplate(final Class<?> clazz, final String templateFilename) {
|
||||
return clazz.getResourceAsStream(templateFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private TemplateUtils() {}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Utility methods relating to networking types such as URLs.
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public final class UrlUtils {
|
||||
|
||||
/**
|
||||
* Converts the given URI to a URL; equivalent to {@link URI#toURL()}
|
||||
* except that it throws a runtime exception.
|
||||
*
|
||||
* @param uri
|
||||
* @return a non-<code>null</code> URL
|
||||
* @throws IllegalArgumentException if the conversion is not possible
|
||||
*/
|
||||
public static URL toURL(final URI uri) {
|
||||
try {
|
||||
return uri.toURL();
|
||||
} catch (final MalformedURLException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private UrlUtils() {}
|
||||
}
|
||||
@@ -1,602 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Helper util class to allow more convenient handling of web.xml file in Web projects.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.1
|
||||
*/
|
||||
public final class WebXmlUtils {
|
||||
|
||||
// Constants
|
||||
private static final String WEB_APP_XPATH = "/web-app/";
|
||||
private static final String WHITESPACE = "[ \t\r\n]";
|
||||
|
||||
/**
|
||||
* Set the display-name element in the web.xml document.
|
||||
*
|
||||
* @param displayName (required)
|
||||
* @param document the web.xml document (required)
|
||||
* @param comment (optional)
|
||||
*/
|
||||
public static void setDisplayName(final String displayName, final Document document, final String comment) {
|
||||
Assert.hasText(displayName, "display name required");
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
|
||||
Element displayNameElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "display-name", document.getDocumentElement());
|
||||
if (displayNameElement == null) {
|
||||
displayNameElement = document.createElement("display-name");
|
||||
insertBetween(displayNameElement, "the-start", "description", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(displayNameElement, comment, document);
|
||||
}
|
||||
}
|
||||
displayNameElement.setTextContent(displayName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the description element in the web.xml document.
|
||||
*
|
||||
* @param description (required)
|
||||
* @param document the web.xml document (required)
|
||||
* @param comment (optional)
|
||||
*/
|
||||
public static void setDescription(final String description, final Document document, final String comment) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.hasText(description, "Description required");
|
||||
|
||||
Element descriptionElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "description", document.getDocumentElement());
|
||||
if (descriptionElement == null) {
|
||||
descriptionElement = document.createElement("description");
|
||||
insertBetween(descriptionElement, "display-name[last()]", "context-param", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(descriptionElement, comment, document);
|
||||
}
|
||||
}
|
||||
descriptionElement.setTextContent(description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a context param to the web.xml document
|
||||
*
|
||||
* @param contextParam (required)
|
||||
* @param document the web.xml document (required)
|
||||
* @param comment (optional)
|
||||
*/
|
||||
public static void addContextParam(final WebXmlParam contextParam, final Document document, final String comment) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.notNull(contextParam, "Context param required");
|
||||
|
||||
Element contextParamElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "context-param[param-name = '" + contextParam.getName() + "']", document.getDocumentElement());
|
||||
if (contextParamElement == null) {
|
||||
contextParamElement = new XmlElementBuilder("context-param", document).addChild(new XmlElementBuilder("param-name", document).setText(contextParam.getName()).build()).build();
|
||||
insertBetween(contextParamElement, "description[last()]", "filter", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(contextParamElement, comment, document);
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(contextParamElement, new XmlElementBuilder("param-value", document).setText(contextParam.getValue()).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new filter definition to web.xml document. The filter will be added AFTER (FilterPosition.LAST) all existing filters.
|
||||
*
|
||||
* @param filterName (required)
|
||||
* @param filterClass the fully qualified name of the filter type (required)
|
||||
* @param urlPattern (required)
|
||||
* @param document the web.xml document (required)
|
||||
* @param comment (optional)
|
||||
* @param initParams a vararg of initial parameters (optional)
|
||||
*/
|
||||
public static void addFilter(final String filterName, final String filterClass, final String urlPattern, final Document document, final String comment, final WebXmlParam... initParams) {
|
||||
addFilterAtPosition(FilterPosition.LAST, null, null, filterName, filterClass, urlPattern, document, comment, initParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new filter definition to web.xml document. The filter will be added at the FilterPosition specified.
|
||||
*
|
||||
* @param filterPosition Filter position (required)
|
||||
* @param beforeFilterName (optional for filter position FIRST and LAST, required for BEFORE and AFTER)
|
||||
* @param filterName (required)
|
||||
* @param filterClass the fully qualified name of the filter type (required)
|
||||
* @param urlPattern (required)
|
||||
* @param document the web.xml document (required)
|
||||
* @param comment (optional)
|
||||
* @param initParams (optional)
|
||||
*/
|
||||
public static void addFilterAtPosition(final FilterPosition filterPosition, final String afterFilterName, final String beforeFilterName, final String filterName, final String filterClass, final String urlPattern, final Document document, final String comment, final WebXmlParam... initParams) {
|
||||
addFilterAtPosition(filterPosition, afterFilterName, beforeFilterName, filterName, filterClass, urlPattern, document, comment, initParams == null ? new ArrayList<WebXmlParam>() : Arrays.asList(initParams), new ArrayList<Dispatcher>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new filter definition to web.xml document. The filter will be added at the FilterPosition specified.
|
||||
*
|
||||
* @param filterPosition Filter position (required)
|
||||
* @param beforeFilterName (optional for filter position FIRST and LAST, required for BEFORE and AFTER)
|
||||
* @param filterName (required)
|
||||
* @param filterClass the fully qualified name of the filter type (required)
|
||||
* @param urlPattern (required)
|
||||
* @param document the web.xml document (required)
|
||||
* @param comment (optional)
|
||||
* @param initParams (optional)
|
||||
* @param dispatchers (optional)
|
||||
*/
|
||||
public static void addFilterAtPosition(final FilterPosition filterPosition, final String afterFilterName, final String beforeFilterName, final String filterName, final String filterClass, final String urlPattern, final Document document, final String comment, List<WebXmlParam> initParams, final List<Dispatcher> dispatchers) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.hasText(filterName, "Filter name required");
|
||||
Assert.hasText(filterClass, "Filter class required");
|
||||
Assert.notNull(urlPattern, "Filter URL mapping pattern required");
|
||||
|
||||
if (initParams == null) {
|
||||
initParams = new ArrayList<WebXmlUtils.WebXmlParam>();
|
||||
}
|
||||
|
||||
// Creating filter
|
||||
Element filterElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "filter[filter-name = '" + filterName + "']", document.getDocumentElement());
|
||||
if (filterElement == null) {
|
||||
filterElement = new XmlElementBuilder("filter", document).addChild(new XmlElementBuilder("filter-name", document).setText(filterName).build()).build();
|
||||
if (filterPosition.equals(FilterPosition.FIRST)) {
|
||||
insertBetween(filterElement, "context-param", "filter", document);
|
||||
} else if (filterPosition.equals(FilterPosition.BEFORE)) {
|
||||
Assert.hasText(beforeFilterName, "The filter position filter name is required when using FilterPosition.BEFORE");
|
||||
insertBefore(filterElement, "filter[filter-name = '" + beforeFilterName + "']", document);
|
||||
} else if (filterPosition.equals(FilterPosition.AFTER)) {
|
||||
Assert.hasText(afterFilterName, "The filter position filter name is required when using FilterPosition.AFTER");
|
||||
insertAfter(filterElement, "filter[filter-name = '" + afterFilterName + "']", document);
|
||||
} else if (filterPosition.equals(FilterPosition.BETWEEN)) {
|
||||
Assert.hasText(beforeFilterName, "The 'before' filter name is required when using FilterPosition.BETWEEN");
|
||||
Assert.hasText(afterFilterName, "The 'after' filter name is required when using FilterPosition.BETWEEN");
|
||||
insertBetween(filterElement, "filter[filter-name = '" + afterFilterName + "']", "filter[filter-name = '" + beforeFilterName + "']", document);
|
||||
} else {
|
||||
insertBetween(filterElement, "context-param[last()]", "filter-mapping", document);
|
||||
}
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(filterElement, comment, document);
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(filterElement, new XmlElementBuilder("filter-class", document).setText(filterClass).build());
|
||||
for (final WebXmlParam initParam : initParams) {
|
||||
appendChildIfNotPresent(filterElement, new XmlElementBuilder("init-param", document).addChild(new XmlElementBuilder("param-name", document).setText(initParam.getName()).build()).addChild(new XmlElementBuilder("param-value", document).setText(initParam.getValue()).build()).build());
|
||||
}
|
||||
|
||||
// Creating filter mapping
|
||||
Element filterMappingElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "filter-mapping[filter-name = '" + filterName + "']", document.getDocumentElement());
|
||||
if (filterMappingElement == null) {
|
||||
filterMappingElement = new XmlElementBuilder("filter-mapping", document).addChild(new XmlElementBuilder("filter-name", document).setText(filterName).build()).build();
|
||||
if (filterPosition.equals(FilterPosition.FIRST)) {
|
||||
insertBetween(filterMappingElement, "filter", "filter-mapping", document);
|
||||
} else if (filterPosition.equals(FilterPosition.BEFORE)) {
|
||||
insertBefore(filterMappingElement, "filter-mapping[filter-name = '" + beforeFilterName + "']", document);
|
||||
} else if (filterPosition.equals(FilterPosition.AFTER)) {
|
||||
insertAfter(filterMappingElement, "filter-mapping[filter-name = '" + beforeFilterName + "']", document);
|
||||
} else if (filterPosition.equals(FilterPosition.BETWEEN)) {
|
||||
insertBetween(filterMappingElement, "filter-mapping[filter-name = '" + afterFilterName + "']", "filter-mapping[filter-name = '" + beforeFilterName + "']", document);
|
||||
} else {
|
||||
insertBetween(filterMappingElement, "filter-mapping[last()]", "listener", document);
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(filterMappingElement, new XmlElementBuilder("url-pattern", document).setText(urlPattern).build());
|
||||
for (final Dispatcher dispatcher : dispatchers) {
|
||||
appendChildIfNotPresent(filterMappingElement, new XmlElementBuilder("dispatcher", document).setText(dispatcher.name()).build());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add listener element to web.xml document
|
||||
*
|
||||
* @param className the fully qualified name of the listener type (required)
|
||||
* @param document (required)
|
||||
* @param comment (optional)
|
||||
*/
|
||||
public static void addListener(final String className, final Document document, final String comment) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.hasText(className, "Class name required");
|
||||
|
||||
Element listenerElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "listener[listener-class = '" + className + "']", document.getDocumentElement());
|
||||
if (listenerElement == null) {
|
||||
listenerElement = new XmlElementBuilder("listener", document).addChild(new XmlElementBuilder("listener-class", document).setText(className).build()).build();
|
||||
insertBetween(listenerElement, "filter-mapping[last()]", "servlet", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(listenerElement, comment, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add servlet element to the web.xml document
|
||||
*
|
||||
* @param servletName (required)
|
||||
* @param className the fully qualified name of the servlet type (required)
|
||||
* @param urlPattern this can be set to null in which case the servletName will be used for mapping (optional)
|
||||
* @param loadOnStartup (optional)
|
||||
* @param document (required)
|
||||
* @param comment (optional)
|
||||
* @param initParams (optional)
|
||||
*/
|
||||
public static void addServlet(final String servletName, final String className, final String urlPattern, final Integer loadOnStartup, final Document document, final String comment, final WebXmlParam... initParams) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.hasText(servletName, "Servlet name required");
|
||||
Assert.hasText(className, "Fully qualified class name required");
|
||||
|
||||
// Create servlet
|
||||
Element servletElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "servlet[servlet-name = '" + servletName + "']", document.getDocumentElement());
|
||||
if (servletElement == null) {
|
||||
servletElement = new XmlElementBuilder("servlet", document).addChild(new XmlElementBuilder("servlet-name", document).setText(servletName).build()).build();
|
||||
insertBetween(servletElement, "listener[last()]", "servlet-mapping", document);
|
||||
if (comment != null && comment.length() > 0) {
|
||||
addCommentBefore(servletElement, comment, document);
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(servletElement, new XmlElementBuilder("servlet-class", document).setText(className).build());
|
||||
for (final WebXmlParam initParam : initParams) {
|
||||
appendChildIfNotPresent(servletElement, new XmlElementBuilder("init-param", document).addChild(new XmlElementBuilder("param-name", document).setText(initParam.getName()).build()).addChild(new XmlElementBuilder("param-value", document).setText(initParam.getValue()).build()).build());
|
||||
}
|
||||
if (loadOnStartup != null) {
|
||||
appendChildIfNotPresent(servletElement, new XmlElementBuilder("load-on-startup", document).setText(loadOnStartup.toString()).build());
|
||||
}
|
||||
|
||||
// Create servlet mapping
|
||||
Element servletMappingElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "servlet-mapping[servlet-name = '" + servletName + "']", document.getDocumentElement());
|
||||
if (servletMappingElement == null) {
|
||||
servletMappingElement = new XmlElementBuilder("servlet-mapping", document).addChild(new XmlElementBuilder("servlet-name", document).setText(servletName).build()).build();
|
||||
insertBetween(servletMappingElement, "servlet[last()]", "session-config", document);
|
||||
}
|
||||
if (StringUtils.hasText(urlPattern)) {
|
||||
appendChildIfNotPresent(servletMappingElement, new XmlElementBuilder("url-pattern", document).setText(urlPattern).build());
|
||||
} else {
|
||||
appendChildIfNotPresent(servletMappingElement, new XmlElementBuilder("servlet-name", document).setText(servletName).build());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set session timeout in web.xml document
|
||||
*
|
||||
* @param timeout
|
||||
* @param document (required)
|
||||
* @param comment (optional)
|
||||
*/
|
||||
public static void setSessionTimeout(final int timeout, final Document document, final String comment) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.notNull(timeout, "Timeout required");
|
||||
|
||||
Element sessionConfigElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "session-config", document.getDocumentElement());
|
||||
if (sessionConfigElement == null) {
|
||||
sessionConfigElement = document.createElement("session-config");
|
||||
insertBetween(sessionConfigElement, "servlet-mapping[last()]", "welcome-file-list", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(sessionConfigElement, comment, document);
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(sessionConfigElement, new XmlElementBuilder("session-timeout", document).setText(String.valueOf(timeout)).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a welcome file definition to web.xml document
|
||||
*
|
||||
* @param path (required)
|
||||
* @param document (required)
|
||||
* @param comment (optional)
|
||||
*/
|
||||
public static void addWelcomeFile(final String path, final Document document, final String comment) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.hasText("Path required");
|
||||
|
||||
Element welcomeFileElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "welcome-file-list", document.getDocumentElement());
|
||||
if (welcomeFileElement == null) {
|
||||
welcomeFileElement = document.createElement("welcome-file-list");
|
||||
insertBetween(welcomeFileElement, "session-config[last()]", "error-page", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(welcomeFileElement, comment, document);
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(welcomeFileElement, new XmlElementBuilder("welcome-file", document).setText(path).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add exception type to web.xml document
|
||||
*
|
||||
* @param exceptionType fully qualified exception type name (required)
|
||||
* @param location (required)
|
||||
* @param document (required)
|
||||
* @param comment (optional)
|
||||
*/
|
||||
public static void addExceptionType(final String exceptionType, final String location, final Document document, final String comment) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.hasText(exceptionType, "Fully qualified exception type name required");
|
||||
Assert.hasText(location, "location required");
|
||||
|
||||
Element errorPageElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "error-page[exception-type = '" + exceptionType + "']", document.getDocumentElement());
|
||||
if (errorPageElement == null) {
|
||||
errorPageElement = new XmlElementBuilder("error-page", document).addChild(new XmlElementBuilder("exception-type", document).setText(exceptionType).build()).build();
|
||||
insertBetween(errorPageElement, "welcome-file-list[last()]", "the-end", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(errorPageElement, comment, document);
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(errorPageElement, new XmlElementBuilder("location", document).setText(location).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add error code to web.xml document
|
||||
*
|
||||
* @param errorCode (required)
|
||||
* @param location (required)
|
||||
* @param document (required)
|
||||
* @param comment (optional)
|
||||
*/
|
||||
public static void addErrorCode(final Integer errorCode, final String location, final Document document, final String comment) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.notNull(errorCode, "Error code required");
|
||||
Assert.hasText(location, "Location required");
|
||||
|
||||
Element errorPageElement = XmlUtils.findFirstElement(WEB_APP_XPATH + "error-page[error-code = '" + errorCode.toString() + "']", document.getDocumentElement());
|
||||
if (errorPageElement == null) {
|
||||
errorPageElement = new XmlElementBuilder("error-page", document).addChild(new XmlElementBuilder("error-code", document).setText(errorCode.toString()).build()).build();
|
||||
insertBetween(errorPageElement, "welcome-file-list[last()]", "the-end", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(errorPageElement, comment, document);
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(errorPageElement, new XmlElementBuilder("location", document).setText(location).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a security constraint to a web.xml document
|
||||
*
|
||||
* @param displayName (optional)
|
||||
* @param webResourceCollections (required)
|
||||
* @param roleNames (optional)
|
||||
* @param transportGuarantee (optional)
|
||||
* @param document (required)
|
||||
* @param comment (optional)
|
||||
* */
|
||||
public static void addSecurityConstraint(final String displayName, final List<WebResourceCollection> webResourceCollections, final List<String> roleNames, final String transportGuarantee, final Document document, final String comment) {
|
||||
Assert.notNull(document, "Web XML document required");
|
||||
Assert.isTrue(!CollectionUtils.isEmpty(webResourceCollections), "A security-constraint element must contain at least one web-resource-collection");
|
||||
|
||||
Element securityConstraintElement = XmlUtils.findFirstElement("security-constraint", document.getDocumentElement());
|
||||
if (securityConstraintElement == null) {
|
||||
securityConstraintElement = document.createElement("security-constraint");
|
||||
insertAfter(securityConstraintElement, "session-config[last()]", document);
|
||||
if (StringUtils.hasText(comment)) {
|
||||
addCommentBefore(securityConstraintElement, comment, document);
|
||||
}
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(displayName)) {
|
||||
appendChildIfNotPresent(securityConstraintElement, new XmlElementBuilder("display-name", document).setText(displayName).build());
|
||||
}
|
||||
|
||||
for (final WebResourceCollection webResourceCollection : webResourceCollections) {
|
||||
final XmlElementBuilder webResourceCollectionBuilder = new XmlElementBuilder("web-resource-collection", document);
|
||||
Assert.hasText(webResourceCollection.getWebResourceName(), "web-resource-name is required");
|
||||
webResourceCollectionBuilder.addChild(new XmlElementBuilder("web-resource-name", document).setText(webResourceCollection.getWebResourceName()).build());
|
||||
if (StringUtils.hasText(webResourceCollection.getDescription())) {
|
||||
webResourceCollectionBuilder.addChild(new XmlElementBuilder("description", document).setText(webResourceCollection.getWebResourceName()).build());
|
||||
}
|
||||
for (final String urlPattern : webResourceCollection.getUrlPatterns()) {
|
||||
if (StringUtils.hasText(urlPattern)) {
|
||||
webResourceCollectionBuilder.addChild(new XmlElementBuilder("url-pattern", document).setText(urlPattern).build());
|
||||
}
|
||||
}
|
||||
for (final String httpMethod : webResourceCollection.getHttpMethods()) {
|
||||
if (StringUtils.hasText(httpMethod)) {
|
||||
webResourceCollectionBuilder.addChild(new XmlElementBuilder("http-method", document).setText(httpMethod).build());
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(securityConstraintElement, webResourceCollectionBuilder.build());
|
||||
}
|
||||
|
||||
if (roleNames != null && roleNames.size() > 0) {
|
||||
final XmlElementBuilder authConstraintBuilder = new XmlElementBuilder("auth-constraint", document);
|
||||
for (final String roleName : roleNames) {
|
||||
if (StringUtils.hasText(roleName)) {
|
||||
authConstraintBuilder.addChild(new XmlElementBuilder("role-name", document).setText(roleName).build());
|
||||
}
|
||||
}
|
||||
appendChildIfNotPresent(securityConstraintElement, authConstraintBuilder.build());
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(transportGuarantee)) {
|
||||
final XmlElementBuilder userDataConstraintBuilder = new XmlElementBuilder("user-data-constraint", document);
|
||||
userDataConstraintBuilder.addChild(new XmlElementBuilder("transport-guarantee", document).setText(transportGuarantee).build());
|
||||
appendChildIfNotPresent(securityConstraintElement, userDataConstraintBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
private static void insertBetween(final Element element, final String afterElementName, final String beforeElementName, final Document document) {
|
||||
final Element beforeElement = XmlUtils.findFirstElement(WEB_APP_XPATH + beforeElementName, document.getDocumentElement());
|
||||
if (beforeElement != null) {
|
||||
document.getDocumentElement().insertBefore(element, beforeElement);
|
||||
addLineBreakBefore(element, document);
|
||||
addLineBreakBefore(element, document);
|
||||
return;
|
||||
}
|
||||
|
||||
final Element afterElement = XmlUtils.findFirstElement(WEB_APP_XPATH + afterElementName, document.getDocumentElement());
|
||||
if (afterElement != null && afterElement.getNextSibling() != null && afterElement.getNextSibling() instanceof Element) {
|
||||
document.getDocumentElement().insertBefore(element, afterElement.getNextSibling());
|
||||
addLineBreakBefore(element, document);
|
||||
addLineBreakBefore(element, document);
|
||||
return;
|
||||
}
|
||||
|
||||
document.getDocumentElement().appendChild(element);
|
||||
addLineBreakBefore(element, document);
|
||||
addLineBreakBefore(element, document);
|
||||
}
|
||||
|
||||
private static void insertBefore(final Element element, final String beforeElementName, final Document document) {
|
||||
final Element beforeElement = XmlUtils.findFirstElement(WEB_APP_XPATH + beforeElementName, document.getDocumentElement());
|
||||
if (beforeElement != null) {
|
||||
document.getDocumentElement().insertBefore(element, beforeElement);
|
||||
addLineBreakBefore(element, document);
|
||||
addLineBreakBefore(element, document);
|
||||
return;
|
||||
}
|
||||
document.getDocumentElement().appendChild(element);
|
||||
addLineBreakBefore(element, document);
|
||||
addLineBreakBefore(element, document);
|
||||
}
|
||||
|
||||
private static void insertAfter(final Element element, final String afterElementName, final Document document) {
|
||||
final Element afterElement = XmlUtils.findFirstElement(WEB_APP_XPATH + afterElementName, document.getDocumentElement());
|
||||
if (afterElement != null && afterElement.getNextSibling() != null && afterElement.getNextSibling() instanceof Element) {
|
||||
document.getDocumentElement().insertBefore(element, afterElement.getNextSibling());
|
||||
addLineBreakBefore(element, document);
|
||||
addLineBreakBefore(element, document);
|
||||
return;
|
||||
}
|
||||
document.getDocumentElement().appendChild(element);
|
||||
addLineBreakBefore(element, document);
|
||||
addLineBreakBefore(element, document);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given child to the given parent if it's not already there
|
||||
*
|
||||
* @param parent the parent to which to add a child (required)
|
||||
* @param child the child to add if not present (required)
|
||||
*/
|
||||
private static void appendChildIfNotPresent(final Node parent, final Element child) {
|
||||
final NodeList existingChildren = parent.getChildNodes();
|
||||
for (int i = 0; i < existingChildren.getLength(); i++) {
|
||||
final Node existingChild = existingChildren.item(i);
|
||||
if (existingChild instanceof Element) {
|
||||
// Attempt matching of possibly nested structures by using of 'getTextContent' as 'isEqualNode' does not match due to line returns, etc
|
||||
// Note, this does not work if child nodes are appearing in a different order than expected
|
||||
if (existingChild.getNodeName().equals(child.getNodeName()) && existingChild.getTextContent().replaceAll(WHITESPACE, "").trim().equals(child.getTextContent().replaceAll(WHITESPACE, ""))) {
|
||||
// If we found a match, there is no need to append the child element
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
parent.appendChild(child);
|
||||
}
|
||||
|
||||
private static void addLineBreakBefore(final Element element, final Document document) {
|
||||
document.getDocumentElement().insertBefore(document.createTextNode("\n "), element);
|
||||
}
|
||||
|
||||
private static void addCommentBefore(final Element element, final String comment, final Document document) {
|
||||
if (null == XmlUtils.findNode("//comment()[.=' " + comment + " ']", document.getDocumentElement())) {
|
||||
document.getDocumentElement().insertBefore(document.createComment(" " + comment + " "), element);
|
||||
addLineBreakBefore(element, document);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Value object that holds init-param style information
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.1
|
||||
*/
|
||||
public static class WebXmlParam extends Pair<String, String> {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name
|
||||
* @param value
|
||||
*/
|
||||
public WebXmlParam(final String name, final String value) {
|
||||
super(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this parameter
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getName() {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum to define filter position
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.1
|
||||
*
|
||||
*/
|
||||
public static enum FilterPosition {
|
||||
FIRST, LAST, BEFORE, AFTER, BETWEEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum to define dispatcher
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.1.1
|
||||
*
|
||||
*/
|
||||
public static enum Dispatcher {
|
||||
FORWARD, REQUEST, INCLUDE, ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience class for passing a web-resource-collection element's details
|
||||
*
|
||||
* @since 1.1.1
|
||||
*/
|
||||
public static class WebResourceCollection {
|
||||
private final String webResourceName;
|
||||
private final String description;
|
||||
private final List<String> urlPatterns;
|
||||
private final List<String> httpMethods;
|
||||
|
||||
public WebResourceCollection(final String webResourceName, final String description, final List<String> urlPatterns, final List<String> httpMethods) {
|
||||
this.webResourceName = webResourceName;
|
||||
this.description = description;
|
||||
this.urlPatterns = urlPatterns;
|
||||
this.httpMethods = httpMethods;
|
||||
}
|
||||
|
||||
public String getWebResourceName() {
|
||||
return webResourceName;
|
||||
}
|
||||
|
||||
public List<String> getUrlPatterns() {
|
||||
return urlPatterns;
|
||||
}
|
||||
|
||||
public List<String> getHttpMethods() {
|
||||
return httpMethods;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private WebXmlUtils() {
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Very simple convenience Builder for XML {@code Element}s
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.0
|
||||
*/
|
||||
public class XmlElementBuilder {
|
||||
|
||||
// Fields
|
||||
private final Element element;
|
||||
|
||||
/**
|
||||
* Create a new Element instance.
|
||||
*
|
||||
* @param name The name of the element (required, not empty)
|
||||
* @param document The parent document (required)
|
||||
*/
|
||||
public XmlElementBuilder(final String name, final Document document) {
|
||||
Assert.hasText(name, "Element name required");
|
||||
Assert.notNull(document, "Owner document required");
|
||||
element = document.createElement(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attribute to the current element.
|
||||
*
|
||||
* @param qName The attribute name (required, not empty)
|
||||
* @param value The value of the attribute (required)
|
||||
* @return the current XmlElementBuilder
|
||||
*/
|
||||
public XmlElementBuilder addAttribute(final String qName, final String value) {
|
||||
Assert.hasText(qName, "Attribute qName required");
|
||||
Assert.notNull(value, "Attribute value required");
|
||||
element.setAttribute(qName, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child node to the current element.
|
||||
*
|
||||
* @param node The new node (required)
|
||||
* @return The builder for the current element
|
||||
*/
|
||||
public XmlElementBuilder addChild(final Node node) {
|
||||
Assert.notNull(node, "Node required");
|
||||
this.element.appendChild(node);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add text contents to the current element. This will overwrite
|
||||
* any previous text content.
|
||||
*
|
||||
* @param text The text content (required, not empty)
|
||||
* @return The builder for the current element
|
||||
*/
|
||||
public XmlElementBuilder setText(final String text) {
|
||||
Assert.hasText(text, "Text content required");
|
||||
element.setTextContent(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element instance.
|
||||
*
|
||||
* @return The element.
|
||||
*/
|
||||
public Element build() {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Utilities related to round-tripping XML documents
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.1
|
||||
*/
|
||||
public final class XmlRoundTripUtils {
|
||||
|
||||
private static MessageDigest digest;
|
||||
|
||||
static {
|
||||
try {
|
||||
digest = MessageDigest.getInstance("sha-1");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("Could not create hash key for identifier");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a base 64 encoded SHA1 hash key for a given XML element. The key is based on the
|
||||
* element name, the attribute names and their values. Child elements are ignored.
|
||||
* Attributes named 'z' are not concluded since they contain the hash key itself.
|
||||
*
|
||||
* @param element The element to create the base 64 encoded hash key for
|
||||
* @return the unique key
|
||||
*/
|
||||
public static String calculateUniqueKeyFor(final Element element) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(element.getTagName());
|
||||
NamedNodeMap attributes = element.getAttributes();
|
||||
SortedMap<String, String> attrKVStore = Collections.synchronizedSortedMap(new TreeMap<String, String>());
|
||||
for (int i = 0, n = attributes.getLength(); i < n; i++) {
|
||||
Node attr = attributes.item(i);
|
||||
if (!"z".equals(attr.getNodeName()) && !attr.getNodeName().startsWith("_")) {
|
||||
attrKVStore.put(attr.getNodeName(), attr.getNodeValue());
|
||||
}
|
||||
}
|
||||
for (Entry<String, String> entry: attrKVStore.entrySet()) {
|
||||
sb.append(entry.getKey()).append(entry.getValue());
|
||||
}
|
||||
return base64(sha1(sb.toString().getBytes()));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will compare the original document with the proposed document and return
|
||||
* true if adjustments to the original document were necessary. Adjustments are only made if new elements or
|
||||
* attributes are proposed. Changes to the order of attributes or elements in the
|
||||
* original document will not result in an adjustment.
|
||||
*
|
||||
* @param original document as read from the file system
|
||||
* @param proposed document as determined by the JspViewManager
|
||||
* @return true if the document was adjusted, otherwise false
|
||||
*/
|
||||
public static boolean compareDocuments(final Document original, final Document proposed) {
|
||||
boolean originalDocumentAdjusted = checkNamespaces(original, proposed);
|
||||
originalDocumentAdjusted |= addOrUpdateElements(original.getDocumentElement(), proposed.getDocumentElement(), originalDocumentAdjusted);
|
||||
originalDocumentAdjusted |= removeElements(original.getDocumentElement(), proposed.getDocumentElement(), originalDocumentAdjusted);
|
||||
return originalDocumentAdjusted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare necessary namespace declarations between original and proposed document, if
|
||||
* namespaces in the original are missing compared to the proposed, we add them to the
|
||||
* original.
|
||||
*
|
||||
* @param original document as read from the file system
|
||||
* @param proposed document as determined by the JspViewManager
|
||||
* @return true if the document was adjusted, otherwise false
|
||||
*/
|
||||
private static boolean checkNamespaces(final Document original, final Document proposed) {
|
||||
boolean originalDocumentChanged = false;
|
||||
NamedNodeMap nsNodes = proposed.getDocumentElement().getAttributes();
|
||||
for (int i = 0; i < nsNodes.getLength(); i++) {
|
||||
if (0 == original.getDocumentElement().getAttribute(nsNodes.item(i).getNodeName()).length()) {
|
||||
original.getDocumentElement().setAttribute(nsNodes.item(i).getNodeName(), nsNodes.item(i).getNodeValue());
|
||||
originalDocumentChanged = true;
|
||||
}
|
||||
}
|
||||
return originalDocumentChanged;
|
||||
}
|
||||
|
||||
private static boolean addOrUpdateElements(final Element original, final Element proposed, boolean originalDocumentChanged) {
|
||||
NodeList proposedChildren = proposed.getChildNodes();
|
||||
for (int i = 0, n = proposedChildren.getLength(); i < n; i++) { // Check proposed elements and compare to originals to find out if we need to add or replace elements
|
||||
Node node = proposedChildren.item(i);
|
||||
if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element proposedElement = (Element) node;
|
||||
String proposedId = proposedElement.getAttribute("id");
|
||||
if (proposedId.length() != 0) { // Only proposed elements with an id will be considered
|
||||
Element originalElement = XmlUtils.findFirstElement("//*[@id='" + proposedId + "']", original);
|
||||
if (null == originalElement) { // Insert proposed element given the original document has no element with a matching id
|
||||
Element placeHolder = DomUtils.findFirstElementByName("util:placeholder", original);
|
||||
if (placeHolder != null) { // Insert right before place holder if we can find it
|
||||
placeHolder.getParentNode().insertBefore(original.getOwnerDocument().importNode(proposedElement, false), placeHolder);
|
||||
} else { // Find the best place to insert the element
|
||||
if (proposed.getAttribute("id").length() != 0) { // Try to find the id of the proposed element's parent id in the original document
|
||||
Element originalParent = XmlUtils.findFirstElement("//*[@id='" + proposed.getAttribute("id") + "']", original);
|
||||
if (originalParent != null) { // Found parent with the same id, so we can just add it as new child
|
||||
originalParent.appendChild(original.getOwnerDocument().importNode(proposedElement, false));
|
||||
} else { // No parent found so we add it as a child of the root element (last resort)
|
||||
original.appendChild(original.getOwnerDocument().importNode(proposedElement, false));
|
||||
}
|
||||
} else { // No parent found so we add it as a child of the root element (last resort)
|
||||
original.appendChild(original.getOwnerDocument().importNode(proposedElement, false));
|
||||
}
|
||||
}
|
||||
originalDocumentChanged = true;
|
||||
} else { // We found an element in the original document with a matching id
|
||||
String originalElementHashCode = originalElement.getAttribute("z");
|
||||
if (originalElementHashCode.length() > 0) { // Only act if a hash code exists
|
||||
if ("?".equals(originalElementHashCode) || originalElementHashCode.equals(calculateUniqueKeyFor(originalElement))) { // Only act if hash codes match (no user changes in the element) or the user requests for the hash code to be regenerated
|
||||
if (!equalElements(originalElement, proposedElement)) { // Check if the elements have equal contents
|
||||
originalElement.getParentNode().replaceChild(original.getOwnerDocument().importNode(proposedElement, false), originalElement); //replace the original with the proposed element
|
||||
originalDocumentChanged = true;
|
||||
}
|
||||
if ("?".equals(originalElementHashCode)) { // Replace z if the user sets its value to '?' as an indication that roo should take over the management of this element again
|
||||
originalElement.setAttribute("z", calculateUniqueKeyFor(proposedElement));
|
||||
originalDocumentChanged = true;
|
||||
}
|
||||
} else { // If hash codes don't match we will mark the element as z="user-managed"
|
||||
if (!originalElementHashCode.equals("user-managed")) {
|
||||
originalElement.setAttribute("z", "user-managed"); // Mark the element as 'user-managed' if the hash codes don't match any more
|
||||
originalDocumentChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
originalDocumentChanged = addOrUpdateElements(original, proposedElement, originalDocumentChanged); // Walk through the document tree recursively
|
||||
}
|
||||
}
|
||||
return originalDocumentChanged;
|
||||
}
|
||||
|
||||
private static boolean removeElements(final Element original, final Element proposed, boolean originalDocumentChanged) {
|
||||
NodeList originalChildren = original.getChildNodes();
|
||||
for (int i = 0, n = originalChildren.getLength(); i < n; i++) { // Check original elements and compare to proposed to find out if we need to remove elements
|
||||
Node node = originalChildren.item(i);
|
||||
if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element originalElement = (Element) node;
|
||||
String originalId = originalElement.getAttribute("id");
|
||||
if (originalId.length() != 0) { // Only proposed elements with an id will be considered
|
||||
Element proposedElement = XmlUtils.findFirstElement("//*[@id='" + originalId + "']", proposed);
|
||||
if (null == proposedElement && (originalElement.getAttribute("z").equals(calculateUniqueKeyFor(originalElement)) || originalElement.getAttribute("z").equals("?"))) { // Remove original element given the proposed document has no element with a matching id
|
||||
originalElement.getParentNode().removeChild(originalElement);
|
||||
originalDocumentChanged = true;
|
||||
}
|
||||
}
|
||||
originalDocumentChanged = removeElements(originalElement, proposed, originalDocumentChanged); // Walk through the document tree recursively
|
||||
}
|
||||
}
|
||||
return originalDocumentChanged;
|
||||
}
|
||||
|
||||
private static boolean equalElements(final Element a, final Element b) {
|
||||
if (!a.getTagName().equals(b.getTagName())) {
|
||||
return false;
|
||||
}
|
||||
NamedNodeMap attributes = a.getAttributes();
|
||||
int customAttributeCounter = 0;
|
||||
for (int i = 0, n = attributes.getLength(); i < n; i++) {
|
||||
Node node = attributes.item(i);
|
||||
if (node != null && !node.getNodeName().startsWith("_")) {
|
||||
if (!node.getNodeName().equals("z") && (b.getAttribute(node.getNodeName()).length() == 0 || !b.getAttribute(node.getNodeName()).equals(node.getNodeValue()))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
customAttributeCounter++;
|
||||
}
|
||||
}
|
||||
if (a.getAttributes().getLength() - customAttributeCounter != b.getAttributes().getLength()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sha-1 hash value for the given data byte array.
|
||||
*
|
||||
* @param data to hash
|
||||
* @return byte[] hash of the input data
|
||||
*/
|
||||
private static byte[] sha1(final byte[] data) {
|
||||
Assert.notNull(digest, "Could not create hash key for identifier");
|
||||
return digest.digest(data);
|
||||
}
|
||||
|
||||
private static String base64(final byte[] data) {
|
||||
return Base64.encodeBytes(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private XmlRoundTripUtils() {}
|
||||
}
|
||||
@@ -1,573 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpression;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.w3c.dom.DOMConfiguration;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
|
||||
import org.w3c.dom.ls.DOMImplementationLS;
|
||||
import org.w3c.dom.ls.LSException;
|
||||
import org.w3c.dom.ls.LSOutput;
|
||||
import org.w3c.dom.ls.LSSerializer;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Utilities related to XML usage.
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @author Ben Alex
|
||||
* @author Alan Stewart
|
||||
* @author Andrew Swan
|
||||
* @since 1.0
|
||||
*/
|
||||
public final class XmlUtils {
|
||||
|
||||
// Constants
|
||||
private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
private static final Map<String, XPathExpression> compiledExpressionCache = new HashMap<String, XPathExpression>();
|
||||
private static final TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
private static final XPath xpath = XPathFactory.newInstance().newXPath();
|
||||
|
||||
/**
|
||||
* Returns the given XML as the root {@link Element} of a new {@link Document}
|
||||
*
|
||||
* @param xml the XML to convert; can be blank
|
||||
* @return <code>null</code> if the given XML is blank
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static Element stringToElement(final String xml) {
|
||||
if (StringUtils.isBlank(xml)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return factory.newDocumentBuilder().parse(new ByteArrayInputStream(xml.getBytes())).getDocumentElement();
|
||||
} catch (final IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (final ParserConfigurationException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (final SAXException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link Element} containing the given text
|
||||
*
|
||||
* @param document the document to contain the new element
|
||||
* @param tagName the element's tag name (required)
|
||||
* @param text the text to set; can be <code>null</code> for none
|
||||
* @return a non-<code>null</code> element
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public static Element createTextElement(final Document document, final String tagName, final String text) {
|
||||
final Element element = document.createElement(tagName);
|
||||
element.setTextContent(text);
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an XML document from the supplied input stream and return a document.
|
||||
*
|
||||
* @param inputStream the input stream to read from (required). The stream is closed upon completion.
|
||||
* @return a document.
|
||||
* @throws IllegalStateException if the stream could not be read
|
||||
*/
|
||||
public static Document readXml(InputStream inputStream) {
|
||||
Assert.notNull(inputStream, "InputStream required");
|
||||
try {
|
||||
if (!(inputStream instanceof BufferedInputStream)) {
|
||||
inputStream = new BufferedInputStream(inputStream);
|
||||
}
|
||||
return getDocumentBuilder().parse(inputStream);
|
||||
} catch (final Exception e) {
|
||||
throw new IllegalStateException("Could not open input stream", e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an XML document to the OutputStream provided. This will use the pre-configured Roo provided Transformer.
|
||||
*
|
||||
* @param outputStream the output stream to write to. The stream is closed upon completion.
|
||||
* @param document the document to write.
|
||||
*/
|
||||
public static void writeXml(final OutputStream outputStream, final Document document) {
|
||||
writeXml(createIndentingTransformer(), outputStream, document);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an XML document to the OutputStream provided. This will use the provided Transformer.
|
||||
*
|
||||
* @param transformer the transformer (can be obtained from XmlUtils.createIndentingTransformer())
|
||||
* @param outputStream the output stream to write to. The stream is closed upon completion.
|
||||
* @param document the document to write.
|
||||
*/
|
||||
public static void writeXml(final Transformer transformer, OutputStream outputStream, final Document document) {
|
||||
Assert.notNull(transformer, "Transformer required");
|
||||
Assert.notNull(outputStream, "OutputStream required");
|
||||
Assert.notNull(document, "Document required");
|
||||
|
||||
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
|
||||
try {
|
||||
if (!(outputStream instanceof BufferedOutputStream)) {
|
||||
outputStream = new BufferedOutputStream(outputStream);
|
||||
}
|
||||
final StreamResult streamResult = createUnixStreamResultForEntry(outputStream);
|
||||
transformer.transform(new DOMSource(document), streamResult);
|
||||
} catch (final Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an XML document to the OutputStream provided. This method will detect if the JDK supports the
|
||||
* DOM Level 3 "format-pretty-print" configuration and make use of it. If not found it will fall back to
|
||||
* using formatting offered by TrAX.
|
||||
*
|
||||
* @param outputStream the output stream to write to. The stream is closed upon completion.
|
||||
* @param document the document to write.
|
||||
*/
|
||||
public static void writeFormattedXml(final OutputStream outputStream, final Document document) {
|
||||
// Note that the "format-pretty-print" DOM configuration parameter can only be set in JDK 1.6+.
|
||||
final DOMImplementation domImplementation = document.getImplementation();
|
||||
if (domImplementation.hasFeature("LS", "3.0") && domImplementation.hasFeature("Core", "2.0")) {
|
||||
DOMImplementationLS domImplementationLS = null;
|
||||
try {
|
||||
domImplementationLS = (DOMImplementationLS) domImplementation.getFeature("LS", "3.0");
|
||||
} catch (final NoSuchMethodError nsme) {
|
||||
// Fall back to default LS
|
||||
DOMImplementationRegistry registry = null;
|
||||
try {
|
||||
registry = DOMImplementationRegistry.newInstance();
|
||||
} catch (final Exception e) {
|
||||
// DOMImplementationRegistry not available. Falling back to TrAX.
|
||||
writeXml(outputStream, document);
|
||||
return;
|
||||
}
|
||||
if (registry != null) {
|
||||
domImplementationLS = (DOMImplementationLS) registry.getDOMImplementation("LS");
|
||||
} else {
|
||||
// DOMImplementationRegistry not available. Falling back to TrAX.
|
||||
writeXml(outputStream, document);
|
||||
}
|
||||
}
|
||||
if (domImplementationLS != null) {
|
||||
final LSSerializer lsSerializer = domImplementationLS.createLSSerializer();
|
||||
final DOMConfiguration domConfiguration = lsSerializer.getDomConfig();
|
||||
if (domConfiguration.canSetParameter("format-pretty-print", Boolean.TRUE)) {
|
||||
lsSerializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
|
||||
final LSOutput lsOutput = domImplementationLS.createLSOutput();
|
||||
lsOutput.setEncoding("UTF-8");
|
||||
lsOutput.setByteStream(outputStream);
|
||||
try {
|
||||
lsSerializer.write(document, lsOutput);
|
||||
} catch (final LSException lse) {
|
||||
throw new IllegalStateException(lse);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(outputStream);
|
||||
}
|
||||
} else {
|
||||
// DOMConfiguration 'format-pretty-print' parameter not available. Falling back to TrAX.
|
||||
writeXml(outputStream, document);
|
||||
}
|
||||
} else {
|
||||
// DOMImplementationLS not available. Falling back to TrAX.
|
||||
writeXml(outputStream, document);
|
||||
}
|
||||
} else {
|
||||
// DOM 3.0 LS and/or DOM 2.0 Core not supported. Falling back to TrAX.
|
||||
writeXml(outputStream, document);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two DOM {@link Node nodes} by comparing the representations of the nodes as XML strings
|
||||
*
|
||||
* @param node1 the first node
|
||||
* @param node2 the second node
|
||||
* @return true if the XML representation node1 is the same as the XML representation of node2, otherwise false
|
||||
*/
|
||||
public static boolean compareNodes(Node node1, Node node2) {
|
||||
Assert.notNull(node1, "First node required");
|
||||
Assert.notNull(node2, "Second node required");
|
||||
// The documents need to be cloned as normalization has side-effects
|
||||
node1 = node1.cloneNode(true);
|
||||
node2 = node2.cloneNode(true);
|
||||
// The documents need to be normalized before comparison takes place to remove any formatting that interfere with comparison
|
||||
if (node1 instanceof Document && node2 instanceof Document) {
|
||||
((Document) node1).normalizeDocument();
|
||||
((Document) node2).normalizeDocument();
|
||||
} else {
|
||||
node1.normalize();
|
||||
node2.normalize();
|
||||
}
|
||||
return nodeToString(node1).equals(nodeToString(node2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link Node node} to an XML string
|
||||
*
|
||||
* @param node the first element
|
||||
* @return the XML String representation of the node, never null
|
||||
*/
|
||||
public static String nodeToString(final Node node) {
|
||||
try {
|
||||
final StringWriter writer = new StringWriter();
|
||||
createIndentingTransformer().transform(new DOMSource(node), new StreamResult(writer));
|
||||
return writer.toString();
|
||||
} catch (final TransformerException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link StreamResult} by wrapping the given outputStream in an
|
||||
* {@link OutputStreamWriter} that transforms Windows line endings (\r\n)
|
||||
* into Unix line endings (\n) on Windows for consistency with Roo's templates.
|
||||
*
|
||||
* @param outputStream
|
||||
* @return StreamResult
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
private static StreamResult createUnixStreamResultForEntry(final OutputStream outputStream) throws UnsupportedEncodingException {
|
||||
final Writer writer;
|
||||
if (StringUtils.LINE_SEPARATOR.equals("\r\n")) {
|
||||
writer = new OutputStreamWriter(outputStream, "ISO-8859-1") {
|
||||
@Override
|
||||
public void write(final char[] cbuf, final int off, final int len) throws IOException {
|
||||
for (int i = off; i < off + len; i++) {
|
||||
if (cbuf[i] != '\r' || (i < cbuf.length - 1 && cbuf[i + 1] != '\n')) {
|
||||
super.write(cbuf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final int c) throws IOException {
|
||||
if (c != '\r') super.write(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final String str, final int off, final int len) throws IOException {
|
||||
final String orig = str.substring(off, off + len);
|
||||
final String filtered = orig.replace("\r\n", "\n");
|
||||
final int lengthDiff = orig.length() - filtered.length();
|
||||
if (filtered.endsWith("\r")) {
|
||||
super.write(filtered.substring(0, filtered.length() - 1), 0, len - lengthDiff - 1);
|
||||
} else {
|
||||
super.write(filtered, 0, len - lengthDiff);
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
writer = new OutputStreamWriter(outputStream, "ISO-8859-1");
|
||||
}
|
||||
return new StreamResult(writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the given parent element for a child element matching the given
|
||||
* XPath expression.
|
||||
*
|
||||
* Please note that the XPath parser used is NOT namespace aware. So if you
|
||||
* want to find an element <code><beans><sec:http></code>, you
|
||||
* need to use the following XPath expression '/beans/http'.
|
||||
*
|
||||
* @param xPathExpression the xPathExpression (required)
|
||||
* @param parent the parent DOM element (required)
|
||||
* @return the Element if discovered (null if no such {@link Element} found)
|
||||
*/
|
||||
public static Element findFirstElement(final String xPathExpression, final Node parent) {
|
||||
final Node node = findNode(xPathExpression, parent);
|
||||
if (node instanceof Element) {
|
||||
return (Element) node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks in under a given root element whether it can find a child node
|
||||
* which matches the XPath expression supplied. Returns {@link Node} if
|
||||
* exists.
|
||||
*
|
||||
* Please note that the XPath parser used is NOT namespace aware. So if you
|
||||
* want to find a element <code><beans><sec:http></code>, you
|
||||
* need to use the XPath expression '<code>/beans/http</code>'.
|
||||
*
|
||||
* @param xPathExpression the XPath expression (required)
|
||||
* @param root the parent DOM element (required)
|
||||
* @return the Node if discovered (null if not found)
|
||||
*/
|
||||
public static Node findNode(final String xPathExpression, final Node root) {
|
||||
Assert.hasText(xPathExpression, "XPath expression required");
|
||||
Assert.notNull(root, "Root element required");
|
||||
Node node = null;
|
||||
try {
|
||||
XPathExpression expr = compiledExpressionCache.get(xPathExpression);
|
||||
if (expr == null) {
|
||||
expr = xpath.compile(xPathExpression);
|
||||
compiledExpressionCache.put(xPathExpression, expr);
|
||||
}
|
||||
node = (Node) expr.evaluate(root, XPathConstants.NODE);
|
||||
} catch (final XPathExpressionException e) {
|
||||
throw new IllegalArgumentException("Unable evaluate XPath expression '" + xPathExpression + "'", e);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks in under a given root element whether it can find a child element
|
||||
* which matches the XPath expression supplied. The {@link Element} must
|
||||
* exist. Returns {@link Element} if exists.
|
||||
*
|
||||
* Please note that the XPath parser used is NOT namespace aware. So if you
|
||||
* want to find a element <beans><sec:http> you need to use the following
|
||||
* XPath expression '/beans/http'.
|
||||
*
|
||||
* @param xPathExpression the XPath expression (required)
|
||||
* @param root the parent DOM element (required)
|
||||
* @return the Element if discovered (never null; an exception is thrown if cannot be found)
|
||||
*/
|
||||
public static Element findRequiredElement(final String xPathExpression, final Element root) {
|
||||
Assert.hasText(xPathExpression, "XPath expression required");
|
||||
Assert.notNull(root, "Root element required");
|
||||
final Element element = findFirstElement(xPathExpression, root);
|
||||
Assert.notNull(element, "Unable to obtain required element '" + xPathExpression + "' from element '" + root + "'");
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks in under a given root element whether it can find a child elements
|
||||
* which match the XPath expression supplied. Returns a {@link List} of
|
||||
* {@link Element} if they exist.
|
||||
*
|
||||
* Please note that the XPath parser used is NOT namespace aware. So if you
|
||||
* want to find a element <beans><sec:http> you need to use the following
|
||||
* XPath expression '/beans/http'.
|
||||
*
|
||||
* @param xPathExpression the xPathExpression
|
||||
* @param root the parent DOM element
|
||||
* @return a {@link List} of type {@link Element} if discovered, otherwise an empty list (never null)
|
||||
*/
|
||||
public static List<Element> findElements(final String xPathExpression, final Element root) {
|
||||
final List<Element> elements = new ArrayList<Element>();
|
||||
NodeList nodes = null;
|
||||
|
||||
try {
|
||||
XPathExpression expr = compiledExpressionCache.get(xPathExpression);
|
||||
if (expr == null) {
|
||||
expr = xpath.compile(xPathExpression);
|
||||
compiledExpressionCache.put(xPathExpression, expr);
|
||||
}
|
||||
nodes = (NodeList) expr.evaluate(root, XPathConstants.NODESET);
|
||||
} catch (final XPathExpressionException e) {
|
||||
throw new IllegalArgumentException("Unable evaluate xpath expression", e);
|
||||
}
|
||||
|
||||
for (int i = 0, n = nodes.getLength(); i < n; i++) {
|
||||
elements.add((Element) nodes.item(i));
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for a given element whether it can find an attribute which matches the
|
||||
* XPath expression supplied. Returns {@link Node} if exists.
|
||||
*
|
||||
* @param xPathExpression the xPathExpression (required)
|
||||
* @param element (required)
|
||||
* @return the Node if discovered (null if not found)
|
||||
*/
|
||||
public static Node findFirstAttribute(final String xPathExpression, final Element element) {
|
||||
Node attr = null;
|
||||
try {
|
||||
XPathExpression expr = compiledExpressionCache.get(xPathExpression);
|
||||
if (expr == null) {
|
||||
expr = xpath.compile(xPathExpression);
|
||||
compiledExpressionCache.put(xPathExpression, expr);
|
||||
}
|
||||
attr = (Node) expr.evaluate(element, XPathConstants.NODE);
|
||||
} catch (final XPathExpressionException e) {
|
||||
throw new IllegalArgumentException("Unable evaluate xpath expression", e);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a transformer that indents entries by 4 characters (never null)
|
||||
*/
|
||||
public static Transformer createIndentingTransformer() {
|
||||
Transformer transformer;
|
||||
try {
|
||||
transformerFactory.setAttribute("indent-number", 4);
|
||||
transformer = transformerFactory.newTransformer();
|
||||
} catch (final Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
|
||||
return transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new document builder (never null)
|
||||
*/
|
||||
public static DocumentBuilder getDocumentBuilder() {
|
||||
// factory.setNamespaceAware(true);
|
||||
try {
|
||||
return factory.newDocumentBuilder();
|
||||
} catch (final ParserConfigurationException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root element of the given XML file.
|
||||
*
|
||||
* @param clazz the class from whose package to open the file (required)
|
||||
* @param xmlFilePath the path of the XML file relative to the given class'
|
||||
* package (required)
|
||||
* @return a non-<code>null</code> element
|
||||
* @see Document#getDocumentElement()
|
||||
*/
|
||||
public static Element getRootElement(final Class<?> clazz, final String xmlFilePath) {
|
||||
final InputStream inputStream = FileUtils.getInputStream(clazz, xmlFilePath);
|
||||
Assert.notNull(inputStream, "Could not open the file '" + xmlFilePath + "'");
|
||||
return readXml(inputStream).getDocumentElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root element of an addon's configuration file.
|
||||
*
|
||||
* @param clazz which owns the configuration
|
||||
* @return the configuration root element
|
||||
*/
|
||||
public static Element getConfiguration(final Class<?> clazz) {
|
||||
return getRootElement(clazz, "configuration.xml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a XHTML compliant id (used in jspx) to a CSS3 selector spec compliant id. In that
|
||||
* it will replace all '.,:,-' to '_'
|
||||
*
|
||||
* @param proposed Id
|
||||
* @return cleaned up Id
|
||||
*/
|
||||
public static String convertId(final String proposed) {
|
||||
return proposed.replaceAll("[:\\.-]", "_");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the presented element for illegal characters that could cause malformed XML.
|
||||
*
|
||||
* @param element the content of the XML element
|
||||
* @throws IllegalArgumentException if the element is null, has no text or contains illegal characters
|
||||
*/
|
||||
public static void assertElementLegal(final String element) {
|
||||
if (StringUtils.isBlank(element)) {
|
||||
throw new IllegalArgumentException("Element required");
|
||||
}
|
||||
|
||||
// Note regular expression for legal characters found to be x5 slower in profiling than this approach
|
||||
final char[] value = element.toCharArray();
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
final char c = value[i];
|
||||
if (' ' == c || '*' == c || '>' == c || '<' == c || '!' == c || '@' == c || '%' == c || '^' == c ||
|
||||
'?' == c || '(' == c || ')' == c || '~' == c || '`' == c || '{' == c || '}' == c || '[' == c || ']' == c ||
|
||||
'|' == c || '\\' == c || '\'' == c || '+' == c) {
|
||||
throw new IllegalArgumentException("Illegal name '" + element + "' (illegal character)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTextContent(final String path, final Element parentElement) {
|
||||
return getTextContent(path, parentElement, null);
|
||||
}
|
||||
|
||||
public static String getTextContent(final String path, final Element parentElement, final String valueIfNull) {
|
||||
final Element element = XmlUtils.findFirstElement(path, parentElement);
|
||||
if (element != null) {
|
||||
return element.getTextContent();
|
||||
}
|
||||
return valueIfNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks in under a given root element whether it can find a child element
|
||||
* which matches the name supplied. Returns {@link Element} if exists.
|
||||
*
|
||||
* @param name the Element name (required)
|
||||
* @param root the parent DOM element (required)
|
||||
* @return the Element if discovered
|
||||
* @deprecated use {@link DomUtils#findFirstElementByName(String, Element)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static Element findFirstElementByName(final String name, final Element root) {
|
||||
return DomUtils.findFirstElementByName(name, root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes empty text nodes from the specified node
|
||||
*
|
||||
* @param node the element where empty text nodes will be removed
|
||||
* @deprecated use {@link DomUtils#removeTextNodes(Node)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static void removeTextNodes(final Node node) {
|
||||
DomUtils.removeTextNodes(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor is private to prevent instantiation
|
||||
*/
|
||||
private XmlUtils() {}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.CollectionUtils;
|
||||
import org.springframework.shell.support.util.Filter;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Unit test of {@link CollectionUtils}
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class CollectionUtilsTest {
|
||||
|
||||
// A simple filter for testing the filtering methods
|
||||
private static final Filter<String> NON_BLANK_FILTER = new Filter<String>() {
|
||||
public boolean include(final String instance) {
|
||||
return StringUtils.hasText(instance);
|
||||
}
|
||||
};
|
||||
|
||||
private static class Parent {
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
private static class Child extends Parent {}
|
||||
|
||||
@Test
|
||||
public void testFilterNullCollection() {
|
||||
assertEquals(0, CollectionUtils.filter(null, NON_BLANK_FILTER).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterNonNullIterableWithNullFilter() {
|
||||
// Set up
|
||||
final Iterable<String> inputs = Arrays.asList("a", "");
|
||||
|
||||
// Invoke
|
||||
final List<? extends String> results = CollectionUtils.filter(inputs, null);
|
||||
|
||||
// Check
|
||||
assertEquals(inputs, results);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterNonNullIterableWithNonNullFilter() {
|
||||
// Set up
|
||||
final Iterable<String> inputs = Arrays.asList("a", "", null, "b");
|
||||
|
||||
// Invoke
|
||||
final List<? extends String> results = CollectionUtils.filter(inputs, NON_BLANK_FILTER);
|
||||
|
||||
// Check
|
||||
assertEquals(Arrays.asList("a", "b"), results);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddNullCollectionToNullCollection() {
|
||||
assertFalse(CollectionUtils.addAll(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddNullCollectionToNonNullCollection() {
|
||||
// Set up
|
||||
final Parent parent = new Parent();
|
||||
final Collection<Parent> parents = Arrays.asList(parent);
|
||||
|
||||
// Invoke
|
||||
final boolean added = CollectionUtils.addAll(null, parents);
|
||||
|
||||
// Check
|
||||
assertFalse(added);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddNonNullCollectionToNonNullCollection() {
|
||||
// Set up
|
||||
final Parent parent = new Parent();
|
||||
final Child child = new Child();
|
||||
final Collection<Parent> parents = new ArrayList<Parent>();
|
||||
parents.add(parent);
|
||||
|
||||
// Invoke
|
||||
final boolean added = CollectionUtils.addAll(Arrays.asList(child), parents);
|
||||
|
||||
// Check
|
||||
assertTrue(added);
|
||||
assertEquals(Arrays.asList(parent, child), parents);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPopulateNullCollectionWithNullCollection() {
|
||||
assertNull(CollectionUtils.populate(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPopulateNonNullCollectionWithNullCollection() {
|
||||
// Set up
|
||||
final Collection<Parent> collection = new ArrayList<Parent>();
|
||||
collection.add(new Parent());
|
||||
|
||||
// Invoke
|
||||
final Collection<Parent> result = CollectionUtils.populate(collection, null);
|
||||
|
||||
// Check
|
||||
assertEquals(0, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPopulateNonNullCollectionWithNonNullCollection() {
|
||||
// Set up
|
||||
final Collection<Parent> originalCollection = new ArrayList<Parent>();
|
||||
originalCollection.add(new Parent());
|
||||
final Child child = new Child();
|
||||
|
||||
// Invoke
|
||||
final Collection<Parent> result = CollectionUtils.populate(originalCollection, Arrays.asList(child));
|
||||
|
||||
// Check
|
||||
assertEquals(Collections.singletonList(child), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFirstElementOfNullCollection() {
|
||||
assertNull(CollectionUtils.firstElementOf(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFirstElementOfEmptyCollection() {
|
||||
assertNull(CollectionUtils.firstElementOf(Collections.emptySet()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFirstElementOfSingleElementCollection() {
|
||||
final String member = "x";
|
||||
assertEquals(member, CollectionUtils.firstElementOf(Collections.singleton(member)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFirstElementOfMultiElementCollection() {
|
||||
final String[] members = {"x", "y", "z"};
|
||||
assertEquals(members[0], CollectionUtils.firstElementOf(Arrays.asList(members)));
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.DomUtils;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.shell.support.util.XmlUtils;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Unit test of {@link DomUtils}
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class DomUtilsTest {
|
||||
|
||||
// Constants
|
||||
private static final String DEFAULT_TEXT = "foo";
|
||||
private static final String NODE_TEXT = "bar";
|
||||
private static final String XML_BEFORE_REMOVAL =
|
||||
"<top>" +
|
||||
" <middle>" +
|
||||
" <bottom id=\"1\" />" +
|
||||
" <bottom id=\"2\" />" +
|
||||
" </middle>" +
|
||||
"</top>";
|
||||
private static final String XML_AFTER_REMOVAL =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<top> <middle/>\n" +
|
||||
"</top>";
|
||||
|
||||
/**
|
||||
* Asserts that the given XML node contains the expected content
|
||||
*
|
||||
* @param expectedLines the expected lines of XML (required); separate each
|
||||
* line with "\n" regardless of the platform
|
||||
* @param actualNode the actual XML node (required)
|
||||
* @throws AssertionError if they are not equal
|
||||
*/
|
||||
private void assertXmlEquals(final String expectedXml, final Node actualNode) {
|
||||
// Replace the dummy line terminator with the platform-specific one that
|
||||
// will be applied by XmlUtils.nodeToString.
|
||||
final String normalisedXml = expectedXml.replace("\n", StringUtils.LINE_SEPARATOR);
|
||||
// Trim trailing whitespace as XmlUtils.nodeToString appends an extra newline.
|
||||
final String actualXml = StringUtils.trimTrailingWhitespace(XmlUtils.nodeToString(actualNode));
|
||||
assertEquals(normalisedXml, actualXml);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTextContentOfNullNode() {
|
||||
assertEquals(DEFAULT_TEXT, DomUtils.getTextContent(null, DEFAULT_TEXT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTextContentOfNonNullNode() {
|
||||
// Set up
|
||||
final Node mockNode = mock(Node.class);
|
||||
when(mockNode.getTextContent()).thenReturn(NODE_TEXT);
|
||||
|
||||
assertEquals(NODE_TEXT, DomUtils.getTextContent(mockNode, DEFAULT_TEXT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveElements() throws Exception {
|
||||
// Set up
|
||||
final Element root = XmlUtils.stringToElement(XML_BEFORE_REMOVAL);
|
||||
final Element middle = DomUtils.getChildElementByTagName(root, "middle");
|
||||
|
||||
// Invoke
|
||||
DomUtils.removeElements("bottom", middle);
|
||||
|
||||
// Check
|
||||
assertXmlEquals(XML_AFTER_REMOVAL, root);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -27,10 +27,8 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.FileCopyUtils;
|
||||
import org.springframework.shell.support.util.FileUtils;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
import org.springframework.shell.support.util.loader.Loader;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* Unit test of {@link FileUtils}
|
||||
@@ -39,7 +37,7 @@ import org.springframework.shell.support.util.loader.Loader;
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class FileUtilsTest {
|
||||
|
||||
|
||||
private static final String MISSING_FILE = "no-such-file.txt";
|
||||
private static final String TEST_FILE = "sub" + File.separator + "file-utils-test.txt";
|
||||
|
||||
@@ -52,136 +50,136 @@ public class FileUtilsTest {
|
||||
public void testGetSystemDependentPathFromNoElements() {
|
||||
FileUtils.getSystemDependentPath();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetSystemDependentPathFromOneElement() {
|
||||
assertEquals("foo", FileUtils.getSystemDependentPath("foo"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetSystemDependentPathFromMultipleElements() {
|
||||
final String expectedPath = "foo" + File.separator + "bar";
|
||||
assertEquals(expectedPath, FileUtils.getSystemDependentPath("foo", "bar"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetFileSeparatorAsRegex() throws Exception {
|
||||
// Set up
|
||||
final String regex = FileUtils.getFileSeparatorAsRegex();
|
||||
final String currentDirectory = new File(FileUtils.CURRENT_DIRECTORY).getCanonicalPath();
|
||||
|
||||
|
||||
// Invoke
|
||||
final String[] pathElements = currentDirectory.split(regex);
|
||||
|
||||
|
||||
// Check
|
||||
assertTrue(pathElements.length > 0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveTrailingSeparatorFromNullPath() {
|
||||
assertNull(FileUtils.removeTrailingSeparator(null));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveTrailingSeparatorFromEmptyPath() {
|
||||
assertEquals("", FileUtils.removeTrailingSeparator(""));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveTrailingSeparatorFromPathWithLeadingSeparator() {
|
||||
final String path = File.separator + "foo";
|
||||
assertEquals(path, FileUtils.removeTrailingSeparator(path));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveTrailingSeparatorFromPathWithMultipleTrailingSeparators() {
|
||||
final String path = "foo" + StringUtils.repeat(File.separator, 3);
|
||||
final String path = "foo" + File.separator + File.separator + File.separator;
|
||||
assertEquals("foo", FileUtils.removeTrailingSeparator(path));
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testEnsureTrailingSeparatorForNullPath() {
|
||||
FileUtils.ensureTrailingSeparator(null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEnsureTrailingSeparatorForEmptyPath() {
|
||||
assertEquals(File.separator, FileUtils.ensureTrailingSeparator(""));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEnsureTrailingSeparatorForPathWithNoTrailingSeparator() {
|
||||
final String path = "foo";
|
||||
assertEquals(path + File.separator, FileUtils.ensureTrailingSeparator(path));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEnsureTrailingSeparatorForPathWithOneTrailingSeparator() {
|
||||
final String path = "foo" + File.separator;
|
||||
assertEquals(path, FileUtils.ensureTrailingSeparator(path));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEnsureTrailingSeparatorFromPathWithMultipleTrailingSeparators() {
|
||||
final String path = "foo" + StringUtils.repeat(File.separator, 3);
|
||||
final String path = "foo" + File.separator + File.separator + File.separator;
|
||||
assertEquals("foo" + File.separator, FileUtils.ensureTrailingSeparator(path));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetCanonicalPathForNullFile() {
|
||||
assertNull(FileUtils.getCanonicalPath(null));
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testGetCanonicalPathForInvalidFile() throws Exception {
|
||||
// Set up
|
||||
final File invalidFile = mock(File.class);
|
||||
when(invalidFile.getCanonicalPath()).thenThrow(new IOException("dummy"));
|
||||
|
||||
|
||||
// Invoke
|
||||
FileUtils.getCanonicalPath(invalidFile);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetCanonicalPathForValidFile() throws Exception {
|
||||
// Set up
|
||||
final File validFile = mock(File.class);
|
||||
final String canonicalPath = "the_path";
|
||||
when(validFile.getCanonicalPath()).thenReturn(canonicalPath);
|
||||
|
||||
|
||||
// Invoke
|
||||
final String actualPath = FileUtils.getCanonicalPath(validFile);
|
||||
|
||||
|
||||
// Check
|
||||
assertEquals(canonicalPath, actualPath);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveLeadingAndTrailingSeparatorsFromNullPath() {
|
||||
assertNull(FileUtils.removeLeadingAndTrailingSeparators(null));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveLeadingAndTrailingSeparatorsFromEmptyPath() {
|
||||
assertEquals("", FileUtils.removeLeadingAndTrailingSeparators(""));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveLeadingAndTrailingSeparatorsFromPlainPath() {
|
||||
final String path = "foo";
|
||||
assertEquals(path, FileUtils.removeLeadingAndTrailingSeparators(path));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveLeadingAndTrailingSeparatorsFromPathWithBoth() {
|
||||
// Set up
|
||||
final String separators = StringUtils.repeat(File.separator, 4);
|
||||
final String separators = File.separator + File.separator + File.separator + File.separator;
|
||||
final String path = separators + "foo" + separators;
|
||||
|
||||
|
||||
// Invoke and check
|
||||
assertEquals("foo", FileUtils.removeLeadingAndTrailingSeparators(path));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetFile() {
|
||||
assertTrue(FileUtils.getFile(Loader.class, TEST_FILE).isFile());
|
||||
@@ -191,47 +189,47 @@ public class FileUtilsTest {
|
||||
public void testGetPath() {
|
||||
assertEquals("/org/springframework/shell/support/util/loader/sub/file-utils-test.txt", FileUtils.getPath(Loader.class, "sub/file-utils-test.txt"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetInputStreamOfFileInSubDirectory() throws Exception {
|
||||
// Invoke
|
||||
final InputStream inputStream = FileUtils.getInputStream(Loader.class, TEST_FILE);
|
||||
|
||||
|
||||
// Check
|
||||
final String contents = FileCopyUtils.copyToString(new InputStreamReader(inputStream));
|
||||
assertEquals("This file is required for FileUtilsTest.", contents);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetInputStreamOfInvalidFile() throws Exception {
|
||||
FileUtils.getInputStream(Loader.class, MISSING_FILE);
|
||||
}
|
||||
|
||||
|
||||
private void assertFirstDirectory(final String path, final String expectedFirstDirectory) {
|
||||
// Invoke
|
||||
final String firstDirectory = FileUtils.getFirstDirectory(path);
|
||||
|
||||
|
||||
// Check
|
||||
assertEquals(expectedFirstDirectory, firstDirectory);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetFirstDirectoryOfExistingDirectory() {
|
||||
// Set up
|
||||
final String directory = FileUtils.getFile(Loader.class, TEST_FILE).getParent();
|
||||
|
||||
|
||||
// Invoke
|
||||
final String firstDirectory = FileUtils.getFirstDirectory(directory);
|
||||
|
||||
|
||||
// Check
|
||||
assertTrue(firstDirectory.endsWith("sub"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetFirstDirectoryOfExistingFile() {
|
||||
assertFirstDirectory(TEST_FILE, "sub");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBackOneDirectory() {
|
||||
assertEquals("foo" + File.separator + "bar", FileUtils.backOneDirectory("foo" + File.separator + "bar" + File.separator + "baz" + File.separator));
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.NumberUtils;
|
||||
|
||||
/**
|
||||
* Unit test of {@link NumberUtils}.
|
||||
*
|
||||
* @author Alan Stewart
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class NumberUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testMinValueOfEmptyArray() {
|
||||
assertNull(NumberUtils.min(new Number[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullMinValues() {
|
||||
assertNull(NumberUtils.min(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneMinValue() {
|
||||
assertEquals(BigDecimal.ONE, NumberUtils.min(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinValues() {
|
||||
assertEquals(new BigDecimal("11"), NumberUtils.min(21, 11, 20L, 33.3D, new Short("55"), 11.3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinValues2() {
|
||||
assertEquals(new BigDecimal("3"), NumberUtils.min(null, 3, null, 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleMinValues() {
|
||||
assertEquals(new BigDecimal(-10), NumberUtils.min(0, 10, null, -10, Integer.MAX_VALUE, BigInteger.TEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleSameMinValues() {
|
||||
assertEquals(-1, NumberUtils.min(-1, -1F, -1L, -1D).intValueExact());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullMaxValues() {
|
||||
assertNull(NumberUtils.max(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneMaxValue() {
|
||||
assertEquals(BigDecimal.ONE, NumberUtils.max(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxValues() {
|
||||
assertEquals(BigDecimal.ONE, NumberUtils.max(null, 1, -1, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleMaxValues() {
|
||||
assertEquals(new BigDecimal(String.valueOf(Double.MAX_VALUE)), NumberUtils.max(0, null, Integer.MIN_VALUE, 10, -10, Integer.MAX_VALUE, Long.MAX_VALUE, Double.MAX_VALUE));
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Unit test of {@link ObjectUtils}
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class ObjectUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testCompareTwoNulls() {
|
||||
assertEquals(0, ObjectUtils.nullSafeComparison(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompareNullWithNonNull() {
|
||||
// Invoke
|
||||
final int result = ObjectUtils.nullSafeComparison(null, "");
|
||||
|
||||
// Check
|
||||
assertTrue(result < 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompareNonNullWithNull() {
|
||||
// Invoke
|
||||
final int result = ObjectUtils.nullSafeComparison("", null);
|
||||
|
||||
// Check
|
||||
assertTrue(result > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompareLesserWithGreater() {
|
||||
// Invoke
|
||||
final int result = ObjectUtils.nullSafeComparison(100, 200);
|
||||
|
||||
// Check
|
||||
assertTrue(result < 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompareGreaterWithLesser() {
|
||||
// Invoke
|
||||
final int result = ObjectUtils.nullSafeComparison(300, 200);
|
||||
|
||||
// Check
|
||||
assertTrue(result > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompareTwoEqualObjects() {
|
||||
assertEquals(0, ObjectUtils.nullSafeComparison(400, 400));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithNullObjectAndNullDefault() {
|
||||
assertNull(ObjectUtils.toString(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithNullObjectAndEmptyDefault() {
|
||||
assertEquals("", ObjectUtils.toString(null, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithNullObjectAndNonEmptyDefault() {
|
||||
assertEquals("x", ObjectUtils.toString(null, "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringWithNonNullObjectAndNullDefault() {
|
||||
assertEquals("1", ObjectUtils.toString(1, "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfNullWhenObjectIsNullAndDefaultIsNull() {
|
||||
assertNull(ObjectUtils.defaultIfNull(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfNullWhenObjectIsNullAndDefaultIsNotNull() {
|
||||
final Object defaultValue = 27;
|
||||
assertEquals(defaultValue, ObjectUtils.defaultIfNull(null, defaultValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfNullWhenObjectIsNotNullAndDefaultIsNull() {
|
||||
final Object value = 27;
|
||||
assertEquals(value, ObjectUtils.defaultIfNull(value, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfNullWhenObjectIsNotNullAndDefaultIsNotNull() {
|
||||
final Integer value = 27;
|
||||
assertEquals(value, ObjectUtils.defaultIfNull(value, value + 1));
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.Pair;
|
||||
import org.springframework.shell.support.util.PairList;
|
||||
|
||||
/**
|
||||
* Unit test of {@link PairList}
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class PairListTest {
|
||||
|
||||
// Constants
|
||||
private static final int KEY_1 = 10;
|
||||
private static final int KEY_2 = 20;
|
||||
private static final String VALUE_1 = "a";
|
||||
private static final String VALUE_2 = "b";
|
||||
private static final Pair<Integer, String> PAIR_1 = new Pair<Integer, String>(KEY_1, VALUE_1);
|
||||
private static final Pair<Integer, String> PAIR_2 = new Pair<Integer, String>(KEY_2, VALUE_2);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testConstructFromVarargArrayOfPairs() {
|
||||
// Invoke
|
||||
final PairList<Integer, String> pairs = new PairList<Integer, String>(PAIR_1, PAIR_2);
|
||||
|
||||
// Check
|
||||
assertEquals(2, pairs.size());
|
||||
assertEquals(Arrays.asList(KEY_1, KEY_2), pairs.getKeys());
|
||||
assertEquals(Arrays.asList(VALUE_1, VALUE_2), pairs.getValues());
|
||||
final Pair<Integer, String>[] array = pairs.toArray();
|
||||
assertEquals(pairs.size(), array.length);
|
||||
assertEquals(pairs, Arrays.asList(array));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructFromListsOfKeysAndValues() {
|
||||
// Invoke
|
||||
final PairList<Integer, String> pairs = new PairList<Integer, String>(Arrays.asList(KEY_1, KEY_2), Arrays.asList(VALUE_1, VALUE_2));
|
||||
|
||||
// Check
|
||||
assertEquals(2, pairs.size());
|
||||
assertEquals(PAIR_1, pairs.get(0));
|
||||
assertEquals(PAIR_2, pairs.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructFromNulListsOfKeysAndValues() {
|
||||
// Invoke
|
||||
final PairList<Integer, String> pairs = new PairList<Integer, String>(null, null);
|
||||
|
||||
// Check
|
||||
assertEquals(0, pairs.size());
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.Pair;
|
||||
|
||||
/**
|
||||
* Unit test of the {@link Pair} class.
|
||||
*
|
||||
* @author Andrew Swan
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class PairTest {
|
||||
|
||||
@Test
|
||||
public void testConstructWithNullKey() {
|
||||
new Pair<Object, Object>(null, "");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructWithNullValue() {
|
||||
new Pair<Object, Object>("", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstanceEqualsItself() {
|
||||
final Pair<Integer, String> pair = new Pair<Integer, String>(1, "a");
|
||||
assertEquals(pair, pair);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualKeyAndValueAreEqual() {
|
||||
assertEquals(new Pair<Integer, String>(1, "a"), new Pair<Integer, String>(1, "a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnequalKeyIsNotEqual() {
|
||||
assertFalse(new Pair<Integer, String>(1, "a").equals(new Pair<Integer, String>(2, "a")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnequalValueIsNotEqual() {
|
||||
assertFalse(new Pair<Integer, String>(1, "a").equals(new Pair<Integer, String>(1, "b")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOtherClassIsNotAPair() {
|
||||
assertFalse(new Pair<Integer, String>(1, "a").equals("foo"));
|
||||
}
|
||||
}
|
||||
@@ -1,533 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link StringUtils}.
|
||||
*
|
||||
* @author Alan Stewart
|
||||
* @since 1.1.3
|
||||
*/
|
||||
public class StringUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testPadRight1() {
|
||||
assertEquals("9999", StringUtils.padRight("9", 4, '9'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPadRight2() {
|
||||
assertEquals("Foo999", StringUtils.padRight("Foo", 6, '9'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPadLeft1() {
|
||||
assertEquals("999", StringUtils.padLeft("9", 3, '9'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPadLeft2() {
|
||||
assertEquals("99Foo", StringUtils.padLeft("Foo", 5, '9'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasText1() {
|
||||
assertTrue(StringUtils.hasText("11111"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasText2() {
|
||||
assertFalse(StringUtils.hasText(" "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountOccurrences() {
|
||||
assertEquals(4, StringUtils.countOccurrencesOf("Alan Keith Stewart - Triathlete", " "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountOccurrencesNull() {
|
||||
assertEquals(0, StringUtils.countOccurrencesOf("Alan Keith Stewart - Triathlete", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepeatNull() {
|
||||
assertNull(StringUtils.repeat(null, 27));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepeatEmptyString() {
|
||||
assertEquals("", StringUtils.repeat("", 42));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepeatSpace() {
|
||||
assertEquals(" ", StringUtils.repeat(" ", 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepeatSingleCharacter() {
|
||||
assertEquals("qqq", StringUtils.repeat("q", 3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRepeatMultipleCharacters() {
|
||||
assertEquals("xyzxyzxyzxyz", StringUtils.repeat("xyz", 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixNullWithNull() {
|
||||
assertNull(StringUtils.prefix(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixNullWithEmpty() {
|
||||
assertNull(StringUtils.prefix(null, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixNullWithNonEmpty() {
|
||||
assertNull(StringUtils.prefix(null, "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixEmptyWithNull() {
|
||||
assertEquals("", StringUtils.prefix("", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixEmptyWithEmpty() {
|
||||
assertEquals("", StringUtils.prefix("", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixEmptyWithNonEmpty() {
|
||||
assertEquals("x", StringUtils.prefix("", "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixNonEmptyWithNewPrefix() {
|
||||
assertEquals("pre-old", StringUtils.prefix("old", "pre-"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixNonEmptyWithExistingPrefix() {
|
||||
assertEquals("pre-old", StringUtils.prefix("pre-old", "pre-"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNullSuffixFromNullString() {
|
||||
assertNull(StringUtils.removeSuffix(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveEmptySuffixFromNullString() {
|
||||
assertNull(StringUtils.removeSuffix(null, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNonEmptySuffixFromNullString() {
|
||||
assertNull(StringUtils.removeSuffix(null, "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNullSuffixFromEmptyString() {
|
||||
assertEquals("", StringUtils.removeSuffix("", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveEmptySuffixFromEmptyString() {
|
||||
assertEquals("", StringUtils.removeSuffix("", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNonEmptySuffixFromEmptyString() {
|
||||
assertEquals("", StringUtils.removeSuffix("", "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveMatchingSuffixFromString() {
|
||||
assertEquals("a", StringUtils.removeSuffix("abc", "bc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNonMatchingSuffixFromString() {
|
||||
assertEquals("abc", StringUtils.removeSuffix("abc", "BC"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNullPrefixFromNullString() {
|
||||
assertNull(StringUtils.removePrefix(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveEmptyPrefixFromNullString() {
|
||||
assertNull(StringUtils.removePrefix(null, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNonEmptyPrefixFromNullString() {
|
||||
assertNull(StringUtils.removePrefix(null, "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNullPrefixFromEmptyString() {
|
||||
assertEquals("", StringUtils.removePrefix("", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveEmptyPrefixFromEmptyString() {
|
||||
assertEquals("", StringUtils.removePrefix("", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNonEmptyPrefixFromEmptyString() {
|
||||
assertEquals("", StringUtils.removePrefix("", "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveMatchingPrefixFromString() {
|
||||
assertEquals("c", StringUtils.removePrefix("abc", "ab"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveNonMatchingPrefixFromString() {
|
||||
assertEquals("abc", StringUtils.removePrefix("abc", "AB"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuffixNullWithNull() {
|
||||
assertNull(StringUtils.suffix(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuffixNullWithEmpty() {
|
||||
assertNull(StringUtils.suffix(null, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuffixNullWithNonEmpty() {
|
||||
assertNull(StringUtils.suffix(null, "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuffixEmptyWithNull() {
|
||||
assertEquals("", StringUtils.suffix("", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuffixEmptyWithEmpty() {
|
||||
assertEquals("", StringUtils.suffix("", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuffixEmptyWithNonEmpty() {
|
||||
assertEquals("x", StringUtils.suffix("", "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuffixNonEmptyWithNewSuffix() {
|
||||
assertEquals("old-suf", StringUtils.suffix("old", "-suf"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuffixNonEmptyWithExistingSuffix() {
|
||||
assertEquals("old-suf", StringUtils.suffix("old-suf", "-suf"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullEqualsNull() {
|
||||
assertTrue(StringUtils.equals(null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyDoesNotEqualNull() {
|
||||
assertFalse(StringUtils.equals("", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullDoesNotEqualEmpty() {
|
||||
assertFalse(StringUtils.equals(null, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpperDoesNotEqualLower() {
|
||||
assertFalse(StringUtils.equals("E", "e"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringEqualsItself() {
|
||||
assertTrue(StringUtils.equals("a", "a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullCollectionToDelimitedString() {
|
||||
assertEquals("", StringUtils.collectionToDelimitedString(null, "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyCollectionToDelimitedString() {
|
||||
assertEquals("", StringUtils.collectionToDelimitedString(Collections.emptySet(), "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingletonCollectionToDelimitedString() {
|
||||
assertEquals("foo", StringUtils.collectionToDelimitedString(Collections.singleton("foo"), "anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoubletonCollectionToDelimitedString() {
|
||||
assertEquals("foo:bar", StringUtils.collectionToDelimitedString(Arrays.asList("foo", "bar"), ":"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullIsBlank() {
|
||||
assertTrue(StringUtils.isBlank(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmptyStringIsBlank() {
|
||||
assertTrue(StringUtils.isBlank(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleSpaceStringIsBlank() {
|
||||
assertTrue(StringUtils.isBlank(" "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWhitespaceIsBlank() {
|
||||
assertTrue(StringUtils.isBlank("\n\r\t "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonBlankStringIsNotBlank() {
|
||||
assertFalse(StringUtils.isBlank("x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayToDelimitedStringWithNullArray() {
|
||||
assertEquals("", StringUtils.arrayToDelimitedString(";", new Object[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayToDelimitedStringWithEmptyArray() {
|
||||
assertEquals("", StringUtils.arrayToDelimitedString(";"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayToDelimitedStringWithSingleElementArray() {
|
||||
assertEquals("foo", StringUtils.arrayToDelimitedString(";", "foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayToDelimitedStringWithMultiElementArray() {
|
||||
assertEquals("foo;27", StringUtils.arrayToDelimitedString(";", "foo", 27));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfEmptyWhenValueIsNullAndNoDefaults() {
|
||||
assertNull(StringUtils.defaultIfEmpty(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfEmptyWhenValueIsEmptyAndNoDefaults() {
|
||||
assertEquals("", StringUtils.defaultIfEmpty(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfEmptyWhenValueIsNullAndOneDefault() {
|
||||
assertEquals("x", StringUtils.defaultIfEmpty(null, "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfEmptyWhenValueIsEmptyAndOneDefault() {
|
||||
assertEquals("x", StringUtils.defaultIfEmpty("", "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfEmptyWhenAllValuesAreBlank() {
|
||||
assertEquals("", StringUtils.defaultIfEmpty(null, null, null, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultIfEmptyWhenValueIsEmptyAndTwoDefaults() {
|
||||
assertEquals("x", StringUtils.defaultIfEmpty("", null, "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenNoArgumentsAreBlank() {
|
||||
// Deliberately chose characters with special meaning to regexs
|
||||
assertEquals("[a[b[c[", StringUtils.replace(".a.b.c.", ".", "["));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenReplacementIsNull() {
|
||||
assertEquals(" ", StringUtils.replace(" ", " ", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenReplacementIsEmpty() {
|
||||
assertEquals(" a ", StringUtils.replace(" a b ", "b", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenReplacementIsWhitespace() {
|
||||
assertEquals(" a ", StringUtils.replace(" a b ", "b", " "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenToReplaceIsNull() {
|
||||
assertEquals(" ", StringUtils.replace(" ", null, "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenToReplaceIsEmpty() {
|
||||
assertEquals(" ", StringUtils.replace(" ", "", "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenToReplaceIsWhiteSpace() {
|
||||
assertEquals("x", StringUtils.replace(" ", " ", "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenOriginalIsNull() {
|
||||
assertNull(StringUtils.replace(null, "x", "y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceAllWhenOriginalIsEmpty() {
|
||||
assertEquals("", StringUtils.replace("", "x", "y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenOriginalIsNull() {
|
||||
assertNull(StringUtils.replaceFirst(null, "x", "y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenOriginalIsEmpty() {
|
||||
assertEquals("", StringUtils.replaceFirst("", "x", "y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenOriginalIsWhitespace() {
|
||||
assertEquals("[ ", StringUtils.replaceFirst(" ", " ", "["));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenToReplaceIsNull() {
|
||||
assertEquals(" ", StringUtils.replaceFirst(" ", null, "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenToReplaceIsEmpty() {
|
||||
assertEquals(" ", StringUtils.replaceFirst(" ", "", "x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenToReplaceIsWhitespace() {
|
||||
assertEquals("x", StringUtils.replaceFirst("x", " ", "y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenReplacementIsNull() {
|
||||
assertEquals("x", StringUtils.replaceFirst("x", "x", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenReplacementIsEmpty() {
|
||||
assertEquals("x", StringUtils.replaceFirst("xx", "x", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenReplacementIsWhitespace() {
|
||||
assertEquals("x ", StringUtils.replaceFirst("x y", "y", " "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceFirstWhenNoArgumentsAreBlank() {
|
||||
assertEquals("x-yz", StringUtils.replaceFirst("xyyz", "y", "-"));
|
||||
}
|
||||
|
||||
private static final String[][] SUBSTRING_AFTER_LAST_SCENARIOS = {
|
||||
// 0 = original, 1 = separator, 2 = expected result
|
||||
{null, "anything", null},
|
||||
{"", "anything", ""},
|
||||
{"anything", "", ""},
|
||||
{"anything", null, ""},
|
||||
{"abc", "a", "bc"},
|
||||
{"abcba", "b", "a"},
|
||||
{"abc", "c", ""},
|
||||
{"a", "a", ""},
|
||||
{"a", "z", ""}
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testSubstringAfterLast() {
|
||||
for (final String[] scenario : SUBSTRING_AFTER_LAST_SCENARIOS) {
|
||||
assertEquals(scenario[2], StringUtils.substringAfterLast(scenario[0], scenario[1]));
|
||||
}
|
||||
}
|
||||
|
||||
private static final String[][] CONTAINS_SCENARIOS = {
|
||||
{null, "anything", "false"},
|
||||
{"anything", null, "false"},
|
||||
{"", "", "true"},
|
||||
{"abc", "", "true"},
|
||||
{"abc", "a", "true"},
|
||||
{"abc", "b", "true"},
|
||||
{"abc", "c", "true"},
|
||||
{"abc", "z", "false"}
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testContains() {
|
||||
for (final String[] scenario : CONTAINS_SCENARIOS) {
|
||||
assertEquals("Failed on scenario " + Arrays.toString(scenario), Boolean.valueOf(scenario[2]), StringUtils.contains(scenario[0], scenario[1]));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrimToEmpty() {
|
||||
String path = " ";
|
||||
assertEquals(" roo>", StringUtils.trimToEmpty(path) + " roo>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrimToEmpty2() {
|
||||
String path = null;
|
||||
assertEquals(" roo>", StringUtils.trimToEmpty(path) + " roo>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrimToEmpty3() {
|
||||
String path = "core";
|
||||
assertEquals("core roo>", StringUtils.trimToEmpty(path) + " roo>");
|
||||
}
|
||||
}
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.shell.support.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.shell.support.util.WebXmlUtils;
|
||||
import org.springframework.shell.support.util.XmlUtils;
|
||||
import org.springframework.shell.support.util.WebXmlUtils.WebXmlParam;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link WebXmlUtils}
|
||||
*
|
||||
* @author Stefan Schmidt
|
||||
* @since 1.1.1
|
||||
*/
|
||||
public class WebXmlUtilsTest {
|
||||
|
||||
private static Document webXml;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
final DocumentBuilder builder = XmlUtils.getDocumentBuilder();
|
||||
webXml = builder.newDocument();
|
||||
webXml.appendChild(webXml.createElement("web-app"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetDisplayName() {
|
||||
WebXmlUtils.setDisplayName("display", webXml, null);
|
||||
|
||||
final Element displayElement = XmlUtils.findFirstElement("display-name", webXml.getDocumentElement());
|
||||
assertNotNull(displayElement);
|
||||
assertEquals("display", displayElement.getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetDescription() {
|
||||
WebXmlUtils.setDescription("test desc", webXml, null);
|
||||
|
||||
final Element descriptionElement = XmlUtils.findFirstElement("description", webXml.getDocumentElement());
|
||||
assertNotNull(descriptionElement);
|
||||
assertEquals("test desc", descriptionElement.getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddContextParam() {
|
||||
WebXmlUtils.addContextParam(new WebXmlUtils.WebXmlParam("key", "value"), webXml, null);
|
||||
|
||||
final Element contextParamElement = XmlUtils.findFirstElement("context-param", webXml.getDocumentElement());
|
||||
assertNotNull(contextParamElement);
|
||||
assertEquals(2, contextParamElement.getChildNodes().getLength());
|
||||
assertEquals("key", XmlUtils.findFirstElement("param-name", contextParamElement).getTextContent());
|
||||
assertEquals("value", XmlUtils.findFirstElement("param-value", contextParamElement).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddFilter() {
|
||||
WebXmlUtils.addFilter("filter1", String.class.getName(), "/*", webXml, null, new WebXmlUtils.WebXmlParam("key", "value"), new WebXmlUtils.WebXmlParam("key2", "value2"));
|
||||
|
||||
final Element filterElement = XmlUtils.findFirstElement("filter", webXml.getDocumentElement());
|
||||
assertNotNull(filterElement);
|
||||
assertEquals("filter1", XmlUtils.findFirstElement("filter-name", filterElement).getTextContent());
|
||||
assertEquals(String.class.getName(), XmlUtils.findFirstElement("filter-class", filterElement).getTextContent());
|
||||
final Element filterMapping = XmlUtils.findFirstElement("filter-mapping", webXml.getDocumentElement());
|
||||
assertNotNull(filterMapping);
|
||||
assertEquals("filter1", XmlUtils.findFirstElement("filter-name", filterMapping).getTextContent());
|
||||
assertEquals("/*", XmlUtils.findFirstElement("url-pattern", filterMapping).getTextContent());
|
||||
final List<Element> initParams = XmlUtils.findElements("init-param", filterElement);
|
||||
assertEquals(2, initParams.size());
|
||||
assertEquals(2, initParams.get(0).getChildNodes().getLength());
|
||||
assertEquals("key", XmlUtils.findFirstElement("param-name", initParams.get(0)).getTextContent());
|
||||
assertEquals("value", XmlUtils.findFirstElement("param-value", initParams.get(0)).getTextContent());
|
||||
assertEquals("key2", XmlUtils.findFirstElement("param-name", initParams.get(1)).getTextContent());
|
||||
assertEquals("value2", XmlUtils.findFirstElement("param-value", initParams.get(1)).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddFilterAtPositionWithDispatcher() {
|
||||
WebXmlUtils.addFilterAtPosition(WebXmlUtils.FilterPosition.BEFORE, null, "filter1", "filter2", Object.class.getName(), "/test", webXml, null, null, Arrays.asList(WebXmlUtils.Dispatcher.ERROR, WebXmlUtils.Dispatcher.INCLUDE, WebXmlUtils.Dispatcher.FORWARD, WebXmlUtils.Dispatcher.REQUEST));
|
||||
|
||||
final Element filterElement = XmlUtils.findFirstElement("filter", webXml.getDocumentElement());
|
||||
assertNotNull(filterElement);
|
||||
assertEquals("filter2", XmlUtils.findFirstElement("filter-name", filterElement).getTextContent());
|
||||
assertEquals(Object.class.getName(), XmlUtils.findFirstElement("filter-class", filterElement).getTextContent());
|
||||
final Element filterMapping = XmlUtils.findFirstElement("filter-mapping", webXml.getDocumentElement());
|
||||
assertNotNull(filterMapping);
|
||||
assertEquals("filter2", XmlUtils.findFirstElement("filter-name", filterMapping).getTextContent());
|
||||
assertEquals("/test", XmlUtils.findFirstElement("url-pattern", filterMapping).getTextContent());
|
||||
final List<Element> dispatchers = XmlUtils.findElements("dispatcher", filterMapping);
|
||||
assertEquals(4, dispatchers.size());
|
||||
assertEquals(WebXmlUtils.Dispatcher.ERROR.name(), dispatchers.get(0).getTextContent());
|
||||
assertEquals(WebXmlUtils.Dispatcher.INCLUDE.name(), dispatchers.get(1).getTextContent());
|
||||
assertEquals(WebXmlUtils.Dispatcher.FORWARD.name(), dispatchers.get(2).getTextContent());
|
||||
assertEquals(WebXmlUtils.Dispatcher.REQUEST.name(), dispatchers.get(3).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddFilterAtPosition() {
|
||||
WebXmlUtils.addFilterAtPosition(WebXmlUtils.FilterPosition.BETWEEN, "filter2", "filter1", "filter3", Integer.class.getName(), "/test2", webXml, null, (WebXmlParam[]) null);
|
||||
|
||||
final List<Element> filterElements = XmlUtils.findElements("filter", webXml.getDocumentElement());
|
||||
assertEquals(3, filterElements.size());
|
||||
assertEquals("filter2", XmlUtils.findFirstElement("filter-name", filterElements.get(0)).getTextContent());
|
||||
assertEquals("filter3", XmlUtils.findFirstElement("filter-name", filterElements.get(1)).getTextContent());
|
||||
assertEquals("filter1", XmlUtils.findFirstElement("filter-name", filterElements.get(2)).getTextContent());
|
||||
assertEquals(Integer.class.getName(), XmlUtils.findFirstElement("filter-class", filterElements.get(1)).getTextContent());
|
||||
final List<Element> filterMappings = XmlUtils.findElements("filter-mapping", webXml.getDocumentElement());
|
||||
assertEquals(3, filterMappings.size());
|
||||
assertEquals("filter2", XmlUtils.findFirstElement("filter-name", filterMappings.get(0)).getTextContent());
|
||||
assertEquals("filter3", XmlUtils.findFirstElement("filter-name", filterMappings.get(1)).getTextContent());
|
||||
assertEquals("filter1", XmlUtils.findFirstElement("filter-name", filterMappings.get(2)).getTextContent());
|
||||
assertEquals("/test2", XmlUtils.findFirstElement("url-pattern", filterMappings.get(1)).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddListener() {
|
||||
WebXmlUtils.addListener(String.class.getName(), webXml, null);
|
||||
|
||||
final Element listenerElement = XmlUtils.findFirstElement("listener", webXml.getDocumentElement());
|
||||
assertNotNull(listenerElement);
|
||||
assertEquals(String.class.getName(), XmlUtils.findFirstElement("listener-class", listenerElement).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddServlet() {
|
||||
WebXmlUtils.addServlet("servlet1", Object.class.getName(), "/servlet1", 1, webXml, null, new WebXmlUtils.WebXmlParam("key1", "value1"), new WebXmlUtils.WebXmlParam("key2", "value2"));
|
||||
|
||||
final Element servletElement = XmlUtils.findFirstElement("servlet", webXml.getDocumentElement());
|
||||
assertNotNull(servletElement);
|
||||
assertEquals("servlet1", XmlUtils.findFirstElement("servlet-name", servletElement).getTextContent());
|
||||
assertEquals(Object.class.getName(), XmlUtils.findFirstElement("servlet-class", servletElement).getTextContent());
|
||||
final Element servletMapping = XmlUtils.findFirstElement("servlet-mapping", webXml.getDocumentElement());
|
||||
assertNotNull(servletMapping);
|
||||
assertEquals("servlet1", XmlUtils.findFirstElement("servlet-name", servletMapping).getTextContent());
|
||||
assertEquals("/servlet1", XmlUtils.findFirstElement("url-pattern", servletMapping).getTextContent());
|
||||
final List<Element> initParams = XmlUtils.findElements("init-param", servletElement);
|
||||
assertEquals(2, initParams.size());
|
||||
assertEquals(2, initParams.get(0).getChildNodes().getLength());
|
||||
assertEquals("key1", XmlUtils.findFirstElement("param-name", initParams.get(0)).getTextContent());
|
||||
assertEquals("value1", XmlUtils.findFirstElement("param-value", initParams.get(0)).getTextContent());
|
||||
assertEquals("key2", XmlUtils.findFirstElement("param-name", initParams.get(1)).getTextContent());
|
||||
assertEquals("value2", XmlUtils.findFirstElement("param-value", initParams.get(1)).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetSessionTimeout() {
|
||||
WebXmlUtils.setSessionTimeout(1000, webXml, null);
|
||||
|
||||
final Element timeElement = XmlUtils.findFirstElement("session-config/session-timeout", webXml.getDocumentElement());
|
||||
assertNotNull(timeElement);
|
||||
assertEquals("1000", timeElement.getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddWelcomeFile() {
|
||||
WebXmlUtils.addWelcomeFile("/welcome", webXml, null);
|
||||
|
||||
final Element welcomeFileElement = XmlUtils.findFirstElement("welcome-file-list/welcome-file", webXml.getDocumentElement());
|
||||
assertNotNull(welcomeFileElement);
|
||||
assertEquals("/welcome", welcomeFileElement.getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddExceptionType() {
|
||||
WebXmlUtils.addExceptionType(IllegalStateException.class.getName(), "/illegal", webXml, null);
|
||||
|
||||
final Element errorPageElement = XmlUtils.findFirstElement("error-page", webXml.getDocumentElement());
|
||||
assertNotNull(errorPageElement);
|
||||
assertEquals(2, errorPageElement.getChildNodes().getLength());
|
||||
assertEquals(IllegalStateException.class.getName(), XmlUtils.findFirstElement("exception-type", errorPageElement).getTextContent());
|
||||
assertEquals("/illegal", XmlUtils.findFirstElement("location", errorPageElement).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddErrorCode() {
|
||||
WebXmlUtils.addErrorCode(404, "/404", webXml, null);
|
||||
|
||||
final Element errorPageElement = (Element) webXml.getDocumentElement().getChildNodes().item(webXml.getDocumentElement().getChildNodes().getLength() - 1);
|
||||
assertNotNull(errorPageElement);
|
||||
assertEquals(2, errorPageElement.getChildNodes().getLength());
|
||||
assertEquals("404", XmlUtils.findFirstElement("error-code", errorPageElement).getTextContent());
|
||||
assertEquals("/404", XmlUtils.findFirstElement("location", errorPageElement).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddSecurityConstraint() {
|
||||
WebXmlUtils.addSecurityConstraint("displayName",
|
||||
Arrays.asList(new WebXmlUtils.WebResourceCollection("web-resource-name", "description", Arrays.asList("/", "/2"), Arrays.asList("POST", "GET"))),
|
||||
Arrays.asList("user", "supervisor"), "transportGuarantee", webXml, null);
|
||||
|
||||
final Element securityConstraintElement = XmlUtils.findFirstElement("security-constraint", webXml.getDocumentElement());
|
||||
assertNotNull(securityConstraintElement);
|
||||
assertEquals("displayName", XmlUtils.findFirstElement("display-name", securityConstraintElement).getTextContent());
|
||||
final Element webResourceCollection = XmlUtils.findFirstElement("web-resource-collection", securityConstraintElement);
|
||||
assertNotNull(webResourceCollection);
|
||||
assertEquals("web-resource-name", XmlUtils.findFirstElement("web-resource-name", webResourceCollection).getTextContent());
|
||||
assertEquals(2, XmlUtils.findElements("url-pattern", webResourceCollection).size());
|
||||
assertEquals(2, XmlUtils.findElements("http-method", webResourceCollection).size());
|
||||
final Element authConstraint = XmlUtils.findFirstElement("auth-constraint", securityConstraintElement);
|
||||
assertNotNull(authConstraint);
|
||||
assertEquals(2, authConstraint.getChildNodes().getLength());
|
||||
final Element userDataConstraint = XmlUtils.findFirstElement("user-data-constraint", securityConstraintElement);
|
||||
assertNotNull(userDataConstraint);
|
||||
assertEquals("transportGuarantee", userDataConstraint.getElementsByTagName("transport-guarantee").item(0).getTextContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateElementSequence() {
|
||||
final List<Element> contents = XmlUtils.findElements("/web-app/*", webXml.getDocumentElement());
|
||||
|
||||
assertEquals(17, contents.size());
|
||||
assertEquals("display-name", contents.get(0).getNodeName());
|
||||
assertEquals("description", contents.get(1).getNodeName());
|
||||
assertEquals("context-param", contents.get(2).getNodeName());
|
||||
assertEquals("filter2", contents.get(3).getChildNodes().item(0).getTextContent());
|
||||
assertEquals("filter3", contents.get(4).getChildNodes().item(0).getTextContent());
|
||||
assertEquals("filter1", contents.get(5).getChildNodes().item(0).getTextContent());
|
||||
assertEquals("filter2", contents.get(6).getChildNodes().item(0).getTextContent());
|
||||
assertEquals("filter3", contents.get(7).getChildNodes().item(0).getTextContent());
|
||||
assertEquals("filter1", contents.get(8).getChildNodes().item(0).getTextContent());
|
||||
assertEquals("listener", contents.get(9).getNodeName());
|
||||
assertEquals("servlet", contents.get(10).getNodeName());
|
||||
assertEquals("servlet-mapping", contents.get(11).getNodeName());
|
||||
assertEquals("session-config", contents.get(12).getNodeName());
|
||||
assertEquals("welcome-file-list", contents.get(13).getNodeName());
|
||||
assertEquals("error-page", contents.get(14).getNodeName());
|
||||
assertEquals("error-page", contents.get(15).getNodeName());
|
||||
assertEquals("security-constraint", contents.get(16).getNodeName());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user