Removed duplicate code from Spring and Roo

This commit is contained in:
Erwin Vervaet
2012-08-02 16:26:44 +02:00
committed by Mark Pollack
parent 7acc0db4de
commit 8620061363
60 changed files with 246 additions and 12261 deletions

View 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.
@@ -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";

View 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.
@@ -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}.

View 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);

View 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.
@@ -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) {

View 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.
@@ -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 {

View 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.
@@ -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}.

View 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.
@@ -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());
}

View 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.
@@ -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() {

View 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.
@@ -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

View 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.
@@ -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.

View 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.
@@ -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
*/

View 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.
@@ -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());

View 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.
@@ -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.

View 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.
@@ -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.

View 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.
@@ -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();
}

View 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.
@@ -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.

View 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.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));

View 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.
@@ -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}

View 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.
@@ -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.

View File

@@ -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(',');
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 &gt; 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 &gt; 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");
}
}

View File

@@ -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() {}
}

View File

@@ -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() {}
}

View 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.
@@ -15,6 +15,8 @@
*/
package org.springframework.shell.support.util;
import org.springframework.util.Assert;
/**
* Methods for working with exceptions.
*

View File

@@ -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() {}
}

View 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.
@@ -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() {

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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() {}
}

View File

@@ -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() {}
}

View 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.
@@ -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() {

View File

@@ -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();
}
}

View File

@@ -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()]);
}
}

View File

@@ -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);
}

View File

@@ -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()));
}
};
}

View File

@@ -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() {}
}

View File

@@ -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() {}
}

View File

@@ -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() {
}
}

View File

@@ -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;
}
}

View File

@@ -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() {}
}

View File

@@ -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>&lt;beans&gt;&lt;sec:http&gt;</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>&lt;beans&gt;&lt;sec:http&gt;</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() {}
}

View File

@@ -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)));
}
}

View File

@@ -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);
}
}

View 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.
@@ -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));

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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());
}
}

View File

@@ -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"));
}
}

View File

@@ -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>");
}
}

View File

@@ -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());
}
}