diff --git a/src/main/java/org/springframework/shell/commands/ResourceBundleHintOperations.java b/src/main/java/org/springframework/shell/commands/ResourceBundleHintOperations.java index eb5a187d..334fbf2b 100644 --- a/src/main/java/org/springframework/shell/commands/ResourceBundleHintOperations.java +++ b/src/main/java/org/springframework/shell/commands/ResourceBundleHintOperations.java @@ -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 getCurrentTopics() { @@ -56,7 +57,7 @@ public class ResourceBundleHintOperations implements HintOperations { } return result; } - + private String determineTopic() { return "start"; //return "general"; diff --git a/src/main/java/org/springframework/shell/converters/FileConverter.java b/src/main/java/org/springframework/shell/converters/FileConverter.java index 5d1e3a94..b2bcd578 100644 --- a/src/main/java/org/springframework/shell/converters/FileConverter.java +++ b/src/main/java/org/springframework/shell/converters/FileConverter.java @@ -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}. diff --git a/src/main/java/org/springframework/shell/converters/StaticFieldConverterImpl.java b/src/main/java/org/springframework/shell/converters/StaticFieldConverterImpl.java index 2e6e2a1d..78c110c0 100644 --- a/src/main/java/org/springframework/shell/converters/StaticFieldConverterImpl.java +++ b/src/main/java/org/springframework/shell/converters/StaticFieldConverterImpl.java @@ -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 ffields = fields.get(requiredType); diff --git a/src/main/java/org/springframework/shell/core/AbstractShell.java b/src/main/java/org/springframework/shell/core/AbstractShell.java index 451b7149..cb097159 100644 --- a/src/main/java/org/springframework/shell/core/AbstractShell.java +++ b/src/main/java/org/springframework/shell/core/AbstractShell.java @@ -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 null 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-null 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 result is * expected to be not null. If result is a * {@link java.lang.Iterable} object, it will be iterated through to print - * the output of toString. For other type of objects, simply output + * the output of toString. For other type of objects, simply output * of toString is shown. Subclasses can alter this implementation * to handle the result differently. - * + * * @param result not null result of execution of a command. */ protected void handleExecutionResult(Object result) { diff --git a/src/main/java/org/springframework/shell/core/Completion.java b/src/main/java/org/springframework/shell/core/Completion.java index 9d0496dd..d1c8fc4a 100644 --- a/src/main/java/org/springframework/shell/core/Completion.java +++ b/src/main/java/org/springframework/shell/core/Completion.java @@ -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 { diff --git a/src/main/java/org/springframework/shell/core/JLineCompletorAdapter.java b/src/main/java/org/springframework/shell/core/JLineCompletorAdapter.java index b47d039f..8cceea6b 100644 --- a/src/main/java/org/springframework/shell/core/JLineCompletorAdapter.java +++ b/src/main/java/org/springframework/shell/core/JLineCompletorAdapter.java @@ -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}. diff --git a/src/main/java/org/springframework/shell/core/JLineLogHandler.java b/src/main/java/org/springframework/shell/core/JLineLogHandler.java index b2727f69..25e84586 100644 --- a/src/main/java/org/springframework/shell/core/JLineLogHandler.java +++ b/src/main/java/org/springframework/shell/core/JLineLogHandler.java @@ -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()); } diff --git a/src/main/java/org/springframework/shell/core/JLineShell.java b/src/main/java/org/springframework/shell/core/JLineShell.java index 621bd84f..905189bd 100644 --- a/src/main/java/org/springframework/shell/core/JLineShell.java +++ b/src/main/java/org/springframework/shell/core/JLineShell.java @@ -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 entries = new ArrayList(); + ArrayList entries = new ArrayList(); 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 - * org.springframework.core.Ordered.getOder will win. - * - * @return history file name + * get history file name from provider. The provider has highest order + * org.springframework.core.Ordered.getOder will win. + * + * @return history file name */ abstract protected String getHistoryFileName(); /** - * get prompt text from provider. The provider has highest order - * org.springframework.core.Ordered.getOder will win. - * + * get prompt text from provider. The provider has highest order + * org.springframework.core.Ordered.getOder 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() { diff --git a/src/main/java/org/springframework/shell/core/MethodTarget.java b/src/main/java/org/springframework/shell/core/MethodTarget.java index 6c7738be..8767e9a4 100644 --- a/src/main/java/org/springframework/shell/core/MethodTarget.java +++ b/src/main/java/org/springframework/shell/core/MethodTarget.java @@ -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 null remainingBuffer and key * @@ -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 diff --git a/src/main/java/org/springframework/shell/core/ParserUtils.java b/src/main/java/org/springframework/shell/core/ParserUtils.java index 9f805a06..434f7939 100644 --- a/src/main/java/org/springframework/shell/core/ParserUtils.java +++ b/src/main/java/org/springframework/shell/core/ParserUtils.java @@ -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. diff --git a/src/main/java/org/springframework/shell/core/SimpleExecutionStrategy.java b/src/main/java/org/springframework/shell/core/SimpleExecutionStrategy.java index 7aed529b..35f0dd70 100644 --- a/src/main/java/org/springframework/shell/core/SimpleExecutionStrategy.java +++ b/src/main/java/org/springframework/shell/core/SimpleExecutionStrategy.java @@ -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 */ diff --git a/src/main/java/org/springframework/shell/core/SimpleParser.java b/src/main/java/org/springframework/shell/core/SimpleParser.java index 062a8b6d..af8229e2 100644 --- a/src/main/java/org/springframework/shell/core/SimpleParser.java +++ b/src/main/java/org/springframework/shell/core/SimpleParser.java @@ -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 sections = new TreeMap(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 builtSections = new ArrayList(); - - for (final Entry entry : sections.entrySet()) { - final String section = entry.getKey(); - final Object target = entry.getValue(); - SortedMap individualCommands = new TreeMap(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 optionKeys = new ArrayList(); - // key: option key, value: help text - Map optionDetails = new HashMap(); - 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()); diff --git a/src/main/java/org/springframework/shell/event/AbstractShellStatusPublisher.java b/src/main/java/org/springframework/shell/event/AbstractShellStatusPublisher.java index 56bb5b50..9773949f 100644 --- a/src/main/java/org/springframework/shell/event/AbstractShellStatusPublisher.java +++ b/src/main/java/org/springframework/shell/event/AbstractShellStatusPublisher.java @@ -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. diff --git a/src/main/java/org/springframework/shell/event/ParseResult.java b/src/main/java/org/springframework/shell/event/ParseResult.java index 47c056cd..bb186e4f 100644 --- a/src/main/java/org/springframework/shell/event/ParseResult.java +++ b/src/main/java/org/springframework/shell/event/ParseResult.java @@ -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. diff --git a/src/main/java/org/springframework/shell/plugin/support/DefaultBannerProvider.java b/src/main/java/org/springframework/shell/plugin/support/DefaultBannerProvider.java index ca3c469f..0b063d32 100644 --- a/src/main/java/org/springframework/shell/plugin/support/DefaultBannerProvider.java +++ b/src/main/java/org/springframework/shell/plugin/support/DefaultBannerProvider.java @@ -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(); } diff --git a/src/main/java/org/springframework/shell/support/logging/DeferredLogHandler.java b/src/main/java/org/springframework/shell/support/logging/DeferredLogHandler.java index 2d547c78..c77a120c 100644 --- a/src/main/java/org/springframework/shell/support/logging/DeferredLogHandler.java +++ b/src/main/java/org/springframework/shell/support/logging/DeferredLogHandler.java @@ -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. diff --git a/src/main/java/org/springframework/shell/support/logging/HandlerUtils.java b/src/main/java/org/springframework/shell/support/logging/HandlerUtils.java index a60f4846..103f9a9c 100644 --- a/src/main/java/org/springframework/shell/support/logging/HandlerUtils.java +++ b/src/main/java/org/springframework/shell/support/logging/HandlerUtils.java @@ -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)); diff --git a/src/main/java/org/springframework/shell/support/logging/LoggingOutputStream.java b/src/main/java/org/springframework/shell/support/logging/LoggingOutputStream.java index 4e4c3ed5..a303739d 100644 --- a/src/main/java/org/springframework/shell/support/logging/LoggingOutputStream.java +++ b/src/main/java/org/springframework/shell/support/logging/LoggingOutputStream.java @@ -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} diff --git a/src/main/java/org/springframework/shell/support/logging/MessageDisplayUtils.java b/src/main/java/org/springframework/shell/support/logging/MessageDisplayUtils.java index fc646083..37005927 100644 --- a/src/main/java/org/springframework/shell/support/logging/MessageDisplayUtils.java +++ b/src/main/java/org/springframework/shell/support/logging/MessageDisplayUtils.java @@ -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. diff --git a/src/main/java/org/springframework/shell/support/style/DefaultToStringStyler.java b/src/main/java/org/springframework/shell/support/style/DefaultToStringStyler.java deleted file mode 100644 index 171e9611..00000000 --- a/src/main/java/org/springframework/shell/support/style/DefaultToStringStyler.java +++ /dev/null @@ -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 toString() styler. - * - *

This class is used by {@link ToStringCreator} to style toString() - * 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(','); - } -} diff --git a/src/main/java/org/springframework/shell/support/style/DefaultValueStyler.java b/src/main/java/org/springframework/shell/support/style/DefaultValueStyler.java deleted file mode 100644 index fedd067d..00000000 --- a/src/main/java/org/springframework/shell/support/style/DefaultValueStyler.java +++ /dev/null @@ -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 toString styling conventions. - * - *

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(); - } -} diff --git a/src/main/java/org/springframework/shell/support/style/StylerUtils.java b/src/main/java/org/springframework/shell/support/style/StylerUtils.java deleted file mode 100644 index adf1dcac..00000000 --- a/src/main/java/org/springframework/shell/support/style/StylerUtils.java +++ /dev/null @@ -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. - * - *

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 style 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); - } -} diff --git a/src/main/java/org/springframework/shell/support/style/ToStringCreator.java b/src/main/java/org/springframework/shell/support/style/ToStringCreator.java deleted file mode 100644 index 19c42a7d..00000000 --- a/src/main/java/org/springframework/shell/support/style/ToStringCreator.java +++ /dev/null @@ -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 toString() methods - * with pluggable styling conventions. By default, ToStringCreator adheres - * to Spring's toString() 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 null - * @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(); - } -} diff --git a/src/main/java/org/springframework/shell/support/style/ToStringStyler.java b/src/main/java/org/springframework/shell/support/style/ToStringStyler.java deleted file mode 100644 index 703c7252..00000000 --- a/src/main/java/org/springframework/shell/support/style/ToStringStyler.java +++ /dev/null @@ -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 toString() 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 toString()'ed object before its fields are styled. - * - * @param buffer the buffer to print to - * @param obj the object to style; can be null - */ - void styleStart(StringBuilder buffer, Object obj); - - /** - * Style a toString()'ed object after it's fields are styled. - * - * @param buffer the buffer to print to - * @param obj the object to style; can be null - */ - 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 null - */ - 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 null - */ - void styleValue(StringBuilder buffer, Object value); - - /** - * Style the field separator. - * - * @param buffer buffer to print to - */ - void styleFieldSeparator(StringBuilder buffer); -} diff --git a/src/main/java/org/springframework/shell/support/style/ValueStyler.java b/src/main/java/org/springframework/shell/support/style/ValueStyler.java deleted file mode 100644 index 4e213ef5..00000000 --- a/src/main/java/org/springframework/shell/support/style/ValueStyler.java +++ /dev/null @@ -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); -} diff --git a/src/main/java/org/springframework/shell/support/util/AntPatchStringMatcher.java b/src/main/java/org/springframework/shell/support/util/AntPatchStringMatcher.java deleted file mode 100644 index c4060e02..00000000 --- a/src/main/java/org/springframework/shell/support/util/AntPatchStringMatcher.java +++ /dev/null @@ -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:
'*' means zero or more characters
'?' 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 uriTemplateVariables; - - /** Constructs a new instance of the AntPatchStringMatcher. */ - AntPatchStringMatcher(final String pattern, final String str, final Map 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 true if the string matches against the pattern, or false 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; - } -} diff --git a/src/main/java/org/springframework/shell/support/util/AntPathMatcher.java b/src/main/java/org/springframework/shell/support/util/AntPathMatcher.java deleted file mode 100644 index fb5b5f99..00000000 --- a/src/main/java/org/springframework/shell/support/util/AntPathMatcher.java +++ /dev/null @@ -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 path against the given pattern. - * @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 true if the supplied path matched, - * false if it didn't - */ - protected boolean doMatch(final String pattern, final String path, final boolean fullMatch, final Map 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:
- * '*' means zero or more characters
- * '?' means one and only one character - * @param pattern pattern to match against. - * Must not be null. - * @param str string which must be matched against the pattern. - * Must not be null. - * @return true if the string matches against the - * pattern, or false otherwise. - */ - private boolean matchStrings(final String pattern, final String str, final Map uriTemplateVariables) { - AntPatchStringMatcher matcher = new AntPatchStringMatcher(pattern, str, uriTemplateVariables); - return matcher.matchStrings(); - } - - /** - * Given a pattern and a full path, determine the pattern-mapped part. - *

For example: - *

    - *
  • '/docs/cvs/commit.html' and '/docs/cvs/commit.html -> ''
  • - *
  • '/docs/*' and '/docs/cvs/commit -> 'cvs/commit'
  • - *
  • '/docs/cvs/*.html' and '/docs/cvs/commit.html -> 'commit.html'
  • - *
  • '/docs/**' and '/docs/cvs/commit -> 'cvs/commit'
  • - *
  • '/docs/**\/*.html' and '/docs/cvs/commit.html -> 'cvs/commit.html'
  • - *
  • '/*.html' and '/docs/cvs/commit.html -> 'docs/cvs/commit.html'
  • - *
  • '*.html' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • - *
  • '*' and '/docs/cvs/commit.html -> '/docs/cvs/commit.html'
  • - *
- *

Assumes that {@link #match} returns true for 'pattern' - * and 'path', but does not 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 extractUriTemplateVariables(final String pattern, final String path) { - Map variables = new LinkedHashMap(); - boolean result = doMatch(pattern, path, true, variables); - Assert.state(result, "Pattern \"" + pattern + "\" is not a match for \"" + path + "\""); - return variables; - } -} diff --git a/src/main/java/org/springframework/shell/support/util/Assert.java b/src/main/java/org/springframework/shell/support/util/Assert.java deleted file mode 100644 index 96c08066..00000000 --- a/src/main/java/org/springframework/shell/support/util/Assert.java +++ /dev/null @@ -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. - * - *

For example, if the contract of a public method states it does not - * allow null 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. - * - *

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. - * - *

This class is similar to JUnit's assertion library. If an argument value is - * deemed invalid, an {@link IllegalArgumentException} is thrown (typically). - * For example: - * - *

- * Assert.notNull(clazz, "The class must not be null");
- * Assert.isTrue(i > 0, "The value must be greater than zero");
- * - * 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 IllegalArgumentException - * if the test result is false. - *
Assert.isTrue(i > 0, "The value must be greater than zero");
- * @param expression a boolean expression - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if expression is false - */ - public static void isTrue(final boolean expression, final String message) { - if (!expression) { - throw new IllegalArgumentException(message); - } - } - - /** - * Assert a boolean expression, throwing IllegalArgumentException - * if the test result is false. - *
Assert.isTrue(i > 0);
- * @param expression a boolean expression - * @throws IllegalArgumentException if expression is false - */ - public static void isTrue(final boolean expression) { - isTrue(expression, "[Assertion failed] - this expression must be true"); - } - - /** - * Assert that an object is null . - *
Assert.isNull(value, "The value must be null");
- * @param object the object to check - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if the object is not null - */ - public static void isNull(final Object object, final String message) { - if (object != null) { - throw new IllegalArgumentException(message); - } - } - - /** - * Assert that an object is null . - *
Assert.isNull(value);
- * @param object the object to check - * @throws IllegalArgumentException if the object is not null - */ - public static void isNull(final Object object) { - isNull(object, "[Assertion failed] - the object argument must be null"); - } - - /** - * Assert that an object is not null . - *
Assert.notNull(clazz, "The class must not be null");
- * @param object the object to check - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if the object is null - */ - public static void notNull(final Object object, final String message) { - if (object == null) { - throw new IllegalArgumentException(message); - } - } - - /** - * Assert that an object is not null . - *
Assert.notNull(clazz);
- * @param object the object to check - * @throws IllegalArgumentException if the object is null - */ - 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 null and not the empty String. - *
Assert.hasLength(name, "Name must not be empty");
- * @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 null and not the empty String. - *
Assert.hasLength(name);
- * @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 null and must contain at least one non-whitespace character. - *
Assert.hasText(name, "'name' must not be empty");
- * @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 null and must contain at least one non-whitespace character. - *
Assert.hasText(name, "'name' must not be empty");
- * @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. - *
Assert.doesNotContain(name, "rod", "Name must not contain 'rod'");
- * @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. - *
Assert.doesNotContain(name, "rod");
- * @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 - * null and must have at least one element. - *
Assert.notEmpty(array, "The array must have elements");
- * @param array the array to check - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if the object array is null 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 - * null and must have at least one element. - *
Assert.notEmpty(array);
- * @param array the array to check - * @throws IllegalArgumentException if the object array is null 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! - *
Assert.noNullElements(array, "The array must have non-null elements");
- * @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 null 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! - *
Assert.noNullElements(array);
- * @param array the array to check - * @throws IllegalArgumentException if the object array contains a null 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 - * null and must have at least one element. - *
Assert.notEmpty(collection, "Collection must have elements");
- * @param collection the collection to check - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if the collection is null 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 - * null and must have at least one element. - *
Assert.notEmpty(collection, "Collection must have elements");
- * @param collection the collection to check - * @throws IllegalArgumentException if the collection is null 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 null - * and must have at least one entry. - *
Assert.notEmpty(map, "Map must have entries");
- * @param map the map to check - * @param message the exception message to use if the assertion fails - * @throws IllegalArgumentException if the map is null 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 null - * and must have at least one entry. - *
Assert.notEmpty(map);
- * @param map the map to check - * @throws IllegalArgumentException if the map is null 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. - *
Assert.instanceOf(Foo.class, foo);
- * @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. - *
Assert.instanceOf(Foo.class, foo);
- * @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 superType.isAssignableFrom(subType) is true. - *
Assert.isAssignable(Number.class, myClass);
- * @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 superType.isAssignableFrom(subType) is true. - *
Assert.isAssignable(Number.class, myClass);
- * @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 IllegalStateException - * if the test result is false. Call isTrue if you wish to - * throw IllegalArgumentException on an assertion failure. - *
Assert.state(id == null, "The id property must not already be initialized");
- * @param expression a boolean expression - * @param message the exception message to use if the assertion fails - * @throws IllegalStateException if expression is false - */ - 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 false. - *

Call {@link #isTrue(boolean)} if you wish to - * throw {@link IllegalArgumentException} on an assertion failure. - *

Assert.state(id == null);
- * @param expression a boolean expression - * @throws IllegalStateException if the supplied expression is false - */ - public static void state(final boolean expression) { - state(expression, "[Assertion failed] - this state invariant must be true"); - } -} diff --git a/src/main/java/org/springframework/shell/support/util/Base64.java b/src/main/java/org/springframework/shell/support/util/Base64.java deleted file mode 100644 index 2dec12d4..00000000 --- a/src/main/java/org/springframework/shell/support/util/Base64.java +++ /dev/null @@ -1,1897 +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.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.UnsupportedEncodingException; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -/** - *

Encodes and decodes to and from Base64 notation.

- *

Homepage: http://iharder.net/base64.

- * - *

Example:

- * - * String encoded = Base64.encode(myByteArray); - *
- * byte[] myByteArray = Base64.decode(encoded); - * - *

The options parameter, which appears in a few places, is used to pass - * several pieces of information to the encoder. In the "higher level" methods such as - * encodeBytes(bytes, options) the options parameter can be used to indicate such - * things as first gzipping the bytes before encoding them, not inserting linefeeds, - * and encoding using the URL-safe and Ordered dialects.

- * - *

Note, according to RFC3548, - * Section 2.1, implementations should not add line feeds unless explicitly told - * to do so. I've got Base64 set to this behavior now, although earlier versions - * broke lines by default.

- * - *

The constants defined in Base64 can be OR-ed together to combine options, so you - * might make a call like this:

- * - * String encoded = Base64.encodeBytes(mybytes, Base64.GZIP | Base64.DO_BREAK_LINES); - *

to compress the data before encoding it and then making the output have newline characters.

- *

Also...

- * String encoded = Base64.encodeBytes(crazyString.getBytes()); - * - * - * - *

- * Change Log: - *

- *
    - *
  • v2.3.7 - Fixed subtle bug when base 64 input stream contained the - * value 01111111, which is an invalid base 64 character but should not - * throw an ArrayIndexOutOfBoundsException either. Led to discovery of - * mishandling (or potential for better handling) of other bad input - * characters. You should now get an IOException if you try decoding - * something that has bad characters in it.
  • - *
  • v2.3.6 - Fixed bug when breaking lines and the final byte of the encoded - * string ended in the last column; the buffer was not properly shrunk and - * contained an extra (null) byte that made it into the string.
  • - *
  • v2.3.5 - Fixed bug in {@link #encodeFromFile} where estimated buffer size - * was wrong for files of size 31, 34, and 37 bytes.
  • - *
  • v2.3.4 - Fixed bug when working with gzipped streams whereby flushing - * the Base64.OutputStream closed the Base64 encoding (by padding with equals - * signs) too soon. Also added an option to suppress the automatic decoding - * of gzipped streams. Also added experimental support for specifying a - * class loader when using the - * {@link #decodeToObject(java.lang.String, int, java.lang.ClassLoader)} - * method.
  • - *
  • v2.3.3 - Changed default char encoding to US-ASCII which reduces the internal Java - * footprint with its CharEncoders and so forth. Fixed some javadocs that were - * inconsistent. Removed imports and specified things like IOException - * explicitly inline.
  • - *
  • v2.3.2 - Reduced memory footprint! Finally refined the "guessing" of how big the - * final encoded data will be so that the code doesn't have to create two output - * arrays: an oversized initial one and then a final, exact-sized one. Big win - * when using the {@link #encodeBytesToBytes(byte[])} family of methods (and not - * using the gzip options which uses a different mechanism with streams and stuff).
  • - *
  • v2.3.1 - Added {@link #encodeBytesToBytes(byte[], int, int, int)} and some - * similar helper methods to be more efficient with memory by not returning a - * String but just a byte array.
  • - *
  • v2.3 - This is not a drop-in replacement! This is two years of comments - * and bug fixes queued up and finally executed. Thanks to everyone who sent - * me stuff, and I'm sorry I wasn't able to distribute your fixes to everyone else. - * Much bad coding was cleaned up including throwing exceptions where necessary - * instead of returning null values or something similar. Here are some changes - * that may affect you: - *
      - *
    • Does not break lines, by default. This is to keep in compliance with - * RFC3548.
    • - *
    • Throws exceptions instead of returning null values. Because some operations - * (especially those that may permit the GZIP option) use IO streams, there - * is a possiblity of an IOException being thrown. After some discussion and - * thought, I've changed the behavior of the methods to throw IOExceptions - * rather than return null if ever there's an error. I think this is more - * appropriate, though it will require some changes to your code. Sorry, - * it should have been done this way to begin with.
    • - *
    • Removed all references to System.out, System.err, and the like. - * Shame on me. All I can say is sorry they were ever there.
    • - *
    • Throws NullPointerExceptions and IllegalArgumentExceptions as needed - * such as when passed arrays are null or offsets are invalid.
    • - *
    • Cleaned up as much javadoc as I could to avoid any javadoc warnings. - * This was especially annoying before for people who were thorough in their - * own projects and then had gobs of javadoc warnings on this file.
    • - *
    - *
  • v2.2.1 - Fixed bug using URL_SAFE and ORDERED encodings. Fixed bug - * when using very small files (~< 40 bytes).
  • - *
  • v2.2 - Added some helper methods for encoding/decoding directly from - * one file to the next. Also added a main() method to support command line - * encoding/decoding from one file to the next. Also added these Base64 dialects: - *
      - *
    1. The default is RFC3548 format.
    2. - *
    3. Calling Base64.setFormat(Base64.BASE64_FORMAT.URLSAFE_FORMAT) generates - * URL and file name friendly format as described in Section 4 of RFC3548. - * http://www.faqs.org/rfcs/rfc3548.html
    4. - *
    5. Calling Base64.setFormat(Base64.BASE64_FORMAT.ORDERED_FORMAT) generates - * URL and file name friendly format that preserves lexical ordering as described - * in http://www.faqs.org/qa/rfcc-1940.html
    6. - *
    - * Special thanks to Jim Kellerman at http://www.powerset.com/ - * for contributing the new Base64 dialects. - *
  • - * - *
  • v2.1 - Cleaned up javadoc comments and unused variables and methods. Added - * some convenience methods for reading and writing to and from files.
  • - *
  • v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems - * with other encodings (like EBCDIC).
  • - *
  • v2.0.1 - Fixed an error when decoding a single byte, that is, when the - * encoded data was a single byte.
  • - *
  • v2.0 - I got rid of methods that used booleans to set options. - * Now everything is more consolidated and cleaner. The code now detects - * when data that's being decoded is gzip-compressed and will decompress it - * automatically. Generally things are cleaner. You'll probably have to - * change some method calls that you were making to support the new - * options format (ints that you "OR" together).
  • - *
  • v1.5.1 - Fixed bug when decompressing and decoding to a - * byte[] using decode(String s, boolean gzipCompressed). - * Added the ability to "suspend" encoding in the Output Stream so - * you can turn on and off the encoding if you need to embed base64 - * data in an otherwise "normal" stream (like an XML file).
  • - *
  • v1.5 - Output stream pases on flush() command but doesn't do anything itself. - * This helps when using GZIP streams. - * Added the ability to GZip-compress objects before encoding them.
  • - *
  • v1.4 - Added helper methods to read/write files.
  • - *
  • v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.
  • - *
  • v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream - * where last buffer being read, if not completely full, was not returned.
  • - *
  • v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.
  • - *
  • v1.3.3 - Fixed I/O streams which were totally messed up.
  • - *
- * - *

- * I am placing this code in the Public Domain. Do with it as you will. - * This software comes with no guarantees or warranties but with - * plenty of well-wishing instead! - * Please visit http://iharder.net/base64 - * periodically to check for updates or to contribute improvements. - *

- * - * @author Robert Harder - * @author rob@iharder.net - * @version 2.3.7 - */ -public class Base64 { - -/* ******** P U B L I C F I E L D S ******** */ - - /** No options specified. Value is zero. */ - public final static int NO_OPTIONS = 0; - - /** Specify encoding in first bit. Value is one. */ - public final static int ENCODE = 1; - - /** Specify decoding in first bit. Value is zero. */ - public final static int DECODE = 0; - - /** Specify that data should be gzip-compressed in second bit. Value is two. */ - public final static int GZIP = 2; - - /** Specify that gzipped data should not be automatically gunzipped. */ - public final static int DONT_GUNZIP = 4; - - /** Do break lines when encoding. Value is 8. */ - public final static int DO_BREAK_LINES = 8; - - /** - * Encode using Base64-like encoding that is URL- and Filename-safe as described - * in Section 4 of RFC3548: - * http://www.faqs.org/rfcs/rfc3548.html. - * It is important to note that data encoded this way is not officially valid Base64, - * or at the very least should not be called Base64 without also specifying that is - * was encoded using the URL- and Filename-safe dialect. - */ - public final static int URL_SAFE = 16; - - /** - * Encode using the special "ordered" dialect of Base64 described here: - * http://www.faqs.org/qa/rfcc-1940.html. - */ - public final static int ORDERED = 32; - -/* ******** P R I V A T E F I E L D S ******** */ - - /** Maximum line length (76) of Base64 output. */ - private final static int MAX_LINE_LENGTH = 76; - - /** The equals sign (=) as a byte. */ - private final static byte EQUALS_SIGN = (byte)'='; - - /** The new line character (\n) as a byte. */ - private final static byte NEW_LINE = (byte)'\n'; - - /** Preferred encoding. */ - private final static String PREFERRED_ENCODING = "US-ASCII"; - - private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding - private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding - -/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */ - - /** The 64 valid Base64 values. */ - /* Host platform me be something funny like EBCDIC, so we hardcode these values. */ - private final static byte[] _STANDARD_ALPHABET = { - (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', - (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', - (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', - (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', - (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', - (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', - (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' - }; - - - /** - * Translates a Base64 value to either its 6-bit reconstruction value - * or a negative number indicating some other meaning. - */ - private final static byte[] _STANDARD_DECODABET = { - -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 - -5,-5, // Whitespace: Tab and Linefeed - -9,-9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 - -9,-9,-9,-9,-9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 - 62, // Plus sign at decimal 43 - -9,-9,-9, // Decimal 44 - 46 - 63, // Slash at decimal 47 - 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine - -9,-9,-9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9,-9,-9, // Decimal 62 - 64 - 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' - 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' - -9,-9,-9,-9,-9,-9, // Decimal 91 - 96 - 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' - 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' - -9,-9,-9,-9,-9 // Decimal 123 - 127 - ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 - }; - - -/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */ - - /** - * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: - * http://www.faqs.org/rfcs/rfc3548.html. - * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash." - */ - private final static byte[] _URL_SAFE_ALPHABET = { - (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', - (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', - (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', - (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', - (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', - (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', - (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_' - }; - - /** - * Used in decoding URL- and Filename-safe dialects of Base64. - */ - private final static byte[] _URL_SAFE_DECODABET = { - -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 - -5,-5, // Whitespace: Tab and Linefeed - -9,-9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 - -9,-9,-9,-9,-9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 - -9, // Plus sign at decimal 43 - -9, // Decimal 44 - 62, // Minus sign at decimal 45 - -9, // Decimal 46 - -9, // Slash at decimal 47 - 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine - -9,-9,-9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9,-9,-9, // Decimal 62 - 64 - 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' - 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' - -9,-9,-9,-9, // Decimal 91 - 94 - 63, // Underscore at decimal 95 - -9, // Decimal 96 - 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' - 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' - -9,-9,-9,-9,-9 // Decimal 123 - 127 - ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 - }; - -/* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */ - - /** - * I don't get the point of this technique, but someone requested it, - * and it is described here: - * http://www.faqs.org/qa/rfcc-1940.html. - */ - private final static byte[] _ORDERED_ALPHABET = { - (byte)'-', - (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', - (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', - (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', - (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', - (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', - (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', - (byte)'_', - (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', - (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', - (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', - (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z' - }; - - /** - * Used in decoding the "ordered" dialect of Base64. - */ - private final static byte[] _ORDERED_DECODABET = { - -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 - -5,-5, // Whitespace: Tab and Linefeed - -9,-9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 - -9,-9,-9,-9,-9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 - -9, // Plus sign at decimal 43 - -9, // Decimal 44 - 0, // Minus sign at decimal 45 - -9, // Decimal 46 - -9, // Slash at decimal 47 - 1,2,3,4,5,6,7,8,9,10, // Numbers zero through nine - -9,-9,-9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9,-9,-9, // Decimal 62 - 64 - 11,12,13,14,15,16,17,18,19,20,21,22,23, // Letters 'A' through 'M' - 24,25,26,27,28,29,30,31,32,33,34,35,36, // Letters 'N' through 'Z' - -9,-9,-9,-9, // Decimal 91 - 94 - 37, // Underscore at decimal 95 - -9, // Decimal 96 - 38,39,40,41,42,43,44,45,46,47,48,49,50, // Letters 'a' through 'm' - 51,52,53,54,55,56,57,58,59,60,61,62,63, // Letters 'n' through 'z' - -9,-9,-9,-9,-9 // Decimal 123 - 127 - ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 - -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 - }; - - - /* ******** D E T E R M I N E W H I C H A L P H A B E T ******** */ - - /** - * Returns one of the _SOMETHING_ALPHABET byte arrays depending on - * the options specified. - * It's possible, though silly, to specify ORDERED and URLSAFE - * in which case one of them will be picked, though there is - * no guarantee as to which one will be picked. - */ - private final static byte[] getAlphabet(final int options) { - if ((options & URL_SAFE) == URL_SAFE) { - return _URL_SAFE_ALPHABET; - } else if ((options & ORDERED) == ORDERED) { - return _ORDERED_ALPHABET; - } else { - return _STANDARD_ALPHABET; - } - } - - /** - * Returns one of the _SOMETHING_DECODABET byte arrays depending on - * the options specified. - * It's possible, though silly, to specify ORDERED and URL_SAFE - * in which case one of them will be picked, though there is - * no guarantee as to which one will be picked. - */ - private final static byte[] getDecodabet(final int options) { - if ((options & URL_SAFE) == URL_SAFE) { - return _URL_SAFE_DECODABET; - } else if ((options & ORDERED) == ORDERED) { - return _ORDERED_DECODABET; - } else { - return _STANDARD_DECODABET; - } - } - - /* ******** E N C O D I N G M E T H O D S ******** */ - - /** - * Encodes up to the first three bytes of array threeBytes - * and returns a four-byte array in Base64 notation. - * The actual number of significant bytes in your array is - * given by numSigBytes. - * The array threeBytes needs only be as big as - * numSigBytes. - * Code can reuse a byte array by passing a four-byte array as b4. - * - * @param b4 A reusable byte array to reduce array instantiation - * @param threeBytes the array to convert - * @param numSigBytes the number of significant bytes in your array - * @return four byte array in Base64 notation. - * @since 1.5.1 - */ - private static byte[] encode3to4(final byte[] b4, final byte[] threeBytes, final int numSigBytes, final int options) { - encode3to4(threeBytes, 0, numSigBytes, b4, 0, options); - return b4; - } - - /** - *

Encodes up to three bytes of the array source - * and writes the resulting four Base64 bytes to destination. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * srcOffset and destOffset. - * This method does not check to make sure your arrays - * are large enough to accomodate srcOffset + 3 for - * the source array or destOffset + 4 for - * the destination array. - * The actual number of significant bytes in your array is - * given by numSigBytes.

- *

This is the lowest level of the encoding methods with - * all possible parameters.

- * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param numSigBytes the number of significant bytes in your array - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @return the destination array - * @since 1.3 - */ - private static byte[] encode3to4(final byte[] source, final int srcOffset, final int numSigBytes, final byte[] destination, final int destOffset, final int options) { - - byte[] ALPHABET = getAlphabet(options); - - // 1 2 3 - // 01234567890123456789012345678901 Bit position - // --------000000001111111122222222 Array position from threeBytes - // --------| || || || | Six bit groups to index ALPHABET - // >>18 >>12 >> 6 >> 0 Right shift necessary - // 0x3f 0x3f 0x3f Additional AND - - // Create buffer with zero-padding if there are only one or two - // significant bytes passed in the array. - // We have to shift left 24 in order to flush out the 1's that appear - // when Java treats a value as negative that is cast from a byte to an int. - int inBuff = (numSigBytes > 0 ? ((source[srcOffset ] << 24) >>> 8) : 0) - | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) - | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); - - switch(numSigBytes) { - case 3: - destination[destOffset ] = ALPHABET[(inBuff >>> 18) ]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = ALPHABET[(inBuff ) & 0x3f]; - return destination; - - case 2: - destination[destOffset ] = ALPHABET[(inBuff >>> 18) ]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - - case 1: - destination[destOffset ] = ALPHABET[(inBuff >>> 18) ]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = EQUALS_SIGN; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - - default: - return destination; - } // end switch - } // end encode3to4 - - /** - * Performs Base64 encoding on the raw ByteBuffer, - * writing it to the encoded ByteBuffer. - * This is an experimental feature. Currently it does not - * pass along any options (such as {@link #DO_BREAK_LINES} - * or {@link #GZIP}. - * - * @param raw input buffer - * @param encoded output buffer - * @since 2.3 - */ - public static void encode(final java.nio.ByteBuffer raw, final java.nio.ByteBuffer encoded) { - byte[] raw3 = new byte[3]; - byte[] enc4 = new byte[4]; - - while(raw.hasRemaining()) { - int rem = Math.min(3,raw.remaining()); - raw.get(raw3,0,rem); - Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS); - encoded.put(enc4); - } // end input remaining - } - - /** - * Performs Base64 encoding on the raw ByteBuffer, - * writing it to the encoded CharBuffer. - * This is an experimental feature. Currently it does not - * pass along any options (such as {@link #DO_BREAK_LINES} - * or {@link #GZIP}. - * - * @param raw input buffer - * @param encoded output buffer - * @since 2.3 - */ - public static void encode(final java.nio.ByteBuffer raw, final java.nio.CharBuffer encoded) { - byte[] raw3 = new byte[3]; - byte[] enc4 = new byte[4]; - - while(raw.hasRemaining()) { - int rem = Math.min(3,raw.remaining()); - raw.get(raw3,0,rem); - Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS); - for (int i = 0; i < 4; i++) { - encoded.put((char)(enc4[i] & 0xFF)); - } - } // end input remaining - } - - /** - * Serializes an object and returns the Base64-encoded - * version of that serialized object. - * - *

As of v 2.3, if the object - * cannot be serialized or there is another error, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- * - * The object is not GZip-compressed before being encoded. - * - * @param serializableObject The object to encode - * @return The Base64-encoded object - * @throws IOException if there is an error - * @throws NullPointerException if serializedObject is null - * @since 1.4 - */ - public static String encodeObject(final java.io.Serializable serializableObject) throws IOException { - return encodeObject(serializableObject, NO_OPTIONS); - } - - /** - * Serializes an object and returns the Base64-encoded - * version of that serialized object. - * - *

As of v 2.3, if the object - * cannot be serialized or there is another error, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- * - * The object is not GZip-compressed before being encoded. - *

- * Example options:

-     *   GZIP: gzip-compresses object before encoding it.
-     *   DO_BREAK_LINES: break lines at 76 characters
-     * 
- *

- * Example: encodeObject(myObj, Base64.GZIP) or - *

- * Example: encodeObject(myObj, Base64.GZIP | Base64.DO_BREAK_LINES) - * - * @param serializableObject The object to encode - * @param options Specified options - * @return The Base64-encoded object - * @see Base64#GZIP - * @see Base64#DO_BREAK_LINES - * @throws IOException if there is an error - * @since 2.0 - */ - public static String encodeObject(final java.io.Serializable serializableObject, final int options) throws IOException { - if (serializableObject == null) { - throw new NullPointerException("Cannot serialize a null object."); - } - - // Streams - ByteArrayOutputStream baos = null; - java.io.OutputStream b64os = null; - GZIPOutputStream gzos = null; - ObjectOutputStream oos = null; - - try { - // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream - baos = new ByteArrayOutputStream(); - b64os = new Base64.OutputStream(baos, ENCODE | options); - if ((options & GZIP) != 0) { - // Gzip - gzos = new GZIPOutputStream(b64os); - oos = new ObjectOutputStream(gzos); - } else { - // Not gzipped - oos = new ObjectOutputStream(b64os); - } - oos.writeObject(serializableObject); - } catch (IOException e) { - // Catch it and then throw it immediately so that - // the finally{} block is called for cleanup. - throw e; - } finally { - IOUtils.closeQuietly(oos, gzos, b64os, baos); - } - - // Return value according to relevant encoding. - try { - return new String(baos.toByteArray(), PREFERRED_ENCODING); - } catch (UnsupportedEncodingException uue) { - // Fall back to some Java default - return new String(baos.toByteArray()); - } // end catch - } // end encode - - /** - * Encodes a byte array into Base64 notation. - * Does not GZip-compress data. - * - * @param source The data to convert - * @return The data in Base64-encoded form - * @throws NullPointerException if source array is null - * @since 1.4 - */ - public static String encodeBytes(final byte[] source) { - // Since we're not going to have the GZIP encoding turned on, - // we're not going to have an IOException thrown, so - // we should not force the user to have to catch it. - String encoded = null; - try { - encoded = encodeBytes(source, 0, source.length, NO_OPTIONS); - } catch (IOException ex) { - assert false : ex.getMessage(); - } // end catch - assert encoded != null; - return encoded; - } - - /** - * Encodes a byte array into Base64 notation. - *

- * Example options:

-     *   GZIP: gzip-compresses object before encoding it.
-     *   DO_BREAK_LINES: break lines at 76 characters
-     *     Note: Technically, this makes your encoding non-compliant.
-     * 
- *

- * Example: encodeBytes(myData, Base64.GZIP) or - *

- * Example: encodeBytes(myData, Base64.GZIP | Base64.DO_BREAK_LINES) - * - *

As of v 2.3, if there is an error with the GZIP stream, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param source The data to convert - * @param options Specified options - * @return The Base64-encoded data as a String - * @see Base64#GZIP - * @see Base64#DO_BREAK_LINES - * @throws IOException if there is an error - * @throws NullPointerException if source array is null - * @since 2.0 - */ - public static String encodeBytes(final byte[] source, final int options) throws IOException { - return encodeBytes(source, 0, source.length, options); - } - - /** - * Encodes a byte array into Base64 notation. - * Does not GZip-compress data. - * - *

As of v 2.3, if there is an error, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param source The data to convert - * @param off Offset in array where conversion should begin - * @param len Length of data to convert - * @return The Base64-encoded data as a String - * @throws NullPointerException if source array is null - * @throws IllegalArgumentException if source array, offset, or length are invalid - * @since 1.4 - */ - public static String encodeBytes(final byte[] source, final int off, final int len) { - // Since we're not going to have the GZIP encoding turned on, - // we're not going to have an IOException thrown, so - // we should not force the user to have to catch it. - String encoded = null; - try { - encoded = encodeBytes(source, off, len, NO_OPTIONS); - } catch (IOException ex) { - assert false : ex.getMessage(); - } // end catch - assert encoded != null; - return encoded; - } - - /** - * Encodes a byte array into Base64 notation. - *

- * Example options:

-     *   GZIP: gzip-compresses object before encoding it.
-     *   DO_BREAK_LINES: break lines at 76 characters
-     *     Note: Technically, this makes your encoding non-compliant.
-     * 
- *

- * Example: encodeBytes(myData, Base64.GZIP) or - *

- * Example: encodeBytes(myData, Base64.GZIP | Base64.DO_BREAK_LINES) - * - *

As of v 2.3, if there is an error with the GZIP stream, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param source The data to convert - * @param off Offset in array where conversion should begin - * @param len Length of data to convert - * @param options Specified options - * @return The Base64-encoded data as a String - * @see Base64#GZIP - * @see Base64#DO_BREAK_LINES - * @throws IOException if there is an error - * @throws NullPointerException if source array is null - * @throws IllegalArgumentException if source array, offset, or length are invalid - * @since 2.0 - */ - public static String encodeBytes(final byte[] source, final int off, final int len, final int options) throws IOException { - byte[] encoded = encodeBytesToBytes(source, off, len, options); - - // Return value according to relevant encoding. - try { - return new String(encoded, PREFERRED_ENCODING); - } catch (UnsupportedEncodingException uue) { - return new String(encoded); - } - } - - /** - * Similar to {@link #encodeBytes(byte[])} but returns - * a byte array instead of instantiating a String. This is more efficient - * if you're working with I/O streams and have large data sets to encode. - * - * @param source The data to convert - * @return The Base64-encoded data as a byte[] (of ASCII characters) - * @throws NullPointerException if source array is null - * @since 2.3.1 - */ - public static byte[] encodeBytesToBytes(final byte[] source) { - byte[] encoded = null; - try { - encoded = encodeBytesToBytes(source, 0, source.length, Base64.NO_OPTIONS); - } catch (IOException ex) { - assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage(); - } - return encoded; - } - - /** - * Similar to {@link #encodeBytes(byte[], int, int, int)} but returns - * a byte array instead of instantiating a String. This is more efficient - * if you're working with I/O streams and have large data sets to encode. - * - * @param source The data to convert - * @param off Offset in array where conversion should begin - * @param len Length of data to convert - * @param options Specified options - * @return The Base64-encoded data as a String - * @see Base64#GZIP - * @see Base64#DO_BREAK_LINES - * @throws IOException if there is an error - * @throws NullPointerException if source array is null - * @throws IllegalArgumentException if source array, offset, or length are invalid - * @since 2.3.1 - */ - public static byte[] encodeBytesToBytes(final byte[] source, final int off, final int len, final int options) throws IOException { - if (source == null) { - throw new NullPointerException("Cannot serialize a null array."); - } - - if (off < 0) { - throw new IllegalArgumentException("Cannot have negative offset: " + off); - } - - if (len < 0) { - throw new IllegalArgumentException("Cannot have length offset: " + len); - } - - if (off + len > source.length ) { - throw new IllegalArgumentException(String.format("Cannot have offset of %d and length of %d with array of length %d", off,len,source.length)); - } - - if ((options & GZIP) != 0) { - // Compress - ByteArrayOutputStream baos = null; - GZIPOutputStream gzos = null; - Base64.OutputStream b64os = null; - - try { - // GZip -> Base64 -> ByteArray - baos = new ByteArrayOutputStream(); - b64os = new Base64.OutputStream(baos, ENCODE | options); - gzos = new GZIPOutputStream(b64os); - - gzos.write(source, off, len); - } catch (IOException e) { - throw e; - } finally { - IOUtils.closeQuietly(gzos, b64os, baos); - } - - return baos.toByteArray(); - } else { - // Don't compress. Better not to use streams at all then. - boolean breakLines = (options & DO_BREAK_LINES) != 0; - - //int len43 = len * 4 / 3; - //byte[] outBuff = new byte[ (len43) // Main 4:3 - // + ((len % 3) > 0 ? 4 : 0) // Account for padding - // + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)]; // New lines - // Try to determine more precisely how big the array needs to be. - // If we get it right, we don't have to do an array copy, and - // we save a bunch of memory. - int encLen = (len / 3) * 4 + (len % 3 > 0 ? 4 : 0); // Bytes needed for actual encoding - if (breakLines) { - encLen += encLen / MAX_LINE_LENGTH; // Plus extra newline characters - } - byte[] outBuff = new byte[encLen]; - - int d = 0; - int e = 0; - int len2 = len - 2; - int lineLength = 0; - for (; d < len2; d+=3, e+=4) { - encode3to4(source, d+off, 3, outBuff, e, options); - - lineLength += 4; - if (breakLines && lineLength >= MAX_LINE_LENGTH) - { - outBuff[e+4] = NEW_LINE; - e++; - lineLength = 0; - } // end if: end of line - } // en dfor: each piece of array - - if (d < len) { - encode3to4(source, d+off, len - d, outBuff, e, options); - e += 4; - } // end if: some padding needed - - // Only resize array if we didn't guess it right. - if (e <= outBuff.length - 1) { - // If breaking lines and the last byte falls right at - // the line length (76 bytes per line), there will be - // one extra byte, and the array will need to be resized. - // Not too bad of an estimate on array size, I'd say. - byte[] finalOut = new byte[e]; - System.arraycopy(outBuff,0, finalOut,0,e); - // System.err.println("Having to resize array from " + outBuff.length + " to " + e); - return finalOut; - } else { - // System.err.println("No need to resize array."); - return outBuff; - } - } // end else: don't compress - } // end encodeBytesToBytes - -/* ******** D E C O D I N G M E T H O D S ******** */ - - /** - * Decodes four bytes from array source - * and writes the resulting bytes (up to three of them) - * to destination. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * srcOffset and destOffset. - * This method does not check to make sure your arrays - * are large enough to accomodate srcOffset + 4 for - * the source array or destOffset + 3 for - * the destination array. - * This method returns the actual number of bytes that - * were converted from the Base64 encoding. - *

This is the lowest level of the decoding methods with - * all possible parameters.

- * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @param options alphabet type is pulled from this (standard, url-safe, ordered) - * @return the number of decoded bytes converted - * @throws NullPointerException if source or destination arrays are null - * @throws IllegalArgumentException if srcOffset or destOffset are invalid - * or there is not enough room in the array. - * @since 1.3 - */ - private static int decode4to3(final byte[] source, final int srcOffset, final byte[] destination, final int destOffset, final int options) { - if (source == null) { - throw new NullPointerException("Source array was null."); - } - if (destination == null) { - throw new NullPointerException("Destination array was null."); - } - if (srcOffset < 0 || srcOffset + 3 >= source.length) { - throw new IllegalArgumentException(String.format( - "Source array with length %d cannot have offset of %d and still process four bytes.", source.length, srcOffset)); - } - if (destOffset < 0 || destOffset +2 >= destination.length) { - throw new IllegalArgumentException(String.format( - "Destination array with length %d cannot have offset of %d and still store three bytes.", destination.length, destOffset)); - } - - byte[] DECODABET = getDecodabet(options); - - // Example: Dk== - if (source[srcOffset + 2] == EQUALS_SIGN) { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ((DECODABET[source[srcOffset ]] << 24) >>> 6) - // | ((DECODABET[source[srcOffset + 1]] << 24) >>> 12); - int outBuff = ((DECODABET[source[srcOffset ]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12); - - destination[destOffset] = (byte)(outBuff >>> 16); - return 1; - } - - // Example: DkL= - else if (source[srcOffset + 3] == EQUALS_SIGN) { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ((DECODABET[source[srcOffset ]] << 24) >>> 6) - // | ((DECODABET[source[srcOffset + 1]] << 24) >>> 12) - // | ((DECODABET[source[srcOffset + 2]] << 24) >>> 18); - int outBuff = ((DECODABET[source[srcOffset ]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6); - - destination[destOffset ] = (byte)(outBuff >>> 16); - destination[destOffset + 1] = (byte)(outBuff >>> 8); - return 2; - } - - // Example: DkLE - else { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ((DECODABET[source[srcOffset ]] << 24) >>> 6) - // | ((DECODABET[source[srcOffset + 1]] << 24) >>> 12) - // | ((DECODABET[source[srcOffset + 2]] << 24) >>> 18) - // | ((DECODABET[source[srcOffset + 3]] << 24) >>> 24); - int outBuff = ((DECODABET[source[srcOffset ]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) - | ((DECODABET[source[srcOffset + 3]] & 0xFF) ); - - - destination[destOffset ] = (byte)(outBuff >> 16); - destination[destOffset + 1] = (byte)(outBuff >> 8); - destination[destOffset + 2] = (byte)(outBuff ); - - return 3; - } - } // end decodeToBytes - - /** - * Low-level access to decoding ASCII characters in - * the form of a byte array. Ignores GUNZIP option, if - * it's set. This is not generally a recommended method, - * although it is used internally as part of the decoding process. - * Special case: if len = 0, an empty array is returned. Still, - * if you need more speed and reduced memory footprint (and aren't - * gzipping), consider this method. - * - * @param source The Base64 encoded data - * @return decoded data - * @since 2.3.1 - */ - public static byte[] decode(final byte[] source) throws IOException { - return decode(source, 0, source.length, Base64.NO_OPTIONS); - } - - /** - * Low-level access to decoding ASCII characters in - * the form of a byte array. Ignores GUNZIP option, if - * it's set. This is not generally a recommended method, - * although it is used internally as part of the decoding process. - * Special case: if len = 0, an empty array is returned. Still, - * if you need more speed and reduced memory footprint (and aren't - * gzipping), consider this method. - * - * @param source The Base64 encoded data - * @param off The offset of where to begin decoding - * @param len The length of characters to decode - * @param options Can specify options such as alphabet type to use - * @return decoded data - * @throws IOException If bogus characters exist in source data - * @since 1.3 - */ - public static byte[] decode(final byte[] source, final int off, final int len, final int options) throws IOException { - // Lots of error checking and exception throwing - if (source == null) { - throw new NullPointerException("Cannot decode null source array."); - } - if (off < 0 || off + len > source.length) { - throw new IllegalArgumentException(String.format("Source array with length %d cannot have offset of %d and process %d bytes.", source.length, off, len)); - } - - if (len == 0) { - return new byte[0]; - } else if (len < 4) { - throw new IllegalArgumentException( - "Base64-encoded string must have at least four characters, but length specified was " + len); - } // end if - - byte[] DECODABET = getDecodabet(options); - - int len34 = len * 3 / 4; // Estimate on array size - byte[] outBuff = new byte[len34]; // Upper limit on size of output - int outBuffPosn = 0; // Keep track of where we're writing - - byte[] b4 = new byte[4]; // Four byte buffer from source, eliminating white space - int b4Posn = 0; // Keep track of four byte input buffer - int i = 0; // Source array counter - byte sbiDecode = 0; // Special value from DECODABET - - for (i = off; i < off+len; i++) { // Loop through source - - sbiDecode = DECODABET[source[i]&0xFF]; - - // White space, Equals sign, or legit Base64 character - // Note the values such as -5 and -9 in the - // DECODABETs at the top of the file. - if (sbiDecode >= WHITE_SPACE_ENC) { - if (sbiDecode >= EQUALS_SIGN_ENC) { - b4[b4Posn++] = source[i]; // Save non-whitespace - if (b4Posn > 3) { // Time to decode? - outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, options); - b4Posn = 0; - - // If that was the equals sign, break out of 'for' loop - if (source[i] == EQUALS_SIGN) { - break; - } // end if: equals sign - } // end if: quartet built - } // end if: equals sign or better - } // end if: white space, equals sign or better - else { - // There's a bad input character in the Base64 stream. - throw new IOException(String.format( - "Bad Base64 input character decimal %d in array position %d", source[i] & 0xFF, i)); - } // end else: - } // each input character - - byte[] out = new byte[outBuffPosn]; - System.arraycopy(outBuff, 0, out, 0, outBuffPosn); - return out; - } // end decode - - /** - * Decodes data from Base64 notation, automatically - * detecting gzip-compressed data and decompressing it. - * - * @param s the string to decode - * @return the decoded data - * @throws IOException If there is a problem - * @since 1.4 - */ - public static byte[] decode(final String s) throws IOException { - return decode(s, NO_OPTIONS); - } - - /** - * Decodes data from Base64 notation, automatically - * detecting gzip-compressed data and decompressing it. - * - * @param s the string to decode - * @param options encode options such as URL_SAFE - * @return the decoded data - * @throws IOException if there is an error - * @throws NullPointerException if s is null - * @since 1.4 - */ - public static byte[] decode(final String s, final int options) throws IOException { - if (s == null) { - throw new NullPointerException("Input string was null."); - } // end if - - byte[] bytes; - try { - bytes = s.getBytes(PREFERRED_ENCODING); - } // end try - catch (UnsupportedEncodingException uee) { - bytes = s.getBytes(); - } // end catch - // - - // Decode - bytes = decode(bytes, 0, bytes.length, options); - - // Check to see if it's gzip-compressed - // GZIP Magic Two-Byte Number: 0x8b1f (35615) - boolean dontGunzip = (options & DONT_GUNZIP) != 0; - if ((bytes != null) && (bytes.length >= 4) && (!dontGunzip)) { - - int head = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); - if (GZIPInputStream.GZIP_MAGIC == head) { - ByteArrayInputStream bais = null; - GZIPInputStream gzis = null; - ByteArrayOutputStream baos = null; - byte[] buffer = new byte[2048]; - int length = 0; - - try { - baos = new ByteArrayOutputStream(); - bais = new ByteArrayInputStream(bytes); - gzis = new GZIPInputStream(bais); - - while((length = gzis.read(buffer)) >= 0) { - baos.write(buffer,0,length); - } // end while: reading input - - // No error? Get new bytes. - bytes = baos.toByteArray(); - - } catch (IOException e) { - e.printStackTrace(); - // Just return originally-decoded bytes - } finally { - IOUtils.closeQuietly(baos, gzis, bais); - } - - } // end if: gzipped - } // end if: bytes.length >= 2 - - return bytes; - } // end decode - - /** - * Attempts to decode Base64 data and deserialize a Java - * Object within. Returns null if there was an error. - * - * @param encodedObject The Base64 data to decode - * @return The decoded and deserialized object - * @throws NullPointerException if encodedObject is null - * @throws IOException if there is a general error - * @throws ClassNotFoundException if the decoded object is of a - * class that cannot be found by the JVM - * @since 1.5 - */ - public static Object decodeToObject(final String encodedObject) - throws IOException, java.lang.ClassNotFoundException { - return decodeToObject(encodedObject,NO_OPTIONS,null); - } - - - /** - * Attempts to decode Base64 data and deserialize a Java - * Object within. Returns null if there was an error. - * If loader is not null, it will be the class loader - * used when deserializing. - * - * @param encodedObject The Base64 data to decode - * @param options Various parameters related to decoding - * @param loader Optional class loader to use in deserializing classes. - * @return The decoded and deserialized object - * @throws NullPointerException if encodedObject is null - * @throws IOException if there is a general error - * @throws ClassNotFoundException if the decoded object is of a - * class that cannot be found by the JVM - * @since 2.3.4 - */ - public static Object decodeToObject(final String encodedObject, final int options, final ClassLoader loader) throws IOException, ClassNotFoundException { - // Decode and gunzip if necessary - byte[] objBytes = decode(encodedObject, options); - - ByteArrayInputStream bais = null; - ObjectInputStream ois = null; - Object obj = null; - - try { - bais = new ByteArrayInputStream(objBytes); - - // If no custom class loader is provided, use Java's builtin OIS. - if (loader == null) { - ois = new ObjectInputStream(bais); - } else { - // Make a customized object input stream that uses the provided class loader - ois = new ObjectInputStream(bais) { - @Override - public Class resolveClass(final java.io.ObjectStreamClass streamClass) - throws IOException, ClassNotFoundException { - Class c = Class.forName(streamClass.getName(), false, loader); - if (c == null) { - return super.resolveClass(streamClass); - } else { - return c; // Class loader knows of this class. - } // end else: not null - } // end resolveClass - }; // end ois - } // end else: no custom class loader - - obj = ois.readObject(); - } // end try - catch (IOException e) { - throw e; // Catch and throw in order to execute finally{} - } // end catch - catch (java.lang.ClassNotFoundException e) { - throw e; // Catch and throw in order to execute finally{} - } // end catch - finally { - IOUtils.closeQuietly(bais, ois); - } - - return obj; - } // end decodeObject - - - - /** - * Convenience method for encoding data to a file. - * - *

As of v 2.3, if there is a error, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned false, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param dataToEncode byte array of data to encode in base64 form - * @param filename Filename for saving encoded data - * @throws IOException if there is an error - * @throws NullPointerException if dataToEncode is null - * @since 2.1 - */ - public static void encodeToFile(final byte[] dataToEncode, final String filename) - throws IOException { - - if (dataToEncode == null) { - throw new NullPointerException("Data to encode was null."); - } // end iff - - Base64.OutputStream bos = null; - try { - bos = new Base64.OutputStream( - new FileOutputStream(filename), Base64.ENCODE); - bos.write(dataToEncode); - } // end try - catch (IOException e) { - throw e; // Catch and throw to execute finally{} block - } // end catch: IOException - finally { - try { bos.close(); } catch (Exception e) {} - } // end finally - - } // end encodeToFile - - - /** - * Convenience method for decoding data to a file. - * - *

As of v 2.3, if there is a error, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned false, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param dataToDecode Base64-encoded data as a string - * @param filename Filename for saving decoded data - * @throws IOException if there is an error - * @since 2.1 - */ - public static void decodeToFile(final String dataToDecode, final String filename) - throws IOException { - - Base64.OutputStream bos = null; - try { - bos = new Base64.OutputStream( - new FileOutputStream(filename), Base64.DECODE); - bos.write(dataToDecode.getBytes(PREFERRED_ENCODING)); - } // end try - catch (IOException e) { - throw e; // Catch and throw to execute finally{} block - } // end catch: IOException - finally { - try { bos.close(); } catch (Exception e) {} - } // end finally - - } // end decodeToFile - - - - - /** - * Convenience method for reading a base64-encoded - * file and decoding it. - * - *

As of v 2.3, if there is a error, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned false, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param filename Filename for reading encoded data - * @return decoded byte array - * @throws IOException if there is an error - * @since 2.1 - */ - public static byte[] decodeFromFile(final String filename) - throws IOException { - - Base64.InputStream bis = null; - try - { - // Set up some useful variables - File file = new File(filename); - byte[] buffer = null; - int length = 0; - int numBytes = 0; - - // Check for size of file - if (file.length() > Integer.MAX_VALUE) - { - throw new IOException("File is too big for this convenience method (" + file.length() + " bytes)."); - } // end if: file too big for int index - buffer = new byte[(int)file.length()]; - - // Open a stream - bis = new Base64.InputStream( - new BufferedInputStream( - new FileInputStream(file)), Base64.DECODE); - - // Read until done - while((numBytes = bis.read(buffer, length, 4096)) >= 0) { - length += numBytes; - } // end while - - // Save in a variable to return - final byte[] decodedData = new byte[length]; - System.arraycopy(buffer, 0, decodedData, 0, length); - return decodedData; - } catch (IOException e) { - throw e; // Catch and release to execute finally{} - } finally { - IOUtils.closeQuietly(bis); - } - } - - /** - * Convenience method for reading a binary file - * and base64-encoding it. - * - *

As of v 2.3, if there is a error, - * the method will throw an IOException. This is new to v2.3! - * In earlier versions, it just returned false, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param filename Filename for reading binary data - * @return base64-encoded string - * @throws IOException if there is an error - * @since 2.1 - */ - public static String encodeFromFile(final String filename) throws IOException { - Base64.InputStream bis = null; - try { - // Set up some useful variables - File file = new File(filename); - byte[] buffer = new byte[Math.max((int)(file.length() * 1.4+1),40)]; // Need max() for math on small files (v2.2.1); Need +1 for a few corner cases (v2.3.5) - int length = 0; - int numBytes = 0; - - // Open a stream - bis = new Base64.InputStream(new BufferedInputStream(new FileInputStream(file)), Base64.ENCODE); - - // Read until done - while((numBytes = bis.read(buffer, length, 4096)) >= 0) { - length += numBytes; - } // end while - - return new String(buffer, 0, length, Base64.PREFERRED_ENCODING); - - } catch (IOException e) { - throw e; // Catch and release to execute finally{} - } finally { - IOUtils.closeQuietly(bis); - } - } - - /** - * Reads infile and encodes it to outfile. - * - * @param infile Input file - * @param outfile Output file - * @throws IOException if there is an error - * @since 2.2 - */ - public static void encodeFileToFile(final String infile, final String outfile) throws IOException { - String encoded = Base64.encodeFromFile(infile); - java.io.OutputStream out = null; - try { - out = new BufferedOutputStream(new FileOutputStream(outfile)); - out.write(encoded.getBytes("US-ASCII")); // Strict, 7-bit output. - } catch (IOException e) { - throw e; - } finally { - IOUtils.closeQuietly(out); - } - } - - /** - * Reads infile and decodes it to outfile. - * - * @param infile Input file - * @param outfile Output file - * @throws IOException if there is an error - * @since 2.2 - */ - public static void decodeFileToFile(final String infile, final String outfile) throws IOException { - byte[] decoded = Base64.decodeFromFile(infile); - java.io.OutputStream out = null; - try { - out = new BufferedOutputStream(new FileOutputStream(outfile)); - out.write(decoded); - } catch (IOException e) { - throw e; // Catch and release to execute finally{} - } finally { - IOUtils.closeQuietly(out); - } - } - - /** Defeats instantiation. */ - private Base64() {} - - /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ - - /** - * A {@link Base64.InputStream} will read data from another - * java.io.InputStream, given in the constructor, - * and encode/decode to/from Base64 notation on the fly. - * - * @see Base64 - * @since 1.3 - */ - public static class InputStream extends java.io.FilterInputStream { - - // Fields - private final boolean encode; // Encoding or decoding - private int position; // Current position in the buffer - private final byte[] buffer; // Small buffer holding converted data - private final int bufferLength; // Length of buffer (3 or 4) - private int numSigBytes; // Number of meaningful bytes in the buffer - private int lineLength; - private final boolean breakLines; // Break lines at less than 80 characters - private final int options; // Record options used to create the stream. - private final byte[] decodabet; // Local copies to avoid extra method calls - - /** - * Constructs a {@link Base64.InputStream} in DECODE mode. - * - * @param in the java.io.InputStream from which to read data. - * @since 1.3 - */ - public InputStream(final java.io.InputStream in) { - this(in, DECODE); - } - - /** - * Constructs a {@link Base64.InputStream} in - * either ENCODE or DECODE mode. - *

- * Valid options:

-         *   ENCODE or DECODE: Encode or Decode as data is read.
-         *   DO_BREAK_LINES: break lines at 76 characters
-         *     (only meaningful when encoding)
-         * 
- *

- * Example: new Base64.InputStream(in, Base64.DECODE) - * - * @param in the java.io.InputStream from which to read data. - * @param options Specified options - * @see Base64#ENCODE - * @see Base64#DECODE - * @see Base64#DO_BREAK_LINES - * @since 2.0 - */ - public InputStream(final java.io.InputStream in, final int options) { - super(in); - this.options = options; // Record for later - this.breakLines = (options & DO_BREAK_LINES) > 0; - this.encode = (options & ENCODE) > 0; - this.bufferLength = encode ? 4 : 3; - this.buffer = new byte[bufferLength]; - this.position = -1; - this.lineLength = 0; - this.decodabet = getDecodabet(options); - } - - /** - * Reads enough of the input stream to convert - * to/from Base64 and returns the next byte. - * - * @return next byte - * @since 1.3 - */ - @Override - public int read() throws IOException { - - // Do we need to get data? - if (position < 0) { - if (encode) { - byte[] b3 = new byte[3]; - int numBinaryBytes = 0; - for (int i = 0; i < 3; i++) { - int b = in.read(); - - // If end of stream, b is -1. - if (b >= 0) { - b3[i] = (byte)b; - numBinaryBytes++; - } else { - break; // out of for loop - } // end else: end of stream - - } // end for: each needed input byte - - if (numBinaryBytes > 0) { - encode3to4(b3, 0, numBinaryBytes, buffer, 0, options); - position = 0; - numSigBytes = 4; - } // end if: got data - else { - return -1; // Must be end of stream - } // end else - } // end if: encoding - - // Else decoding - else { - byte[] b4 = new byte[4]; - int i = 0; - for (i = 0; i < 4; i++) { - // Read four "meaningful" bytes: - int b = 0; - do { b = in.read(); } - while(b >= 0 && decodabet[b & 0x7f] <= WHITE_SPACE_ENC); - - if (b < 0) { - break; // Reads a -1 if end of stream - } // end if: end of stream - - b4[i] = (byte)b; - } // end for: each needed input byte - - if (i == 4) { - numSigBytes = decode4to3(b4, 0, buffer, 0, options); - position = 0; - } // end if: got four characters - else if (i == 0) { - return -1; - } // end else if: also padded correctly - else { - // Must have broken out from above. - throw new IOException("Improperly padded Base64 input."); - } // end - - } // end else: decode - } // end else: get data - - // Got data? - if (position >= 0) { - // End of relevant data? - if (position >= numSigBytes) { - return -1; - } // end if: got data - - if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) { - lineLength = 0; - return '\n'; - } // end if - else { - lineLength++; // This isn't important when decoding - // but throwing an extra "if" seems - // just as wasteful. - - int b = buffer[position++]; - - if (position >= bufferLength) { - position = -1; - } // end if: end - - return b & 0xFF; // This is how you "cast" a byte that's - // intended to be unsigned. - } // end else - } // end if: position >= 0 - - // Else error - else { - throw new IOException("Error in Base64 code reading stream."); - } // end else - } // end read - - /** - * Calls {@link #read()} repeatedly until the end of stream - * is reached or len bytes are read. - * Returns number of bytes read into array or -1 if - * end of stream is encountered. - * - * @param dest array to hold values - * @param off offset for array - * @param len max number of bytes to read into array - * @return bytes read into array or -1 if end of stream is encountered. - * @since 1.3 - */ - @Override - public int read(final byte[] dest, final int off, final int len) throws IOException { - int i; - int b; - for (i = 0; i < len; i++) { - b = read(); - - if (b >= 0) { - dest[off + i] = (byte) b; - } - else if (i == 0) { - return -1; - } - else { - break; // Out of 'for' loop - } // Out of 'for' loop - } // end for: each byte read - return i; - } // end read - - } // end inner class InputStream - - /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */ - - /** - * A {@link Base64.OutputStream} will write data to another - * java.io.OutputStream, given in the constructor, - * and encode/decode to/from Base64 notation on the fly. - * - * @see Base64 - * @since 1.3 - */ - public static class OutputStream extends java.io.FilterOutputStream { - - private final boolean encode; - private int position; - private byte[] buffer; - private final int bufferLength; - private int lineLength; - private final boolean breakLines; - private final byte[] b4; // Scratch used in a few places - private boolean suspendEncoding; - private final int options; // Record for later - private final byte[] decodabet; // Local copies to avoid extra method calls - - /** - * Constructs a {@link Base64.OutputStream} in ENCODE mode. - * - * @param out the java.io.OutputStream to which data will be written. - * @since 1.3 - */ - public OutputStream(final java.io.OutputStream out) { - this(out, ENCODE); - } - - /** - * Constructs a {@link Base64.OutputStream} in - * either ENCODE or DECODE mode. - *

- * Valid options:

-         *   ENCODE or DECODE: Encode or Decode as data is read.
-         *   DO_BREAK_LINES: don't break lines at 76 characters
-         *     (only meaningful when encoding)
-         * 
- *

- * Example: new Base64.OutputStream(out, Base64.ENCODE) - * - * @param out the java.io.OutputStream to which data will be written. - * @param options Specified options. - * @see Base64#ENCODE - * @see Base64#DECODE - * @see Base64#DO_BREAK_LINES - * @since 1.3 - */ - public OutputStream(final java.io.OutputStream out, final int options) { - super(out); - this.breakLines = (options & DO_BREAK_LINES) != 0; - this.encode = (options & ENCODE) != 0; - this.bufferLength = encode ? 3 : 4; - this.buffer = new byte[bufferLength]; - this.position = 0; - this.lineLength = 0; - this.suspendEncoding = false; - this.b4 = new byte[4]; - this.options = options; - this.decodabet = getDecodabet(options); - } - - /** - * Writes the byte to the output stream after converting to/from Base64 - * notation. When encoding, bytes are buffered three at a time before - * the output stream actually gets a write() call. When decoding, bytes - * are buffered four at a time. - * - * @param theByte the byte to write - * @since 1.3 - */ - @Override - public void write(final int theByte) throws IOException { - // Encoding suspended? - if (suspendEncoding) { - this.out.write(theByte); - return; - } - - // Encode? - if (encode) { - buffer[position++] = (byte)theByte; - if (position >= bufferLength) { // Enough to encode. - - this.out.write(encode3to4(b4, buffer, bufferLength, options)); - - lineLength += 4; - if (breakLines && lineLength >= MAX_LINE_LENGTH) { - this.out.write(NEW_LINE); - lineLength = 0; - } // end if: end of line - - position = 0; - } // end if: enough to output - } // end if: encoding - - // Else, Decoding - else { - // Meaningful Base64 character? - if (decodabet[theByte & 0x7f] > WHITE_SPACE_ENC) { - buffer[position++] = (byte)theByte; - if (position >= bufferLength) { - // Enough to output - int len = Base64.decode4to3(buffer, 0, b4, 0, options); - out.write(b4, 0, len); - position = 0; - } - } else if (decodabet[theByte & 0x7f] != WHITE_SPACE_ENC) { - // Not white space either - throw new IOException("Invalid character in Base64 data."); - } - } - } - - /** - * Calls {@link #write(int)} repeatedly until len - * bytes are written. - * - * @param theBytes array from which to read bytes - * @param off offset for array - * @param len max number of bytes to read into array - * @since 1.3 - */ - @Override - public void write(final byte[] theBytes, final int off, final int len) throws IOException { - // Encoding suspended? - if (suspendEncoding) { - this.out.write(theBytes, off, len); - return; - } // end if: supsended - - for (int i = 0; i < len; i++) { - write(theBytes[off + i]); - } // end for: each byte written - } - - /** - * Pads the buffer without closing the stream. - * - * @throws IOException if there's an error. - */ - public void flushBase64() throws IOException { - if (position > 0) { - if (encode) { - out.write(encode3to4(b4, buffer, position, options)); - position = 0; - } // end if: encoding - else { - throw new IOException("Base64 input not properly padded."); - } // end else: decoding - } // end if: buffer partially full - } - - /** - * Flushes and closes (I think, in the superclass) the stream. - * - * @since 1.3 - */ - @Override - public void close() throws IOException { - // 1. Ensure that pending characters are written - flushBase64(); - - // 2. Actually close the stream - // Base class both flushes and closes. - super.close(); - - buffer = null; - out = null; - } - - /** - * Suspends encoding of the stream. - * May be helpful if you need to embed a piece of - * base64-encoded data in a stream. - * - * @throws IOException if there's an error flushing - * @since 1.5.1 - */ - public void suspendEncoding() throws IOException { - flushBase64(); - this.suspendEncoding = true; - } - - /** - * Resumes encoding of the stream. - * May be helpful if you need to embed a piece of - * base64-encoded data in a stream. - * - * @since 1.5.1 - */ - public void resumeEncoding() { - this.suspendEncoding = false; - } - } // end inner class OutputStream -} // end class Base64 diff --git a/src/main/java/org/springframework/shell/support/util/ClassUtils.java b/src/main/java/org/springframework/shell/support/util/ClassUtils.java deleted file mode 100644 index b4696e47..00000000 --- a/src/main/java/org/springframework/shell/support/util/ClassUtils.java +++ /dev/null @@ -1,1026 +0,0 @@ -/* - * Copyright 2002-2010 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.beans.Introspector; -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -/** - * Miscellaneous class utility methods. Mainly for internal use within the - * framework; consider - * Apache Commons Lang - * for a more comprehensive suite of class utilities. - * - * @author Juergen Hoeller - * @author Keith Donald - * @author Rob Harrop - * @author Sam Brannen - * @since 1.1 - * @see org.springframework.util.TypeUtils - * @see ReflectionUtils - */ -@SuppressWarnings("all") -public abstract class ClassUtils { - - /** Suffix for array class names: "[]" */ - public static final String ARRAY_SUFFIX = "[]"; - - /** Prefix for internal array class names: "[" */ - private static final String INTERNAL_ARRAY_PREFIX = "["; - - /** Prefix for internal non-primitive array class names: "[L" */ - private static final String NON_PRIMITIVE_ARRAY_PREFIX = "[L"; - - /** The package separator character '.' */ - private static final char PACKAGE_SEPARATOR = '.'; - - /** The inner class separator character '$' */ - private static final char INNER_CLASS_SEPARATOR = '$'; - - /** The CGLIB class separator character "$$" */ - public static final String CGLIB_CLASS_SEPARATOR = "$$"; - - /** The ".class" file suffix */ - public static final String CLASS_FILE_SUFFIX = ".class"; - - /** - * Map with primitive wrapper type as key and corresponding primitive - * type as value, for example: Integer.class -> int.class. - */ - private static final Map, Class> primitiveWrapperTypeMap = new HashMap, Class>(8); - - /** - * Map with primitive type as key and corresponding wrapper - * type as value, for example: int.class -> Integer.class. - */ - private static final Map, Class> primitiveTypeToWrapperMap = new HashMap, Class>(8); - - /** - * Map with primitive type name as key and corresponding primitive - * type as value, for example: "int" -> "int.class". - */ - private static final Map> primitiveTypeNameMap = new HashMap>(32); - - /** - * Map with common "java.lang" class name as key and corresponding Class as value. - * Primarily for efficient deserialization of remote invocations. - */ - private static final Map> commonClassCache = new HashMap>(32); - - static { - primitiveWrapperTypeMap.put(Boolean.class, boolean.class); - primitiveWrapperTypeMap.put(Byte.class, byte.class); - primitiveWrapperTypeMap.put(Character.class, char.class); - primitiveWrapperTypeMap.put(Double.class, double.class); - primitiveWrapperTypeMap.put(Float.class, float.class); - primitiveWrapperTypeMap.put(Integer.class, int.class); - primitiveWrapperTypeMap.put(Long.class, long.class); - primitiveWrapperTypeMap.put(Short.class, short.class); - - for (Map.Entry, Class> entry : primitiveWrapperTypeMap.entrySet()) { - primitiveTypeToWrapperMap.put(entry.getValue(), entry.getKey()); - registerCommonClasses(entry.getKey()); - } - - Set> primitiveTypes = new HashSet>(32); - primitiveTypes.addAll(primitiveWrapperTypeMap.values()); - primitiveTypes.addAll(Arrays.asList(boolean[].class, byte[].class, char[].class, double[].class, float[].class, int[].class, long[].class, short[].class)); - primitiveTypes.add(void.class); - for (Class primitiveType : primitiveTypes) { - primitiveTypeNameMap.put(primitiveType.getName(), primitiveType); - } - - registerCommonClasses(Boolean[].class, Byte[].class, Character[].class, Double[].class, Float[].class, Integer[].class, Long[].class, Short[].class); - registerCommonClasses(Number.class, Number[].class, String.class, String[].class, Object.class, Object[].class, Class.class, Class[].class); - registerCommonClasses(Throwable.class, Exception.class, RuntimeException.class, Error.class, StackTraceElement.class, StackTraceElement[].class); - } - - /** - * Register the given common classes with the ClassUtils cache. - */ - private static void registerCommonClasses(final Class... commonClasses) { - for (Class clazz : commonClasses) { - commonClassCache.put(clazz.getName(), clazz); - } - } - - /** - * Return the default ClassLoader to use: typically the thread context - * ClassLoader, if available; the ClassLoader that loaded the ClassUtils - * class will be used as fallback. - *

Call this method if you intend to use the thread context ClassLoader - * in a scenario where you absolutely need a non-null ClassLoader reference: - * for example, for class path resource loading (but not necessarily for - * Class.forName, which accepts a null ClassLoader - * reference as well). - * @return the default ClassLoader (never null) - * @see java.lang.Thread#getContextClassLoader() - */ - public static ClassLoader getDefaultClassLoader() { - ClassLoader cl = null; - try { - cl = Thread.currentThread().getContextClassLoader(); - } catch (Throwable ex) { - // Cannot access thread context ClassLoader - falling back to system class loader... - } - if (cl == null) { - // No thread context class loader -> use class loader of this class. - cl = ClassUtils.class.getClassLoader(); - } - return cl; - } - - /** - * Override the thread context ClassLoader with the environment's bean ClassLoader - * if necessary, i.e. if the bean ClassLoader is not equivalent to the thread - * context ClassLoader already. - * @param classLoaderToUse the actual ClassLoader to use for the thread context - * @return the original thread context ClassLoader, or null if not overridden - */ - public static ClassLoader overrideThreadContextClassLoader(final ClassLoader classLoaderToUse) { - Thread currentThread = Thread.currentThread(); - ClassLoader threadContextClassLoader = currentThread.getContextClassLoader(); - if (classLoaderToUse != null && !classLoaderToUse.equals(threadContextClassLoader)) { - currentThread.setContextClassLoader(classLoaderToUse); - return threadContextClassLoader; - } - return null; - } - - /** - * Replacement for Class.forName() that also returns Class instances - * for primitives (like "int") and array class names (like "String[]"). - *

Always uses the default class loader: that is, preferably the thread context - * class loader, or the ClassLoader that loaded the ClassUtils class as fallback. - * @param name the name of the Class - * @return Class instance for the supplied name - * @throws ClassNotFoundException if the class was not found - * @throws LinkageError if the class file could not be loaded - * @see Class#forName(String, boolean, ClassLoader) - * @see #getDefaultClassLoader() - * @deprecated as of Spring 3.0, in favor of specifying a ClassLoader explicitly: - * see {@link #forName(String, ClassLoader)} - */ - @Deprecated - public static Class forName(final String name) throws ClassNotFoundException, LinkageError { - return forName(name, getDefaultClassLoader()); - } - - /** - * Replacement for Class.forName() that also returns Class instances - * for primitives (e.g."int") and array class names (e.g. "String[]"). - * Furthermore, it is also capable of resolving inner class names in Java source - * style (e.g. "java.lang.Thread.State" instead of "java.lang.Thread$State"). - * @param name the name of the Class - * @param classLoader the class loader to use - * (may be null, which indicates the default class loader) - * @return Class instance for the supplied name - * @throws ClassNotFoundException if the class was not found - * @throws LinkageError if the class file could not be loaded - * @see Class#forName(String, boolean, ClassLoader) - */ - public static Class forName(final String name, final ClassLoader classLoader) throws ClassNotFoundException, LinkageError { - Assert.notNull(name, "Name must not be null"); - - Class clazz = resolvePrimitiveClassName(name); - if (clazz == null) { - clazz = commonClassCache.get(name); - } - if (clazz != null) { - return clazz; - } - - // "java.lang.String[]" style arrays - if (name.endsWith(ARRAY_SUFFIX)) { - String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length()); - Class elementClass = forName(elementClassName, classLoader); - return Array.newInstance(elementClass, 0).getClass(); - } - - // "[Ljava.lang.String;" style arrays - if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) { - String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1); - Class elementClass = forName(elementName, classLoader); - return Array.newInstance(elementClass, 0).getClass(); - } - - // "[[I" or "[[Ljava.lang.String;" style arrays - if (name.startsWith(INTERNAL_ARRAY_PREFIX)) { - String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length()); - Class elementClass = forName(elementName, classLoader); - return Array.newInstance(elementClass, 0).getClass(); - } - - ClassLoader classLoaderToUse = classLoader; - if (classLoaderToUse == null) { - classLoaderToUse = getDefaultClassLoader(); - } - try { - return classLoaderToUse.loadClass(name); - } catch (ClassNotFoundException ex) { - int lastDotIndex = name.lastIndexOf('.'); - if (lastDotIndex != -1) { - String innerClassName = name.substring(0, lastDotIndex) + '$' + name.substring(lastDotIndex + 1); - try { - return classLoaderToUse.loadClass(innerClassName); - } catch (ClassNotFoundException ex2) { - // swallow - let original exception get through - } - } - throw ex; - } - } - - /** - * Resolve the given class name into a Class instance. Supports - * primitives (like "int") and array class names (like "String[]"). - *

This is effectively equivalent to the forName - * method with the same arguments, with the only difference being - * the exceptions thrown in case of class loading failure. - * @param className the name of the Class - * @param classLoader the class loader to use - * (may be null, which indicates the default class loader) - * @return Class instance for the supplied name - * @throws IllegalArgumentException if the class name was not resolvable - * (that is, the class could not be found or the class file could not be loaded) - * @see #forName(String, ClassLoader) - */ - public static Class resolveClassName(final String className, final ClassLoader classLoader) throws IllegalArgumentException { - try { - return forName(className, classLoader); - } catch (ClassNotFoundException ex) { - throw new IllegalArgumentException("Cannot find class [" + className + "]", ex); - } catch (LinkageError ex) { - throw new IllegalArgumentException("Error loading class [" + className + "]: problem with class file or dependent class.", ex); - } - } - - /** - * Resolve the given class name as primitive class, if appropriate, - * according to the JVM's naming rules for primitive classes. - *

Also supports the JVM's internal class names for primitive arrays. - * Does not support the "[]" suffix notation for primitive arrays; - * this is only supported by {@link #forName(String, ClassLoader)}. - * @param name the name of the potentially primitive class - * @return the primitive class, or null if the name does not denote - * a primitive class or primitive array class - */ - public static Class resolvePrimitiveClassName(final String name) { - Class result = null; - // Most class names will be quite long, considering that they - // SHOULD sit in a package, so a length check is worthwhile. - if (name != null && name.length() <= 8) { - // Could be a primitive - likely. - result = primitiveTypeNameMap.get(name); - } - return result; - } - - /** - * Determine whether the {@link Class} identified by the supplied name is present - * and can be loaded. Will return false if either the class or - * one of its dependencies is not present or cannot be loaded. - * @param className the name of the class to check - * @return whether the specified class is present - * @deprecated as of Spring 2.5, in favor of {@link #isPresent(String, ClassLoader)} - */ - @Deprecated - public static boolean isPresent(final String className) { - return isPresent(className, getDefaultClassLoader()); - } - - /** - * Determine whether the {@link Class} identified by the supplied name is present - * and can be loaded. Will return false if either the class or - * one of its dependencies is not present or cannot be loaded. - * @param className the name of the class to check - * @param classLoader the class loader to use - * (may be null, which indicates the default class loader) - * @return whether the specified class is present - */ - public static boolean isPresent(final String className, final ClassLoader classLoader) { - try { - forName(className, classLoader); - return true; - } catch (Throwable ex) { - // Class or one of its dependencies is not present... - return false; - } - } - - /** - * Return the user-defined class for the given instance: usually simply - * the class of the given instance, but the original class in case of a - * CGLIB-generated subclass. - * @param instance the instance to check - * @return the user-defined class - */ - public static Class getUserClass(final Object instance) { - Assert.notNull(instance, "Instance must not be null"); - return getUserClass(instance.getClass()); - } - - /** - * Return the user-defined class for the given class: usually simply the given - * class, but the original class in case of a CGLIB-generated subclass. - * @param clazz the class to check - * @return the user-defined class - */ - public static Class getUserClass(final Class clazz) { - if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) { - Class superClass = clazz.getSuperclass(); - if (superClass != null && !Object.class.equals(superClass)) { - return superClass; - } - } - return clazz; - } - - /** - * Check whether the given class is cache-safe in the given context, - * i.e. whether it is loaded by the given ClassLoader or a parent of it. - * @param clazz the class to analyze - * @param classLoader the ClassLoader to potentially cache metadata in - */ - public static boolean isCacheSafe(final Class clazz, final ClassLoader classLoader) { - Assert.notNull(clazz, "Class must not be null"); - ClassLoader target = clazz.getClassLoader(); - if (target == null) { - return false; - } - ClassLoader cur = classLoader; - if (cur == target) { - return true; - } - while (cur != null) { - cur = cur.getParent(); - if (cur == target) { - return true; - } - } - return false; - } - - /** - * Get the class name without the qualified package name. - * @param className the className to get the short name for - * @return the class name of the class without the package name - * @throws IllegalArgumentException if the className is empty - */ - public static String getShortName(final String className) { - Assert.hasLength(className, "Class name must not be empty"); - int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR); - int nameEndIndex = className.indexOf(CGLIB_CLASS_SEPARATOR); - if (nameEndIndex == -1) { - nameEndIndex = className.length(); - } - String shortName = className.substring(lastDotIndex + 1, nameEndIndex); - shortName = shortName.replace(INNER_CLASS_SEPARATOR, PACKAGE_SEPARATOR); - return shortName; - } - - /** - * Get the class name without the qualified package name. - * @param clazz the class to get the short name for - * @return the class name of the class without the package name - */ - public static String getShortName(final Class clazz) { - return getShortName(getQualifiedName(clazz)); - } - - /** - * Return the short string name of a Java class in uncapitalized JavaBeans - * property format. Strips the outer class name in case of an inner class. - * @param clazz the class - * @return the short name rendered in a standard JavaBeans property format - * @see java.beans.Introspector#decapitalize(String) - */ - public static String getShortNameAsProperty(final Class clazz) { - String shortName = ClassUtils.getShortName(clazz); - int dotIndex = shortName.lastIndexOf('.'); - shortName = (dotIndex != -1 ? shortName.substring(dotIndex + 1) : shortName); - return Introspector.decapitalize(shortName); - } - - /** - * Determine the name of the class file, relative to the containing - * package: e.g. "String.class" - * @param clazz the class - * @return the file name of the ".class" file - */ - public static String getClassFileName(final Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - String className = clazz.getName(); - int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR); - return className.substring(lastDotIndex + 1) + CLASS_FILE_SUFFIX; - } - - /** - * Determine the name of the package of the given class: - * e.g. "java.lang" for the java.lang.String class. - * @param clazz the class - * @return the package name, or the empty String if the class - * is defined in the default package - */ - public static String getPackageName(final Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - String className = clazz.getName(); - int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR); - return (lastDotIndex != -1 ? className.substring(0, lastDotIndex) : ""); - } - - /** - * Return the qualified name of the given class: usually simply - * the class name, but component type class name + "[]" for arrays. - * @param clazz the class - * @return the qualified name of the class - */ - public static String getQualifiedName(final Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - if (clazz.isArray()) { - return getQualifiedNameForArray(clazz); - } else { - return clazz.getName(); - } - } - - /** - * Build a nice qualified name for an array: - * component type class name + "[]". - * @param clazz the array class - * @return a qualified name for the array class - */ - private static String getQualifiedNameForArray(Class clazz) { - StringBuilder result = new StringBuilder(); - while (clazz.isArray()) { - clazz = clazz.getComponentType(); - result.append(ClassUtils.ARRAY_SUFFIX); - } - result.insert(0, clazz.getName()); - return result.toString(); - } - - /** - * Return the qualified name of the given method, consisting of - * fully qualified interface/class name + "." + method name. - * @param method the method - * @return the qualified name of the method - */ - public static String getQualifiedMethodName(final Method method) { - Assert.notNull(method, "Method must not be null"); - return method.getDeclaringClass().getName() + "." + method.getName(); - } - - /** - * Return a descriptive name for the given object's type: usually simply - * the class name, but component type class name + "[]" for arrays, - * and an appended list of implemented interfaces for JDK proxies. - * @param value the value to introspect - * @return the qualified name of the class - */ - public static String getDescriptiveType(final Object value) { - if (value == null) { - return null; - } - Class clazz = value.getClass(); - if (Proxy.isProxyClass(clazz)) { - StringBuilder result = new StringBuilder(clazz.getName()); - result.append(" implementing "); - Class[] ifcs = clazz.getInterfaces(); - for (int i = 0; i < ifcs.length; i++) { - result.append(ifcs[i].getName()); - if (i < ifcs.length - 1) { - result.append(','); - } - } - return result.toString(); - } else if (clazz.isArray()) { - return getQualifiedNameForArray(clazz); - } else { - return clazz.getName(); - } - } - - /** - * Check whether the given class matches the user-specified type name. - * @param clazz the class to check - * @param typeName the type name to match - */ - public static boolean matchesTypeName(final Class clazz, final String typeName) { - return (typeName != null && - (typeName.equals(clazz.getName()) || typeName.equals(clazz.getSimpleName()) || - (clazz.isArray() && typeName.equals(getQualifiedNameForArray(clazz))))); - } - - /** - * Determine whether the given class has a public constructor with the given signature. - *

Essentially translates NoSuchMethodException to "false". - * @param clazz the clazz to analyze - * @param parameterTypes the parameter types of the method - * @return whether the class has a corresponding constructor - * @see java.lang.Class#getMethod - */ - public static boolean hasConstructor(final Class clazz, final Class... parameterTypes) { - return (getConstructorIfAvailable(clazz, parameterTypes) != null); - } - - /** - * Determine whether the given class has a public constructor with the given signature, - * and return it if available (else return null). - *

Essentially translates NoSuchMethodException to null. - * @param clazz the clazz to analyze - * @param parameterTypes the parameter types of the method - * @return the constructor, or null if not found - * @see java.lang.Class#getConstructor - */ - public static Constructor getConstructorIfAvailable(final Class clazz, final Class... parameterTypes) { - Assert.notNull(clazz, "Class must not be null"); - try { - return clazz.getConstructor(parameterTypes); - } catch (NoSuchMethodException ex) { - return null; - } - } - - /** - * Determine whether the given class has a method with the given signature. - *

Essentially translates NoSuchMethodException to "false". - * @param clazz the clazz to analyze - * @param methodName the name of the method - * @param parameterTypes the parameter types of the method - * @return whether the class has a corresponding method - * @see java.lang.Class#getMethod - */ - public static boolean hasMethod(final Class clazz, final String methodName, final Class... parameterTypes) { - return (getMethodIfAvailable(clazz, methodName, parameterTypes) != null); - } - - /** - * Determine whether the given class has a method with the given signature, - * and return it if available (else return null). - *

Essentially translates NoSuchMethodException to null. - * @param clazz the clazz to analyze - * @param methodName the name of the method - * @param parameterTypes the parameter types of the method - * @return the method, or null if not found - * @see java.lang.Class#getMethod - */ - public static Method getMethodIfAvailable(final Class clazz, final String methodName, final Class... parameterTypes) { - Assert.notNull(clazz, "Class must not be null"); - Assert.notNull(methodName, "Method name must not be null"); - try { - return clazz.getMethod(methodName, parameterTypes); - } catch (NoSuchMethodException ex) { - return null; - } - } - - /** - * Return the number of methods with a given name (with any argument types), - * for the given class and/or its superclasses. Includes non-public methods. - * @param clazz the clazz to check - * @param methodName the name of the method - * @return the number of methods with the given name - */ - public static int getMethodCountForName(final Class clazz, final String methodName) { - Assert.notNull(clazz, "Class must not be null"); - Assert.notNull(methodName, "Method name must not be null"); - int count = 0; - Method[] declaredMethods = clazz.getDeclaredMethods(); - for (Method method : declaredMethods) { - if (methodName.equals(method.getName())) { - count++; - } - } - Class[] ifcs = clazz.getInterfaces(); - for (Class ifc : ifcs) { - count += getMethodCountForName(ifc, methodName); - } - if (clazz.getSuperclass() != null) { - count += getMethodCountForName(clazz.getSuperclass(), methodName); - } - return count; - } - - /** - * Does the given class or one of its superclasses at least have one or more - * methods with the supplied name (with any argument types)? - * Includes non-public methods. - * @param clazz the clazz to check - * @param methodName the name of the method - * @return whether there is at least one method with the given name - */ - public static boolean hasAtLeastOneMethodWithName(final Class clazz, final String methodName) { - Assert.notNull(clazz, "Class must not be null"); - Assert.notNull(methodName, "Method name must not be null"); - Method[] declaredMethods = clazz.getDeclaredMethods(); - for (Method method : declaredMethods) { - if (method.getName().equals(methodName)) { - return true; - } - } - Class[] ifcs = clazz.getInterfaces(); - for (Class ifc : ifcs) { - if (hasAtLeastOneMethodWithName(ifc, methodName)) { - return true; - } - } - return (clazz.getSuperclass() != null && hasAtLeastOneMethodWithName(clazz.getSuperclass(), methodName)); - } - - /** - * Given a method, which may come from an interface, and a target class used - * in the current reflective invocation, find the corresponding target method - * if there is one. E.g. the method may be IFoo.bar() and the - * target class may be DefaultFoo. In this case, the method may be - * DefaultFoo.bar(). This enables attributes on that method to be found. - *

NOTE: In contrast to {@link org.springframework.aop.support.AopUtils#getMostSpecificMethod}, - * this method does not resolve Java 5 bridge methods automatically. - * Call {@link org.springframework.core.BridgeMethodResolver#findBridgedMethod} - * if bridge method resolution is desirable (e.g. for obtaining metadata from - * the original method definition). - * @param method the method to be invoked, which may come from an interface - * @param targetClass the target class for the current invocation. - * May be null or may not even implement the method. - * @return the specific target method, or the original method if the - * targetClass doesn't implement it or is null - */ - public static Method getMostSpecificMethod(final Method method, final Class targetClass) { - Method specificMethod = null; - if (method != null && isOverridable(method, targetClass) && targetClass != null && !targetClass.equals(method.getDeclaringClass())) { - specificMethod = ReflectionUtils.findMethod(targetClass, method.getName(), method.getParameterTypes()); - } - return (specificMethod != null ? specificMethod : method); - } - - /** - * Determine whether the given method is overridable in the given target class. - * @param method the method to check - * @param targetClass the target class to check against - */ - private static boolean isOverridable(final Method method, final Class targetClass) { - if (Modifier.isPrivate(method.getModifiers())) { - return false; - } - if (Modifier.isPublic(method.getModifiers()) || Modifier.isProtected(method.getModifiers())) { - return true; - } - return getPackageName(method.getDeclaringClass()).equals(getPackageName(targetClass)); - } - - /** - * Return a public static method of a class. - * @param methodName the static method name - * @param clazz the class which defines the method - * @param args the parameter types to the method - * @return the static method, or null if no static method was found - * @throws IllegalArgumentException if the method name is blank or the clazz is null - */ - public static Method getStaticMethod(final Class clazz, final String methodName, final Class... args) { - Assert.notNull(clazz, "Class must not be null"); - Assert.notNull(methodName, "Method name must not be null"); - try { - Method method = clazz.getMethod(methodName, args); - return Modifier.isStatic(method.getModifiers()) ? method : null; - } catch (NoSuchMethodException ex) { - return null; - } - } - - /** - * Check if the given class represents a primitive wrapper, - * i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double. - * @param clazz the class to check - * @return whether the given class is a primitive wrapper class - */ - public static boolean isPrimitiveWrapper(final Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - return primitiveWrapperTypeMap.containsKey(clazz); - } - - /** - * Check if the given class represents a primitive (i.e. boolean, byte, - * char, short, int, long, float, or double) or a primitive wrapper - * (i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double). - * @param clazz the class to check - * @return whether the given class is a primitive or primitive wrapper class - */ - public static boolean isPrimitiveOrWrapper(final Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - return (clazz.isPrimitive() || isPrimitiveWrapper(clazz)); - } - - /** - * Check if the given class represents an array of primitives, - * i.e. boolean, byte, char, short, int, long, float, or double. - * @param clazz the class to check - * @return whether the given class is a primitive array class - */ - public static boolean isPrimitiveArray(final Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - return (clazz.isArray() && clazz.getComponentType().isPrimitive()); - } - - /** - * Check if the given class represents an array of primitive wrappers, - * i.e. Boolean, Byte, Character, Short, Integer, Long, Float, or Double. - * @param clazz the class to check - * @return whether the given class is a primitive wrapper array class - */ - public static boolean isPrimitiveWrapperArray(final Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - return (clazz.isArray() && isPrimitiveWrapper(clazz.getComponentType())); - } - - /** - * Resolve the given class if it is a primitive class, - * returning the corresponding primitive wrapper type instead. - * @param clazz the class to check - * @return the original class, or a primitive wrapper for the original primitive type - */ - public static Class resolvePrimitiveIfNecessary(final Class clazz) { - Assert.notNull(clazz, "Class must not be null"); - return (clazz.isPrimitive() && clazz != void.class? primitiveTypeToWrapperMap.get(clazz) : clazz); - } - - /** - * Check if the right-hand side type may be assigned to the left-hand side - * type, assuming setting by reflection. Considers primitive wrapper - * classes as assignable to the corresponding primitive types. - * @param lhsType the target type - * @param rhsType the value type that should be assigned to the target type - * @return if the target type is assignable from the value type - * @see org.springframework.util.TypeUtils#isAssignable - */ - public static boolean isAssignable(final Class lhsType, final Class rhsType) { - Assert.notNull(lhsType, "Left-hand side type must not be null"); - Assert.notNull(rhsType, "Right-hand side type must not be null"); - return (lhsType.isAssignableFrom(rhsType) || lhsType.equals(primitiveWrapperTypeMap.get(rhsType))); - } - - /** - * Determine if the given type is assignable from the given value, - * assuming setting by reflection. Considers primitive wrapper classes - * as assignable to the corresponding primitive types. - * @param type the target type - * @param value the value that should be assigned to the type - * @return if the type is assignable from the value - */ - public static boolean isAssignableValue(final Class type, final Object value) { - Assert.notNull(type, "Type must not be null"); - return (value != null ? isAssignable(type, value.getClass()) : !type.isPrimitive()); - } - - /** - * Convert a "/"-based resource path to a "."-based fully qualified class name. - * @param resourcePath the resource path pointing to a class - * @return the corresponding fully qualified class name - */ - public static String convertResourcePathToClassName(final String resourcePath) { - Assert.notNull(resourcePath, "Resource path must not be null"); - return resourcePath.replace('/', '.'); - } - - /** - * Convert a "."-based fully qualified class name to a "/"-based resource path. - * @param className the fully qualified class name - * @return the corresponding resource path, pointing to the class - */ - public static String convertClassNameToResourcePath(final String className) { - Assert.notNull(className, "Class name must not be null"); - return className.replace('.', '/'); - } - - /** - * Return a path suitable for use with ClassLoader.getResource - * (also suitable for use with Class.getResource by prepending a - * slash ('/') to the return value). Built by taking the package of the specified - * class file, converting all dots ('.') to slashes ('/'), adding a trailing slash - * if necessary, and concatenating the specified resource name to this. - *
As such, this function may be used to build a path suitable for - * loading a resource file that is in the same package as a class file, - * although {@link org.springframework.core.io.ClassPathResource} is usually - * even more convenient. - * @param clazz the Class whose package will be used as the base - * @param resourceName the resource name to append. A leading slash is optional. - * @return the built-up resource path - * @see java.lang.ClassLoader#getResource - * @see java.lang.Class#getResource - */ - public static String addResourcePathToPackagePath(final Class clazz, final String resourceName) { - Assert.notNull(resourceName, "Resource name must not be null"); - if (!resourceName.startsWith("/")) { - return classPackageAsResourcePath(clazz) + "/" + resourceName; - } - return classPackageAsResourcePath(clazz) + resourceName; - } - - /** - * Given an input class object, return a string which consists of the - * class's package name as a pathname, i.e., all dots ('.') are replaced by - * slashes ('/'). Neither a leading nor trailing slash is added. The result - * could be concatenated with a slash and the name of a resource and fed - * directly to ClassLoader.getResource(). For it to be fed to - * Class.getResource instead, a leading slash would also have - * to be prepended to the returned value. - * @param clazz the input class. A null value or the default - * (empty) package will result in an empty string ("") being returned. - * @return a path which represents the package name - * @see ClassLoader#getResource - * @see Class#getResource - */ - public static String classPackageAsResourcePath(final Class clazz) { - if (clazz == null) { - return ""; - } - String className = clazz.getName(); - int packageEndIndex = className.lastIndexOf('.'); - if (packageEndIndex == -1) { - return ""; - } - String packageName = className.substring(0, packageEndIndex); - return packageName.replace('.', '/'); - } - - /** - * Build a String that consists of the names of the classes/interfaces - * in the given array. - *

Basically like AbstractCollection.toString(), but stripping - * the "class "/"interface " prefix before every class name. - * @param classes a Collection of Class objects (may be null) - * @return a String of form "[com.foo.Bar, com.foo.Baz]" - * @see java.util.AbstractCollection#toString() - */ - public static String classNamesToString(final Class... classes) { - return classNamesToString(Arrays.asList(classes)); - } - - /** - * Build a String that consists of the names of the classes/interfaces - * in the given collection. - *

Basically like AbstractCollection.toString(), but stripping - * the "class "/"interface " prefix before every class name. - * @param classes a Collection of Class objects (may be null) - * @return a String of form "[com.foo.Bar, com.foo.Baz]" - * @see java.util.AbstractCollection#toString() - */ - public static String classNamesToString(final Collection> classes) { - if (CollectionUtils.isEmpty(classes)) { - return "[]"; - } - StringBuilder sb = new StringBuilder("["); - for (Iterator> it = classes.iterator(); it.hasNext();) { - Class clazz = it.next(); - sb.append(clazz.getName()); - if (it.hasNext()) { - sb.append(", "); - } - } - sb.append("]"); - return sb.toString(); - } - - /** - * Return all interfaces that the given instance implements as array, - * including ones implemented by superclasses. - * @param instance the instance to analyze for interfaces - * @return all interfaces that the given instance implements as array - */ - public static Class[] getAllInterfaces(final Object instance) { - Assert.notNull(instance, "Instance must not be null"); - return getAllInterfacesForClass(instance.getClass()); - } - - /** - * Return all interfaces that the given class implements as array, - * including ones implemented by superclasses. - *

If the class itself is an interface, it gets returned as sole interface. - * @param clazz the class to analyze for interfaces - * @return all interfaces that the given object implements as array - */ - public static Class[] getAllInterfacesForClass(final Class clazz) { - return getAllInterfacesForClass(clazz, null); - } - - /** - * Return all interfaces that the given class implements as array, - * including ones implemented by superclasses. - *

If the class itself is an interface, it gets returned as sole interface. - * @param clazz the class to analyze for interfaces - * @param classLoader the ClassLoader that the interfaces need to be visible in - * (may be null when accepting all declared interfaces) - * @return all interfaces that the given object implements as array - */ - public static Class[] getAllInterfacesForClass(final Class clazz, final ClassLoader classLoader) { - Set ifcs = getAllInterfacesForClassAsSet(clazz, classLoader); - return ifcs.toArray(new Class[ifcs.size()]); - } - - /** - * Return all interfaces that the given instance implements as Set, - * including ones implemented by superclasses. - * @param instance the instance to analyze for interfaces - * @return all interfaces that the given instance implements as Set - */ - public static Set getAllInterfacesAsSet(final Object instance) { - Assert.notNull(instance, "Instance must not be null"); - return getAllInterfacesForClassAsSet(instance.getClass()); - } - - /** - * Return all interfaces that the given class implements as Set, - * including ones implemented by superclasses. - *

If the class itself is an interface, it gets returned as sole interface. - * @param clazz the class to analyze for interfaces - * @return all interfaces that the given object implements as Set - */ - public static Set getAllInterfacesForClassAsSet(final Class clazz) { - return getAllInterfacesForClassAsSet(clazz, null); - } - - /** - * Return all interfaces that the given class implements as Set, - * including ones implemented by superclasses. - *

If the class itself is an interface, it gets returned as sole interface. - * @param clazz the class to analyze for interfaces - * @param classLoader the ClassLoader that the interfaces need to be visible in - * (may be null when accepting all declared interfaces) - * @return all interfaces that the given object implements as Set - */ - public static Set getAllInterfacesForClassAsSet(Class clazz, final ClassLoader classLoader) { - Assert.notNull(clazz, "Class must not be null"); - if (clazz.isInterface() && isVisible(clazz, classLoader)) { - return Collections.singleton(clazz); - } - Set interfaces = new LinkedHashSet(); - while (clazz != null) { - Class[] ifcs = clazz.getInterfaces(); - for (Class ifc : ifcs) { - interfaces.addAll(getAllInterfacesForClassAsSet(ifc, classLoader)); - } - clazz = clazz.getSuperclass(); - } - return interfaces; - } - - /** - * Create a composite interface Class for the given interfaces, - * implementing the given interfaces in one single Class. - *

This implementation builds a JDK proxy class for the given interfaces. - * @param interfaces the interfaces to merge - * @param classLoader the ClassLoader to create the composite Class in - * @return the merged interface as Class - * @see java.lang.reflect.Proxy#getProxyClass - */ - public static Class createCompositeInterface(final Class[] interfaces, final ClassLoader classLoader) { - Assert.notEmpty(interfaces, "Interfaces must not be empty"); - Assert.notNull(classLoader, "ClassLoader must not be null"); - return Proxy.getProxyClass(classLoader, interfaces); - } - - /** - * Check whether the given class is visible in the given ClassLoader. - * @param clazz the class to check (typically an interface) - * @param classLoader the ClassLoader to check against (may be null, - * in which case this method will always return true) - */ - public static boolean isVisible(final Class clazz, final ClassLoader classLoader) { - if (classLoader == null) { - return true; - } - try { - Class actualClass = classLoader.loadClass(clazz.getName()); - return (clazz == actualClass); - // Else: different interface class found... - } catch (ClassNotFoundException ex) { - // No interface class found... - return false; - } - } -} \ No newline at end of file diff --git a/src/main/java/org/springframework/shell/support/util/CollectionUtils.java b/src/main/java/org/springframework/shell/support/util/CollectionUtils.java deleted file mode 100644 index 555b9028..00000000 --- a/src/main/java/org/springframework/shell/support/util/CollectionUtils.java +++ /dev/null @@ -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 true if the supplied Collection is null - * or empty. Otherwise, return false. - * - * @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 true if the supplied Map is null - * or empty. Otherwise, return false. - * - * @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. - *

A null 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 null) - * @param collection the target Collection to merge the array into - */ - public static void mergeArrayIntoCollection(final Object array, final Collection 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. - *

Uses Properties.propertyNames() to even catch - * default properties linked into the original Properties instance. - * - * @param props the Properties instance to merge (may be null) - * @param map the target Map to merge the properties into - */ - public static void mergePropertiesIntoMap(final Properties props, final Map 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 true if found, false 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 true if found, false 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. - *

Enforces the given instance to be present, rather than returning - * true for an equal element as well. - * - * @param collection the Collection to check - * @param element the element to look for - * @return true if found, false 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 true if any element in 'candidates' is - * contained in 'source'; otherwise returns false. - * - * @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 'candidates' that is contained in - * 'source'. If no element in 'candidates' is present in - * 'source' returns null. 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 null 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 null if none or more than one such value found - */ - @SuppressWarnings("unchecked") - public static T findValueOfType(final Collection collection, final Class 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 null 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 true if the collection contains a single reference or - * multiple references to the same instance, false 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 the type of object being filtered - * @param unfiltered the iterable to filter; can be null - * @param filter the filter to apply; can be null for none - * @return a non-null list - */ - public static List filter(final Iterable unfiltered, final Filter filter) { - final List filtered = new ArrayList(); - 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 the type of item in the collection being updated - * @param newItems the items being added; can be null for none - * @param existingItems the items being added to; must be modifiable - * @return true 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 boolean addAll(final Collection newItems, final Collection 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 the type of element in the collection - * @param collection the collection to populate (can be null) - * @param items the items with which to populate the collection (can be - * null or empty for none) - * @return the given collection (useful if it was anonymous) - */ - public static Collection populate(final Collection collection, final Collection items) { - if (collection != null) { - collection.clear(); - if (items != null) { - collection.addAll(items); - } - } - return collection; - } - - /** - * Returns the first element of the given collection - * - * @param - * @param collection - * @return null if the first element is null or - * the collection is null or empty - */ - public static T firstElementOf(final Collection collection) { - if (isEmpty(collection)) { - return null; - } - return collection.iterator().next(); - } - - /** - * Constructor is private to prevent instantiation - * - * @since 1.2.0 - */ - private CollectionUtils() {} -} \ No newline at end of file diff --git a/src/main/java/org/springframework/shell/support/util/DomUtils.java b/src/main/java/org/springframework/shell/support/util/DomUtils.java deleted file mode 100644 index e9847436..00000000 --- a/src/main/java/org/springframework/shell/support/util/DomUtils.java +++ /dev/null @@ -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 getElementsByTagName method). - * - * @param element the DOM element to analyze - * @param childElementNames the child element names to look for - * @return a List of child org.w3c.dom.Element instances - * @see org.w3c.dom.Element - * @see org.w3c.dom.Element#getElementsByTagName - */ - public static List 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 childEleNameList = Arrays.asList(childElementNames); - NodeList nl = element.getChildNodes(); - List childEles = new ArrayList(); - 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 getElementsByTagName method). - * - * @param element the DOM element to analyze - * @param childEleName the child element name to look for - * @return a List of child org.w3c.dom.Element instances - * @see org.w3c.dom.Element - * @see org.w3c.dom.Element#getElementsByTagName - */ - public static List 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 org.w3c.dom.Element instance, - * or null 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 null 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. - *

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 true if either - * {@link Node#getLocalName} or {@link Node#getNodeName} equals desiredName, - * otherwise returns false. - * - * @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 null - * @param defaultValue the value to return if the node is null - * @return the given default value if the node is null - * @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 null) - * @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 null 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 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() {} -} diff --git a/src/main/java/org/springframework/shell/support/util/ExceptionUtils.java b/src/main/java/org/springframework/shell/support/util/ExceptionUtils.java index 99f7f9aa..065b0e9b 100644 --- a/src/main/java/org/springframework/shell/support/util/ExceptionUtils.java +++ b/src/main/java/org/springframework/shell/support/util/ExceptionUtils.java @@ -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. * diff --git a/src/main/java/org/springframework/shell/support/util/FileCopyUtils.java b/src/main/java/org/springframework/shell/support/util/FileCopyUtils.java deleted file mode 100644 index bdbeb554..00000000 --- a/src/main/java/org/springframework/shell/support/util/FileCopyUtils.java +++ /dev/null @@ -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. - * - *

- * 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. - *

- * 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() {} -} diff --git a/src/main/java/org/springframework/shell/support/util/FileUtils.java b/src/main/java/org/springframework/shell/support/util/FileUtils.java index 13188a2a..fb6a0919 100644 --- a/src/main/java/org/springframework/shell/support/util/FileUtils.java +++ b/src/main/java/org/springframework/shell/support/util/FileUtils.java @@ -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 null) * @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 null) * @return the path, modified as above, or null if null 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 null) * @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() { diff --git a/src/main/java/org/springframework/shell/support/util/Filter.java b/src/main/java/org/springframework/shell/support/util/Filter.java deleted file mode 100644 index 667ffb9d..00000000 --- a/src/main/java/org/springframework/shell/support/util/Filter.java +++ /dev/null @@ -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 the type of object to be filtered - */ -public interface Filter { - - /** - * Indicates whether to include the given instance in the filtered results - * - * @param type the type to evaluate; can be null - * @return false to exclude the given type - */ - boolean include(T instance); -} \ No newline at end of file diff --git a/src/main/java/org/springframework/shell/support/util/HexUtils.java b/src/main/java/org/springframework/shell/support/util/HexUtils.java deleted file mode 100644 index 331d1613..00000000 --- a/src/main/java/org/springframework/shell/support/util/HexUtils.java +++ /dev/null @@ -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. - * - *

- * 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; - } -} diff --git a/src/main/java/org/springframework/shell/support/util/NumberUtils.java b/src/main/java/org/springframework/shell/support/util/NumberUtils.java deleted file mode 100644 index 83f76863..00000000 --- a/src/main/java/org/springframework/shell/support/util/NumberUtils.java +++ /dev/null @@ -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 null) - * @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 null) - * @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 null elements - * - * @param findMinimum false to get the maximum - * @param numbers can be null, empty, or contain null - * elements - * @return null if the array is null, empty, or - * all its elements are null - */ - 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 null) - * @return null if the given number was null - */ - 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() {} -} diff --git a/src/main/java/org/springframework/shell/support/util/ObjectUtils.java b/src/main/java/org/springframework/shell/support/util/ObjectUtils.java deleted file mode 100644 index 42ec5365..00000000 --- a/src/main/java/org/springframework/shell/support/util/ObjectUtils.java +++ /dev/null @@ -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, null - * 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 null, - * in which case the return value will always be false) - * @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 null) - * @param obj the Object to append - * @return the new array (of the same component type; never null) - */ - 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). - *

A null source value will be converted to an - * empty Object array. - * - * @param source the (potentially primitive) array - * @return the corresponding object array (never null) - * @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 true - * if both are null or false if only one is - * null. - *

Compares arrays with Arrays.equals, 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 - * {@link Object#hashCode()}. If the object is an array, - * this method will delegate to any of the nullSafeHashCode - * methods for arrays in this class. If the object is null, - * 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 null) - * @return 0 if the array is null - */ - 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 null - * @return 0 if array is null - */ - 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 null - * @return 0 if array is null - */ - 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 null - * @return 0 if array is null - */ - 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 null - * @return 0 if array is null - */ - 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 null - * @return 0 if array is null - */ - 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 null - * @return 0 if array is null - */ - 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 null - * @return 0 if array is null - */ - 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 null - * @return 0 if array is null - */ - 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 {@link Double#hashCode()}. - * - * @see Double#hashCode() - */ - public static int hashCode(final double dbl) { - long bits = Double.doubleToLongBits(dbl); - return hashCode(bits); - } - - /** - * Return the same value as {@link Float#hashCode()}. - * - * @see Float#hashCode() - */ - public static int hashCode(final float flt) { - return Float.floatToIntBits(flt); - } - - /** - * Return the same value as {@link Long#hashCode()}. - * - * @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 null) - * @return the object's identity as String representation, - * or an empty String if the object was null - */ - 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 obj is - * not null; otherwise returns an empty String. - *

Differs from {@link #nullSafeToString(Object)} in that it returns - * an empty String rather than "null" for a null value. - * - * @param obj the object to build a display String for - * @return a display String representation of obj - * @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. - *

Returns "null" if obj is null. - * - * @param obj the object to introspect (may be null) - * @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. - *

Builds a String representation of the contents in case of an array. - * Returns "null" if obj is null. - * - * @param obj the object to build a String representation for - * @return a String representation of obj - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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. - *

The String representation consists of a list of the array's elements, - * enclosed in curly braces ("{}"). Adjacent elements are separated - * by the characters ", " (a comma followed by a space). Returns - * "null" if array is null. - * - * @param array the array to build a String representation for - * @return a String representation of array - */ - 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 null equivalent to - * null and null "less than" any - * non-null instance. Two non-null instances are - * compared using the first one's {@link Comparable#compareTo(Object)} - * method. - * - * @param the type of objects being compared - * @param one the first object being compared (can be null) - * @param other the second object being compared (can be null) - * @return see {@link Comparable#compareTo(Object)} - * @since 1.2.0 - */ - public static int nullSafeComparison(final Comparable 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 - * null, the given default string - * - * @param object the object to represent as a String (can be null) - * @param defaultValue the value to return if the given object is null (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 null, otherwise the given - * default value - * - * @param the type of object being defaulted - * @param object the object to check (can be null) - * @param defaultValue the default value (can be null) - * @return null iff both values are null - * @since 1.2.0 - */ - public static T defaultIfNull(final T object, final T defaultValue) { - if (object == null) { - return defaultValue; - } - return object; - } - - /** - * Constructor is private to prevent instantiation - */ - private ObjectUtils() {} -} diff --git a/src/main/java/org/springframework/shell/support/util/OsUtils.java b/src/main/java/org/springframework/shell/support/util/OsUtils.java index e757025a..f374f5d3 100644 --- a/src/main/java/org/springframework/shell/support/util/OsUtils.java +++ b/src/main/java/org/springframework/shell/support/util/OsUtils.java @@ -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() { diff --git a/src/main/java/org/springframework/shell/support/util/Pair.java b/src/main/java/org/springframework/shell/support/util/Pair.java deleted file mode 100644 index 6a5d2cfd..00000000 --- a/src/main/java/org/springframework/shell/support/util/Pair.java +++ /dev/null @@ -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 the key type - * @param the value type - */ -public class Pair { - - // Fields - private final K key; - private final V value; - - /** - * Constructor - * - * @param key can be null - * @param value can be null - */ - public Pair(final K key, final V value) { - this.key = key; - this.value = value; - } - - /** - * Returns the key - * - * @return null if it is - */ - public K getKey() { - return key; - } - - /** - * Returns the value - * - * @return null 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(); - } -} diff --git a/src/main/java/org/springframework/shell/support/util/PairList.java b/src/main/java/org/springframework/shell/support/util/PairList.java deleted file mode 100644 index f9491f8f..00000000 --- a/src/main/java/org/springframework/shell/support/util/PairList.java +++ /dev/null @@ -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 null keys. - * - * @author Andrew Swan - * @since 1.2.0 - * @param the type of key - * @param the type of value - */ -public class PairList extends ArrayList> { - - // For serialisation - private static final long serialVersionUID = 5990417235907246300L; - - /** - * Returns the given array of pairs as a modifiable list - * - * @param the type of key - * @param the type of value - * @param pairs the pairs to put in a list - * @return a non-null list - */ - public PairList(final Pair... 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 keys, final List 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-null list - */ - public List getKeys() { - final List keys = new ArrayList(); - for (final Pair pair : this) { - keys.add(pair.getKey()); - } - return keys; - } - - /** - * Returns the values of each {@link Pair} in this list - * - * @return a non-null modifiable copy of this list - */ - public List getValues() { - final List values = new ArrayList(); - for (final Pair 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 null - * @param value the value to add; can be null - * @return true (as specified by Collection.add(E)) - */ - public boolean add(final K key, final V value) { - return add(new Pair(key, value)); - } - - @SuppressWarnings("unchecked") - @Override - public Pair[] toArray() { - return super.toArray(new Pair[size()]); - } -} diff --git a/src/main/java/org/springframework/shell/support/util/PathMatcher.java b/src/main/java/org/springframework/shell/support/util/PathMatcher.java deleted file mode 100644 index 0b5443a7..00000000 --- a/src/main/java/org/springframework/shell/support/util/PathMatcher.java +++ /dev/null @@ -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 String-based path matching. - * - *

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 path represent a pattern that can be matched - * by an implementation of this interface? - *

If the return value is false, 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 true if the given path represents a pattern - */ - boolean isPattern(String path); - - /** - * Match the given path against the given pattern, - * according to this PathMatcher's matching strategy. - * @param pattern the pattern to match against - * @param path the path String to test - * @return true if the supplied path matched, - * false if it didn't - */ - boolean match(String pattern, String path); - - /** - * Match the given path against the corresponding part of the given - * pattern, according to this PathMatcher's matching strategy. - *

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 true if the supplied path matched, - * false if it didn't - */ - boolean matchStart(String pattern, String path); - - /** - * Given a pattern and a full path, determine the pattern-mapped part. - *

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. - *

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. - *

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 pattern 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 path - * (never null) - */ - 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 '}'). - * - *

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 extractUriTemplateVariables(String pattern, String path); -} diff --git a/src/main/java/org/springframework/shell/support/util/ReflectionUtils.java b/src/main/java/org/springframework/shell/support/util/ReflectionUtils.java deleted file mode 100644 index 247ea70f..00000000 --- a/src/main/java/org/springframework/shell/support/util/ReflectionUtils.java +++ /dev/null @@ -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. - * - *

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 name. 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 null 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 name 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 null if type is specified) - * @param type the type of the field (may be null if name is specified) - * @return the corresponding Field object, or null 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 - * value. In accordance with - * {@link Field#set(Object, Object)} semantics, the new value is - * automatically unwrapped if the underlying field has a primitive type. - *

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 null - */ - 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. - *

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 Object. - *

Returns null 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 null 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 Object. - *

Returns null 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 null to indicate any signature) - * @return the Method object, or null 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 null when - * invoking a static {@link Method}. - *

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 null - * when invoking a static {@link Method}. - *

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 null) - * @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 null) - * @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. - *

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. - *

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 - * target exception of an {@link InvocationTargetException}. - * Should only be called if no checked exception is expected to be thrown by - * the target method. - *

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 - * target exception of an {@link InvocationTargetException}. - * Should only be called if no checked exception is expected to be thrown by - * the target method. - *

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 true if the exception can be thrown as-is; - * false 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 setAccessible(true) 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 setAccessible(true) 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 setAccessible(true) 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. - *

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. - *

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 methods = new ArrayList(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())); - } - }; -} diff --git a/src/main/java/org/springframework/shell/support/util/StringUtils.java b/src/main/java/org/springframework/shell/support/util/StringUtils.java deleted file mode 100644 index bbdbb511..00000000 --- a/src/main/java/org/springframework/shell/support/util/StringUtils.java +++ /dev/null @@ -1,1448 +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.Collections; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeSet; - -/** - * Miscellaneous {@link String} utility methods. - * - *

Mainly for internal use within the framework; consider - * Jakarta's Commons Lang - * for a more comprehensive suite of String utilities. - * - *

This class delivers some simple functionality that should really - * be provided by the core Java String and {@link StringBuilder} - * classes, such as the ability to {@link #replace} all occurrences of a given - * substring in a target string. It also provides easy-to-use methods to convert - * between delimited strings, such as CSV strings, and collections and arrays. - * - * @author Rod Johnson - * @author Juergen Hoeller - * @author Keith Donald - * @author Rob Harrop - * @author Rick Evans - * @author Arjen Poutsma - * @since 16 April 2001 - * @see org.apache.commons.lang.StringUtils - */ -public final class StringUtils { - - // Constants - private static final String FOLDER_SEPARATOR = "/"; - private static final String WINDOWS_FOLDER_SEPARATOR = "\\"; - private static final String TOP_PATH = ".."; - private static final String CURRENT_PATH = "."; - private static final char EXTENSION_SEPARATOR = '.'; - - /** - * The platform-specific line separator. - * - * @since 1.2.0 - */ - public static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - //--------------------------------------------------------------------- - // General convenience methods for working with Strings - //--------------------------------------------------------------------- - - /** - * Check that the given CharSequence is neither null nor of length 0. - * Note: Will return true for a CharSequence that purely consists of whitespace. - *

-	 * StringUtils.hasLength(null) = false
-	 * StringUtils.hasLength("") = false
-	 * StringUtils.hasLength(" ") = true
-	 * StringUtils.hasLength("Hello") = true
-	 * 
- * @param str the CharSequence to check (may be null) - * @return true if the CharSequence is not null and has length - * @see #hasText(String) - */ - public static boolean hasLength(final CharSequence str) { - return (str != null && str.length() > 0); - } - - /** - * Check that the given String is neither null nor of length 0. - * Note: Will return true for a String that purely consists of whitespace. - * @param str the String to check (may be null) - * @return true if the String is not null and has length - * @see #hasLength(CharSequence) - */ - public static boolean hasLength(final String str) { - return hasLength((CharSequence) str); - } - - /** - * Check whether the given CharSequence has actual text. - * More specifically, returns true if the string not null, - * its length is greater than 0, and it contains at least one non-whitespace character. - *

-	 * StringUtils.hasText(null) = false
-	 * StringUtils.hasText("") = false
-	 * StringUtils.hasText(" ") = false
-	 * StringUtils.hasText("12345") = true
-	 * StringUtils.hasText(" 12345 ") = true
-	 * 
- * @param str the CharSequence to check (may be null) - * @return true if the CharSequence is not null, - * its length is greater than 0, and it does not contain whitespace only - * @see java.lang.Character#isWhitespace - */ - public static boolean hasText(final CharSequence str) { - if (!hasLength(str)) { - return false; - } - int strLen = str.length(); - for (int i = 0; i < strLen; i++) { - if (!Character.isWhitespace(str.charAt(i))) { - return true; - } - } - return false; - } - - /** - * Check whether the given String has actual text. - * More specifically, returns true if the string not null, - * its length is greater than 0, and it contains at least one non-whitespace character. - * @param str the String to check (may be null) - * @return true if the String is not null, its length is - * greater than 0, and it does not contain whitespace only - * @see #hasText(CharSequence) - */ - public static boolean hasText(final String str) { - return hasText((CharSequence) str); - } - - /** - * Indicates whether the given substring occurs within the given string. - * Inspired by the eponymous method in commons-lang. - *
-		StringUtils.contains(null, *)     = false
-		StringUtils.contains(*, null)     = false
-		StringUtils.contains("", "")      = true
-		StringUtils.contains("abc", "")   = true
-		StringUtils.contains("abc", "a")  = true
-		StringUtils.contains("abc", "z")  = false
- * - * @param str the string to look within (can be null) - * @param substr the string to look for (can be null) - * @return see above - * @since 1.2.0 - */ - public static boolean contains(final String str, final String substr) { - if (str == null || substr == null) { - return false; - } - return str.contains(substr); - } - - /** - * Check whether the given CharSequence contains any whitespace characters. - * @param str the CharSequence to check (may be null) - * @return true if the CharSequence is not empty and - * contains at least 1 whitespace character - * @see java.lang.Character#isWhitespace - */ - public static boolean containsWhitespace(final CharSequence str) { - if (!hasLength(str)) { - return false; - } - int strLen = str.length(); - for (int i = 0, n = strLen; i < n; i++) { - if (Character.isWhitespace(str.charAt(i))) { - return true; - } - } - return false; - } - - /** - * Check whether the given String contains any whitespace characters. - * @param str the String to check (may be null) - * @return true if the String is not empty and - * contains at least 1 whitespace character - * @see #containsWhitespace(CharSequence) - */ - public static boolean containsWhitespace(final String str) { - return containsWhitespace((CharSequence) str); - } - - /** - * Trim leading and trailing whitespace from the given String. - * @param str the String to check - * @return the trimmed String - * @see java.lang.Character#isWhitespace - */ - public static String trimWhitespace(final String str) { - if (!hasLength(str)) { - return str; - } - StringBuilder sb = new StringBuilder(str); - while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) { - sb.deleteCharAt(0); - } - while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) { - sb.deleteCharAt(sb.length() - 1); - } - return sb.toString(); - } - - /** - * Trim all whitespace from the given String: - * leading, trailing, and inbetween characters. - * @param str the String to check - * @return the trimmed String - * @see java.lang.Character#isWhitespace - */ - public static String trimAllWhitespace(final String str) { - if (!hasLength(str)) { - return str; - } - StringBuilder sb = new StringBuilder(str); - int index = 0; - while (sb.length() > index) { - if (Character.isWhitespace(sb.charAt(index))) { - sb.deleteCharAt(index); - } - else { - index++; - } - } - return sb.toString(); - } - - /** - * Trim leading whitespace from the given String. - * @param str the String to check - * @return the trimmed String - * @see java.lang.Character#isWhitespace - */ - public static String trimLeadingWhitespace(final String str) { - if (!hasLength(str)) { - return str; - } - StringBuilder sb = new StringBuilder(str); - while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) { - sb.deleteCharAt(0); - } - return sb.toString(); - } - - /** - * Trim trailing whitespace from the given String. - * @param str the String to check - * @return the trimmed String - * @see java.lang.Character#isWhitespace - */ - public static String trimTrailingWhitespace(final String str) { - if (!hasLength(str)) { - return str; - } - StringBuilder sb = new StringBuilder(str); - while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) { - sb.deleteCharAt(sb.length() - 1); - } - return sb.toString(); - } - - /** - * Trim all occurences of the supplied leading character from the given String. - * @param str the String to check - * @param leadingCharacter the leading character to be trimmed - * @return the trimmed String - */ - public static String trimLeadingCharacter(final String str, final char leadingCharacter) { - if (!hasLength(str)) { - return str; - } - StringBuilder sb = new StringBuilder(str); - while (sb.length() > 0 && sb.charAt(0) == leadingCharacter) { - sb.deleteCharAt(0); - } - return sb.toString(); - } - - /** - * Trim all occurences of the supplied trailing character from the given String. - * @param str the String to check - * @param trailingCharacter the trailing character to be trimmed - * @return the trimmed String - */ - public static String trimTrailingCharacter(final String str, final char trailingCharacter) { - if (!hasLength(str)) { - return str; - } - StringBuilder sb = new StringBuilder(str); - while (sb.length() > 0 && sb.charAt(sb.length() - 1) == trailingCharacter) { - sb.deleteCharAt(sb.length() - 1); - } - return sb.toString(); - } - - /** - * Test if the given String starts with the specified prefix, - * ignoring upper/lower case. - * @param str the String to check - * @param prefix the prefix to look for - * @see java.lang.String#startsWith - */ - public static boolean startsWithIgnoreCase(final String str, final String prefix) { - if (str == null || prefix == null) { - return false; - } - if (str.startsWith(prefix)) { - return true; - } - if (str.length() < prefix.length()) { - return false; - } - String lcStr = str.substring(0, prefix.length()).toLowerCase(); - String lcPrefix = prefix.toLowerCase(); - return lcStr.equals(lcPrefix); - } - - /** - * Test if the given String ends with the specified suffix, - * ignoring upper/lower case. - * @param str the String to check - * @param suffix the suffix to look for - * @see java.lang.String#endsWith - */ - public static boolean endsWithIgnoreCase(final String str, final String suffix) { - if (str == null || suffix == null) { - return false; - } - if (str.endsWith(suffix)) { - return true; - } - if (str.length() < suffix.length()) { - return false; - } - - String lcStr = str.substring(str.length() - suffix.length()).toLowerCase(); - String lcSuffix = suffix.toLowerCase(); - return lcStr.equals(lcSuffix); - } - - /** - * Test whether the given string matches the given substring - * at the given index. - * @param str the original string (or StringBuilder) - * @param index the index in the original string to start matching against - * @param substring the substring to match at the given index - */ - public static boolean substringMatch(final CharSequence str, final int index, final CharSequence substring) { - for (int j = 0, n = substring.length(); j < n; j++) { - int i = index + j; - if (i >= str.length() || str.charAt(i) != substring.charAt(j)) { - return false; - } - } - return true; - } - - /** - * Count the occurrences of the substring in string s. - * @param str string to search in. Return 0 if this is null. - * @param sub string to search for. Return 0 if this is null. - */ - public static int countOccurrencesOf(final String str, final String sub) { - if (!hasLength(str) || !hasLength(sub)) { - return 0; - } - int count = 0, pos = 0, idx = 0; - while ((idx = str.indexOf(sub, pos)) != -1) { - ++count; - pos = idx + sub.length(); - } - return count; - } - - /** - * Returns the given string repeated the given number of times - * - * @param str the string to repeat (can be null or empty) - * @param times the number of times to repeat it - * @return null if null is given - */ - public static String repeat(final String str, final int times) { - if (!hasLength(str)) { - return str; - } - final StringBuilder sb = new StringBuilder(str.length() * times); - for (int i = 0; i < times; i++) { - sb.append(str); - } - return sb.toString(); - } - - /** - * Replaces all occurrences of one string within another. - * - * @param original the string to modify (can be zero length to do nothing) - * @param toReplace the string to replace (can be blank to do nothing) - * @param replacement the string to replace it with (can be null to do nothing) - * @return the original string, modified as necessary - */ - public static String replace(final String original, final String toReplace, final String replacement) { - String result = original; - String previousResult; - do { - previousResult = result; - result = replaceFirst(previousResult, toReplace, replacement); - } while (!equals(previousResult, result)); - return result; - } - - /** - * Delete all occurrences of the given substring. - * @param inString the original String - * @param pattern the pattern to delete all occurrences of - * @return the resulting String - */ - public static String delete(final String inString, final String pattern) { - return replace(inString, pattern, ""); - } - - /** - * Delete any character in a given String. - * @param inString the original String - * @param charsToDelete a set of characters to delete. - * E.g. "az\n" will delete 'a's, 'z's and new lines. - * @return the resulting String - */ - public static String deleteAny(final String inString, final String charsToDelete) { - if (!hasLength(inString) || !hasLength(charsToDelete)) { - return inString; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0, n = inString.length(); i < n; i++) { - char c = inString.charAt(i); - if (charsToDelete.indexOf(c) == -1) { - sb.append(c); - } - } - return sb.toString(); - } - - //--------------------------------------------------------------------- - // Convenience methods for working with formatted Strings - //--------------------------------------------------------------------- - - /** - * Quote the given String with single quotes. - * @param str the input String (e.g. "myString") - * @return the quoted String (e.g. "'myString'"), - * or null if the input was null - */ - public static String quote(final String str) { - return (str != null ? "'" + str + "'" : null); - } - - /** - * Turn the given Object into a String with single quotes - * if it is a String; keeping the Object as-is else. - * @param obj the input Object (e.g. "myString") - * @return the quoted String (e.g. "'myString'"), - * or the input object as-is if not a String - */ - public static Object quoteIfString(final Object obj) { - return (obj instanceof String ? quote((String) obj) : obj); - } - - /** - * Unqualify a string qualified by a '.' dot character. For example, - * "this.name.is.qualified", returns "qualified". - * @param qualifiedName the qualified name - */ - public static String unqualify(final String qualifiedName) { - return unqualify(qualifiedName, '.'); - } - - /** - * Unqualify a string qualified by a separator character. For example, - * "this:name:is:qualified" returns "qualified" if using a ':' separator. - * @param qualifiedName the qualified name - * @param separator the separator - */ - public static String unqualify(final String qualifiedName, final char separator) { - return qualifiedName.substring(qualifiedName.lastIndexOf(separator) + 1); - } - - /** - * Capitalize a String, changing the first letter to - * upper case as per {@link Character#toUpperCase(char)}. - * No other letters are changed. - * @param str the String to capitalize, may be null - * @return the capitalized String, null if null - */ - public static String capitalize(final String str) { - return changeFirstCharacterCase(str, true); - } - - /** - * Uncapitalize a String, changing the first letter to - * lower case as per {@link Character#toLowerCase(char)}. - * No other letters are changed. - * @param str the String to uncapitalize, may be null - * @return the uncapitalized String, null if null - */ - public static String uncapitalize(final String str) { - return changeFirstCharacterCase(str, false); - } - - private static String changeFirstCharacterCase(final String str, final boolean capitalize) { - if (!hasText(str)) { - return str; - } - StringBuilder sb = new StringBuilder(str.length()); - if (capitalize) { - sb.append(Character.toUpperCase(str.charAt(0))); - } else { - sb.append(Character.toLowerCase(str.charAt(0))); - } - sb.append(str.substring(1)); - return sb.toString(); - } - - /** - * Extract the filename from the given path, - * e.g. "mypath/myfile.txt" -> "myfile.txt". - * @param path the file path (may be null) - * @return the extracted filename, or null if none - */ - public static String getFilename(final String path) { - if (path == null) { - return null; - } - int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); - return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path); - } - - /** - * Extract the filename extension from the given path, - * e.g. "mypath/myfile.txt" -> "txt". - * @param path the file path (may be null) - * @return the extracted filename extension, or null if none - */ - public static String getFilenameExtension(final String path) { - if (path == null) { - return null; - } - int sepIndex = path.lastIndexOf(EXTENSION_SEPARATOR); - return (sepIndex != -1 ? path.substring(sepIndex + 1) : null); - } - - /** - * Strip the filename extension from the given path, - * e.g. "mypath/myfile.txt" -> "mypath/myfile". - * @param path the file path (may be null) - * @return the path with stripped filename extension, - * or null if none - */ - public static String stripFilenameExtension(final String path) { - if (path == null) { - return null; - } - int sepIndex = path.lastIndexOf(EXTENSION_SEPARATOR); - return (sepIndex != -1 ? path.substring(0, sepIndex) : path); - } - - /** - * Apply the given relative path to the given path, - * assuming standard Java folder separation (i.e. "/" separators); - * @param path the path to start from (usually a full file path) - * @param relativePath the relative path to apply - * (relative to the full file path above) - * @return the full file path that results from applying the relative path - */ - public static String applyRelativePath(final String path, final String relativePath) { - int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR); - if (separatorIndex != -1) { - String newPath = path.substring(0, separatorIndex); - if (!relativePath.startsWith(FOLDER_SEPARATOR)) { - newPath += FOLDER_SEPARATOR; - } - return newPath + relativePath; - } - return relativePath; - } - - /** - * Normalize the path by suppressing sequences like "path/.." and - * inner simple dots. - *

The result is convenient for path comparison. For other uses, - * notice that Windows separators ("\") are replaced by simple slashes. - * @param path the original path - * @return the normalized path - */ - public static String cleanPath(final String path) { - if (path == null) { - return null; - } - String pathToUse = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR); - - // Strip prefix from path to analyze, to not treat it as part of the - // first path element. This is necessary to correctly parse paths like - // "file:core/../core/io/Resource.class", where the ".." should just - // strip the first "core" directory while keeping the "file:" prefix. - int prefixIndex = pathToUse.indexOf(":"); - String prefix = ""; - if (prefixIndex != -1) { - prefix = pathToUse.substring(0, prefixIndex + 1); - pathToUse = pathToUse.substring(prefixIndex + 1); - } - if (pathToUse.startsWith(FOLDER_SEPARATOR)) { - prefix = prefix + FOLDER_SEPARATOR; - pathToUse = pathToUse.substring(1); - } - - String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR); - List pathElements = new ArrayList(); - int tops = 0; - - for (int i = pathArray.length - 1; i >= 0; i--) { - String element = pathArray[i]; - if (CURRENT_PATH.equals(element)) { - // Points to current directory - drop it. - } else if (TOP_PATH.equals(element)) { - // Registering top path found. - tops++; - } else { - if (tops > 0) { - // Merging path element with element corresponding to top path. - tops--; - } - else { - // Normal path element found. - pathElements.add(0, element); - } - } - } - - // Remaining top paths need to be retained. - for (int i = 0; i < tops; i++) { - pathElements.add(0, TOP_PATH); - } - - return prefix + collectionToDelimitedString(pathElements, FOLDER_SEPARATOR); - } - - /** - * Compare two paths after normalization of them. - * @param path1 first path for comparison - * @param path2 second path for comparison - * @return whether the two paths are equivalent after normalization - */ - public static boolean pathEquals(final String path1, final String path2) { - return cleanPath(path1).equals(cleanPath(path2)); - } - - /** - * Parse the given localeString into a {@link Locale}. - *

This is the inverse operation of {@link Locale#toString Locale's toString}. - * @param localeString the locale string, following Locale's - * toString() format ("en", "en_UK", etc); - * also accepts spaces as separators, as an alternative to underscores - * @return a corresponding Locale instance - */ - public static Locale parseLocaleString(final String localeString) { - String[] parts = tokenizeToStringArray(localeString, "_ ", false, false); - String language = (parts.length > 0 ? parts[0] : ""); - String country = (parts.length > 1 ? parts[1] : ""); - String variant = ""; - if (parts.length >= 2) { - // There is definitely a variant, and it is everything after the country - // code sans the separator between the country code and the variant. - int endIndexOfCountryCode = localeString.indexOf(country) + country.length(); - // Strip off any leading '_' and whitespace, what's left is the variant. - variant = trimLeadingWhitespace(localeString.substring(endIndexOfCountryCode)); - if (variant.startsWith("_")) { - variant = trimLeadingCharacter(variant, '_'); - } - } - return (language.length() > 0 ? new Locale(language, country, variant) : null); - } - - /** - * Determine the RFC 3066 compliant language tag, - * as used for the HTTP "Accept-Language" header. - * @param locale the Locale to transform to a language tag - * @return the RFC 3066 compliant language tag as String - */ - public static String toLanguageTag(final Locale locale) { - return locale.getLanguage() + (hasText(locale.getCountry()) ? "-" + locale.getCountry() : ""); - } - - //--------------------------------------------------------------------- - // Convenience methods for working with String arrays - //--------------------------------------------------------------------- - - /** - * Append the given String to the given String array, returning a new array - * consisting of the input array contents plus the given String. - * @param arr the array to append to (can be null) - * @param str the String to append - * @return the new array (never null) - */ - public static String[] addStringToArray(final String[] arr, final String str) { - if (ObjectUtils.isEmpty(arr)) { - return new String[] {str}; - } - String[] newArr = new String[arr.length + 1]; - System.arraycopy(arr, 0, newArr, 0, arr.length); - newArr[arr.length] = str; - return newArr; - } - - /** - * Concatenate the given String arrays into one, - * with overlapping array elements included twice. - *

The order of elements in the original arrays is preserved. - * @param arr1 the first array (can be null) - * @param arr2 the second array (can be null) - * @return the new array (null if both given arrays were null) - */ - public static String[] concatenateStringArrays(final String[] arr1, final String[] arr2) { - if (ObjectUtils.isEmpty(arr1)) { - return arr2; - } - if (ObjectUtils.isEmpty(arr2)) { - return arr1; - } - String[] newArr = new String[arr1.length + arr2.length]; - System.arraycopy(arr1, 0, newArr, 0, arr1.length); - System.arraycopy(arr2, 0, newArr, arr1.length, arr2.length); - return newArr; - } - - /** - * Merge the given String arrays into one, with overlapping - * array elements only included once. - *

The order of elements in the original arrays is preserved - * (with the exception of overlapping elements, which are only - * included on their first occurrence). - * @param arr1 the first array (can be null) - * @param arr2 the second array (can be null) - * @return the new array (null if both given arrays were null) - */ - public static String[] mergeStringArrays(final String[] arr1, final String[] arr2) { - if (ObjectUtils.isEmpty(arr1)) { - return arr2; - } - if (ObjectUtils.isEmpty(arr2)) { - return arr1; - } - List result = new ArrayList(); - result.addAll(Arrays.asList(arr1)); - for (int i = 0, n = arr2.length; i < n; i++) { - String str = arr2[i]; - if (!result.contains(str)) { - result.add(str); - } - } - return toStringArray(result); - } - - /** - * Turn given source String array into sorted array. - * @param arr the source array - * @return the sorted array (never null) - */ - public static String[] sortStringArray(final String[] arr) { - if (ObjectUtils.isEmpty(arr)) { - return new String[0]; - } - Arrays.sort(arr); - return arr; - } - - /** - * Copy the given Collection into a String array. - * The Collection must contain String elements only. - * @param coll the Collection to copy - * @return the String array (null if the passed-in - * Collection was null) - */ - public static String[] toStringArray(final Collection coll) { - if (coll == null) { - return null; - } - return coll.toArray(new String[coll.size()]); - } - - /** - * Copy the given Enumeration into a String array. - * The Enumeration must contain String elements only. - * @param enumeration the Enumeration to copy - * @return the String array (null if the passed-in - * Enumeration was null) - */ - public static String[] toStringArray(final Enumeration enumeration) { - if (enumeration == null) { - return null; - } - List list = Collections.list(enumeration); - return list.toArray(new String[list.size()]); - } - - /** - * Trim the elements of the given String array, - * calling String.trim() on each of them. - * @param arr the original String array - * @return the resulting array (of the same size) with trimmed elements - */ - public static String[] trimArrayElements(final String[] arr) { - if (ObjectUtils.isEmpty(arr)) { - return new String[0]; - } - String[] result = new String[arr.length]; - for (int i = 0, n = arr.length; i < n; i++) { - String element = arr[i]; - result[i] = (element != null ? element.trim() : null); - } - return result; - } - - /** - * Remove duplicate Strings from the given array. - * Also sorts the array, as it uses a TreeSet. - * @param arr the String array - * @return an array without duplicates, in natural sort order - */ - public static String[] removeDuplicateStrings(final String[] arr) { - if (ObjectUtils.isEmpty(arr)) { - return arr; - } - Set set = new TreeSet(); - for (int i = 0, n = arr.length; i < n; i++) { - set.add(arr[i]); - } - return toStringArray(set); - } - - /** - * Split a String at the first occurrence of the delimiter. - * Does not include the delimiter in the result. - * @param toSplit the string to split - * @param delim to split the string up with - * @return a two element array with index 0 being before the delimiter, and - * index 1 being after the delimiter (neither element includes the delimiter); - * or null if the delimiter wasn't found in the given input String - */ - public static String[] split(final String toSplit, final String delim) { - if (!hasLength(toSplit) || !hasLength(delim)) { - return null; - } - int offset = toSplit.indexOf(delim); - if (offset < 0) { - return null; - } - String beforeDelimiter = toSplit.substring(0, offset); - String afterDelimiter = toSplit.substring(offset + delim.length()); - return new String[] {beforeDelimiter, afterDelimiter}; - } - - /** - * Take an array Strings and split each element based on the given delimiter. - * A Properties instance is then generated, with the left of the - * delimiter providing the key, and the right of the delimiter providing the value. - *

Will trim both the key and value before adding them to the - * Properties instance. - * @param arr the array to process - * @param delim to split each element using (typically the equals symbol) - * @return a Properties instance representing the array contents, - * or null if the array to process was null or empty - */ - public static Properties splitArrayElementsIntoProperties(final String[] arr, final String delim) { - return splitArrayElementsIntoProperties(arr, delim, null); - } - - /** - * Take an array Strings and split each element based on the given delimiter. - * A Properties instance is then generated, with the left of the - * delimiter providing the key, and the right of the delimiter providing the value. - *

Will trim both the key and value before adding them to the - * Properties instance. - * - * @param arr the array to process - * @param delim to split each element using (typically the equals symbol) - * @param charsToDelete one or more characters to remove from each element - * prior to attempting the split operation (typically the quotation mark - * symbol), or null if no removal should occur - * @return a Properties instance representing the array contents, - * or null if the array to process was null or empty - */ - public static Properties splitArrayElementsIntoProperties(final String[] arr, final String delim, final String charsToDelete) { - if (ObjectUtils.isEmpty(arr)) { - return null; - } - - Properties result = new Properties(); - for (int i = 0, n = arr.length; i < n; i++) { - String element = arr[i]; - if (charsToDelete != null) { - element = deleteAny(arr[i], charsToDelete); - } - String[] splittedElement = split(element, delim); - if (splittedElement == null) { - continue; - } - result.setProperty(splittedElement[0].trim(), splittedElement[1].trim()); - } - return result; - } - - /** - * Tokenize the given String into a String array via a StringTokenizer. - * Trims tokens and omits empty tokens. - *

The given delimiters string is supposed to consist of any number of - * delimiter characters. Each of those characters can be used to separate - * tokens. A delimiter is always a single character; for multi-character - * delimiters, consider using delimitedListToStringArray - * - * @param str the String to tokenize - * @param delimiters the delimiter characters, assembled as String - * (each of those characters is individually considered as delimiter). - * @return an array of the tokens - * @see java.util.StringTokenizer - * @see java.lang.String#trim() - * @see #delimitedListToStringArray - */ - public static String[] tokenizeToStringArray(final String str, final String delimiters) { - return tokenizeToStringArray(str, delimiters, true, true); - } - - /** - * Tokenize the given String into a String array via a StringTokenizer. - *

The given delimiters string is supposed to consist of any number of - * delimiter characters. Each of those characters can be used to separate - * tokens. A delimiter is always a single character; for multi-character - * delimiters, consider using delimitedListToStringArray - * @param str the String to tokenize - * @param delimiters the delimiter characters, assembled as String - * (each of those characters is individually considered as delimiter) - * @param trimTokens trim the tokens via String's trim - * @param ignoreEmptyTokens omit empty tokens from the result array - * (only applies to tokens that are empty after trimming; StringTokenizer - * will not consider subsequent delimiters as token in the first place). - * @return an array of the tokens (null if the input String - * was null) - * @see java.util.StringTokenizer - * @see java.lang.String#trim() - * @see #delimitedListToStringArray - */ - public static String[] tokenizeToStringArray(final String str, final String delimiters, final boolean trimTokens, final boolean ignoreEmptyTokens) { - if (str == null) { - return null; - } - - StringTokenizer st = new StringTokenizer(str, delimiters); - List tokens = new ArrayList(); - while (st.hasMoreTokens()) { - String token = st.nextToken(); - if (trimTokens) { - token = token.trim(); - } - if (!ignoreEmptyTokens || token.length() > 0) { - tokens.add(token); - } - } - return toStringArray(tokens); - } - - /** - * Take a String which is a delimited list and convert it to a String array. - *

A single delimiter can consists of more than one character: It will still - * be considered as single delimiter string, rather than as bunch of potential - * delimiter characters - in contrast to tokenizeToStringArray. - * @param str the input String - * @param delim the delimiter between elements (this is a single delimiter, - * rather than a bunch individual delimiter characters) - * @return an array of the tokens in the list - * @see #tokenizeToStringArray - */ - public static String[] delimitedListToStringArray(final String str, final String delim) { - return delimitedListToStringArray(str, delim, null); - } - - /** - * Take a String which is a delimited list and convert it to a String array. - *

A single delimiter can consists of more than one character: It will still - * be considered as single delimiter string, rather than as bunch of potential - * delimiter characters - in contrast to tokenizeToStringArray. - * @param str the input String - * @param delimiter the delimiter between elements (this is a single delimiter, - * rather than a bunch individual delimiter characters) - * @param charsToDelete a set of characters to delete. Useful for deleting unwanted - * line breaks: e.g. "\r\n\f" will delete all new lines and line feeds in a String. - * @return an array of the tokens in the list - * @see #tokenizeToStringArray - */ - public static String[] delimitedListToStringArray(final String str, final String delimiter, final String charsToDelete) { - if (str == null) { - return new String[0]; - } - if (delimiter == null) { - return new String[] {str}; - } - List result = new ArrayList(); - if ("".equals(delimiter)) { - for (int i = 0; i < str.length(); i++) { - result.add(deleteAny(str.substring(i, i + 1), charsToDelete)); - } - } - else { - int pos = 0; - int delPos = 0; - while ((delPos = str.indexOf(delimiter, pos)) != -1) { - result.add(deleteAny(str.substring(pos, delPos), charsToDelete)); - pos = delPos + delimiter.length(); - } - if (str.length() > 0 && pos <= str.length()) { - // Add rest of String, but not in case of empty input. - result.add(deleteAny(str.substring(pos), charsToDelete)); - } - } - return toStringArray(result); - } - - /** - * Convert a CSV list into an array of Strings. - * @param str the input String - * @return an array of Strings, or the empty array in case of empty input - */ - public static String[] commaDelimitedListToStringArray(final String str) { - return delimitedListToStringArray(str, ","); - } - - /** - * Convenience method to convert a CSV string list to a set. - * Note that this will suppress duplicates. - * @param str the input String - * @return a Set of String entries in the list - */ - public static Set commaDelimitedListToSet(final String str) { - Set set = new TreeSet(); - String[] tokens = commaDelimitedListToStringArray(str); - for (int i = 0; i < tokens.length; i++) { - set.add(tokens[i]); - } - return set; - } - - /** - * Convenience method to return a Collection as a delimited (e.g. CSV) - * String. E.g. useful for toString() implementations. - * @param coll the Collection to display - * @param delim the delimiter to use (probably a ",") - * @param prefix the String to start each element with - * @param suffix the String to end each element with - * @return the delimited String (never null) - */ - public static String collectionToDelimitedString(final Collection coll, final String delim, final String prefix, final String suffix) { - if (CollectionUtils.isEmpty(coll)) { - return ""; - } - StringBuilder sb = new StringBuilder(); - Iterator it = coll.iterator(); - while (it.hasNext()) { - sb.append(prefix).append(it.next()).append(suffix); - if (it.hasNext() && delim != null) { - sb.append(delim); - } - } - return sb.toString(); - } - - /** - * Concatenates the given collection using the given delimiter between each item. - * - * @param coll the collection to display (can be null or empty) - * @param delim the delimiter to use (can be null or empty for none) - * @return the delimited String (never null) - */ - public static String collectionToDelimitedString(final Collection coll, final String delim) { - return collectionToDelimitedString(coll, delim, "", ""); - } - - /** - * Convenience method to return a Collection as a CSV String. - * E.g. useful for toString() implementations. - * @param coll the Collection to display - * @return the delimited String - */ - public static String collectionToCommaDelimitedString(final Collection coll) { - return collectionToDelimitedString(coll, ","); - } - - /** - * Convenience method to return a String array as a delimited (e.g. CSV) - * String. E.g. useful for toString() implementations. - * - * @param arr the array to display - * @param delim the delimiter to use (probably a ",") - * @return the delimited String - * @since 1.2.0 - */ - public static String arrayToDelimitedString(final String delim, final Object... arr) { - return arrayToDelimitedString(arr, delim); - } - - /** - * Convenience method to return a String array as a delimited (e.g. CSV) - * String. E.g. useful for toString() implementations. - * - * @param arr the array to display - * @param delim the delimiter to use (probably a ",") - * @return the delimited String - */ - public static String arrayToDelimitedString(final Object[] arr, final String delim) { - if (ObjectUtils.isEmpty(arr)) { - return ""; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < arr.length; i++) { - if (i > 0) { - sb.append(delim); - } - sb.append(arr[i]); - } - return sb.toString(); - } - - /** - * Convenience method to return a String array as a CSV String. - * E.g. useful for toString() implementations. - * @param arr the array to display - * @return the delimited String - */ - public static String arrayToCommaDelimitedString(final Object[] arr) { - return arrayToDelimitedString(arr, ","); - } - - /** - * Converts the given String to uppercase. - * - * @param str the input String (may be null) - * @return the String in uppercase, otherwise null - */ - public static String toUpperCase(final String str) { - return str == null ? null : str.toUpperCase(); - } - - /** - * Converts the given String to lowercase. - * - * @param str the input String (may be null) - * @return the String in lowercase, otherwise null - */ - public static String toLowerCase(final String str) { - return str == null ? null : str.toLowerCase(); - } - - /** - *

- * Removes leading and trailing whitespace from both ends of this String returning null if the String is empty ("") after the trim or if it is null. - * - *

-	 * StringUtils.trimToNull(null) = null
-	 * StringUtils.trimToNull("") = null
-	 * StringUtils.trimToNull(" ") = null
-	 * StringUtils.trimToNull("abc") = "abc"
-	 * StringUtils.trimToNull(" abc ") = "abc"
-	 * 
- * - * @param str the String to be trimmed, may be null - * @return the trimmed String, null if only chars <= 32, empty or null String input - * @since 1.1 - */ - public static String trimToNull(final String str) { - String ts = trimWhitespace(str); - return !hasText(ts) ? null : ts; - } - - /** - *

- * Removes leading and trailing whitespace from both ends of this String returning an empty String ("") if the String is empty after the trim or if it is null. - * - *

-	 * StringUtils.trimToNull(null) = ""
-	 * StringUtils.trimToNull("") = ""
-	 * StringUtils.trimToNull(" ") = ""
-	 * StringUtils.trimToNull("abc") = "abc"
-	 * StringUtils.trimToNull(" abc ") = "abc"
-	 * 
- * - * @param str the String to be trimmed, may be null - * @return the trimmed String, an empty String("") if only chars <= 32, empty or null String input - * @since 1.1 - */ - public static String trimToEmpty(final String str) { - String ts = trimWhitespace(str); - return !hasText(ts) ? "" : ts; - } - - /** - * Returns either the passed in String, or if it's blank, the first of the - * given default values that is not blank. If all the given Strings are - * blank, returns the last of them. - * - *
    - *
  • StringUtils.defaultIfEmpty(null, "NULL") = "NULL"
  • - *
  • StringUtils.defaultIfEmpty("", "NULL") = "NULL"
  • - *
  • StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
  • - *
  • StringUtils.defaultIfEmpty(null, "", "bat") = "bat"
  • - *
  • StringUtils.defaultIfEmpty(null, null, "") = ""
  • - *
- * - * @param str the String to check, may be null - * @param defaultStr the default String to return if the input is empty ("") - * or null, may be null; note that if this is an expression, it will be - * evaluated before this method is called regardless of whether the first - * string is empty, so if this evaluation is expensive and performance is - * critical, check the first string for emptiness yourself rather than using - * this method - * @return the passed in String, or the default - */ - public static String defaultIfEmpty(final String str, final String... defaultValues) { - if (hasText(str) || ObjectUtils.isEmpty(defaultValues)) { - return str; - } - for (final String defaultValue : defaultValues) { - if (hasText(defaultValue)) { - return defaultValue; - } - } - return defaultValues[defaultValues.length - 1]; - } - - /** - * Right pads the presented string with the delim character. - * - * @param str the string to pad - * @param size the size to pad to - * @param padChar the padding character - * @return the right padded string - */ - public static String padRight(final String str, final int size, final char padChar) { - if (str == null) { - return null; - } - int pads = size - str.length(); - if (pads <= 0) { - return str; - } - return str.concat(padding(pads, padChar)); - } - - /** - * Left pads the presented string with the delim character. - * - * @param str the string to pad - * @param size the size to pad to - * @param padChar the padding character - * @return the left padded string - */ - public static String padLeft(final String str, final int size, final char padChar) { - if (str == null) { - return null; - } - int pads = size - str.length(); - if (pads <= 0) { - return str; - } - return padding(pads, padChar).concat(str); - } - - private static String padding(final int repeat, final char padChar) throws IndexOutOfBoundsException { - if (repeat < 0) { - throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat); - } - final char[] buf = new char[repeat]; - for (int i = 0; i < buf.length; i++) { - buf[i] = padChar; - } - return new String(buf); - } - - /** - * Prefixes the given string with the given prefix, if it's not already. - * - * @param str the string to prefix (can be blank) - * @param prefix the prefix to apply (can be blank to do nothing) - * @return null if a null string was given, - * otherwise the prefixed string - * @since 1.2.0 - */ - public static String prefix(final String str, final String prefix) { - if (str == null || prefix == null || str.startsWith(prefix)) { - return str; - } - return prefix + str; - } - - /** - * Removes the given prefix from the given string, if it exists - * - * @param str the string to modify (can be blank to do nothing) - * @param prefix the prefix to remove (can be blank to do nothing) - * @return null if a null string was given - * @since 1.2.0 - */ - public static String removePrefix(final String str, final String prefix) { - if (!hasText(str) || !hasText(prefix) || !str.startsWith(prefix)) { - return str; - } - return str.substring(prefix.length()); - } - - /** - * Removes the given suffix from the given string, if it exists - * - * @param str the string to modify (can be blank to do nothing) - * @param suffix the suffix to remove (can be blank to do nothing) - * @return null if a null string was given - * @since 1.2.0 - */ - public static String removeSuffix(final String str, final String suffix) { - if (!hasText(str) || !hasText(suffix) || !str.endsWith(suffix)) { - return str; - } - return str.substring(0, str.length() - suffix.length()); - } - - /** - * Appends the given suffix to the given string, if not already present - * - * @param str the string to modify (can be blank to do nothing) - * @param suffix the suffix to append (can be blank to do nothing) - * @return null if a null string was given - * @since 1.2.0 - */ - public static String suffix(final String str, final String suffix) { - if (str == null || suffix == null || str.endsWith(suffix)) { - return str; - } - return str + suffix; - } - - /** - * Indicates whether the two given strings are equal, including case, where - * null is (only) equal to null. - * - * @param str1 the first string to compare (can be null) - * @param str2 the second string to compare (can be null) - * @return see above - * @since 1.2.0 - */ - public static boolean equals(final String str1, final String str2) { - if (str1 == null) { - return str2 == null; - } - return str1.equals(str2); - } - - /** - * Indicates whether the given text is blank. More fluent than calling - * StringUtils.isBlank(blah). - * - * @param str the text to check (can be blank) - * @return the opposite of {@link #hasText(String)} - * @since 1.2.0 - */ - public static boolean isBlank(final String str) { - return !hasText(str); - } - - /** - * Replaces the first occurrence of the given substring in the given string. - *

- * Use in preference to {@link String#replaceFirst(String, String)} when - * toReplace is not a regular expression (e.g. some part of a - * file path, which on Windows will contain backslashes, which have special - * meaning to regexs). - * - * @param original the string to modify (can be zero length to do nothing) - * @param toReplace the string to replace (can be blank to do nothing) - * @param replacement the string to replace it with (can be null to do nothing) - * @return the original string, modified as necessary - * @since 1.2.0 - */ - public static String replaceFirst(final String original, final String toReplace, final String replacement) { - if (!hasLength(original) || !hasLength(toReplace) || replacement == null || !original.contains(toReplace)) { - return original; - } - final int startOfOld = original.indexOf(toReplace); - final int endOfOld = startOfOld + toReplace.length(); - return arrayToDelimitedString("", original.substring(0, startOfOld), replacement, original.substring(endOfOld)); - } - - /** - * Returns the substring after the last occurrence of a separator. The separator is not returned. - *

A null string input will return null. An empty ("") string input will return the empty string. - * An empty or null separator will return the empty string if the input string is not null. - *

If nothing is found, the empty string is returned. - *

-	     StringUtils.substringAfterLast(null, *)      = null
-	     StringUtils.substringAfterLast("", *)        = ""
-	     StringUtils.substringAfterLast(*, "")        = ""
-	     StringUtils.substringAfterLast(*, null)      = ""
-	     StringUtils.substringAfterLast("abc", "a")   = "bc"
-	     StringUtils.substringAfterLast("abcba", "b") = "a"
-	     StringUtils.substringAfterLast("abc", "c")   = ""
-	     StringUtils.substringAfterLast("a", "a")     = ""
-	     StringUtils.substringAfterLast("a", "z")     = ""
- * - * @param original the String to get a substring from, may be null - * @param separator the String to search for, may be null - * @return the substring after the last occurrence of the separator, - * null if null String input - * @since 1.2.0 - */ - public static String substringAfterLast(final String original, final String separator) { - if (!hasLength(original)) { - return original; - } - if (!hasLength(separator)) { - return ""; - } - final int separatorStart = original.lastIndexOf(separator); - if (separatorStart == -1) { - return ""; - } - return original.substring(separatorStart + separator.length()); - } - - /** - * Constructor is private to prevent instantiation - */ - private StringUtils() {} -} \ No newline at end of file diff --git a/src/main/java/org/springframework/shell/support/util/TemplateUtils.java b/src/main/java/org/springframework/shell/support/util/TemplateUtils.java deleted file mode 100644 index eff35e40..00000000 --- a/src/main/java/org/springframework/shell/support/util/TemplateUtils.java +++ /dev/null @@ -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() {} -} diff --git a/src/main/java/org/springframework/shell/support/util/UrlUtils.java b/src/main/java/org/springframework/shell/support/util/UrlUtils.java deleted file mode 100644 index ca9035cd..00000000 --- a/src/main/java/org/springframework/shell/support/util/UrlUtils.java +++ /dev/null @@ -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-null 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() {} -} diff --git a/src/main/java/org/springframework/shell/support/util/WebXmlUtils.java b/src/main/java/org/springframework/shell/support/util/WebXmlUtils.java deleted file mode 100644 index 84ba972b..00000000 --- a/src/main/java/org/springframework/shell/support/util/WebXmlUtils.java +++ /dev/null @@ -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() : Arrays.asList(initParams), new ArrayList()); - } - - /** - * 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 initParams, final List 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(); - } - - // 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 webResourceCollections, final List 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 { - - /** - * 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 urlPatterns; - private final List httpMethods; - - public WebResourceCollection(final String webResourceName, final String description, final List urlPatterns, final List httpMethods) { - this.webResourceName = webResourceName; - this.description = description; - this.urlPatterns = urlPatterns; - this.httpMethods = httpMethods; - } - - public String getWebResourceName() { - return webResourceName; - } - - public List getUrlPatterns() { - return urlPatterns; - } - - public List getHttpMethods() { - return httpMethods; - } - - public String getDescription() { - return description; - } - } - - /** - * Constructor is private to prevent instantiation - */ - private WebXmlUtils() { - } -} diff --git a/src/main/java/org/springframework/shell/support/util/XmlElementBuilder.java b/src/main/java/org/springframework/shell/support/util/XmlElementBuilder.java deleted file mode 100644 index 8b0c0da3..00000000 --- a/src/main/java/org/springframework/shell/support/util/XmlElementBuilder.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/java/org/springframework/shell/support/util/XmlRoundTripUtils.java b/src/main/java/org/springframework/shell/support/util/XmlRoundTripUtils.java deleted file mode 100644 index 3a1cdff9..00000000 --- a/src/main/java/org/springframework/shell/support/util/XmlRoundTripUtils.java +++ /dev/null @@ -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 attrKVStore = Collections.synchronizedSortedMap(new TreeMap()); - 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 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() {} -} diff --git a/src/main/java/org/springframework/shell/support/util/XmlUtils.java b/src/main/java/org/springframework/shell/support/util/XmlUtils.java deleted file mode 100644 index 1430badd..00000000 --- a/src/main/java/org/springframework/shell/support/util/XmlUtils.java +++ /dev/null @@ -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 compiledExpressionCache = new HashMap(); - 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 null 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 null for none - * @return a non-null 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 <beans><sec:http>, 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 <beans><sec:http>, you - * need to use the XPath expression '/beans/http'. - * - * @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 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 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 findElements(final String xPathExpression, final Element root) { - final List elements = new ArrayList(); - 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-null 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() {} -} \ No newline at end of file diff --git a/src/test/java/org/springframework/shell/support/util/CollectionUtilsTest.java b/src/test/java/org/springframework/shell/support/util/CollectionUtilsTest.java deleted file mode 100644 index 1309fb0d..00000000 --- a/src/test/java/org/springframework/shell/support/util/CollectionUtilsTest.java +++ /dev/null @@ -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 NON_BLANK_FILTER = new Filter() { - 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 inputs = Arrays.asList("a", ""); - - // Invoke - final List results = CollectionUtils.filter(inputs, null); - - // Check - assertEquals(inputs, results); - } - - @Test - public void testFilterNonNullIterableWithNonNullFilter() { - // Set up - final Iterable inputs = Arrays.asList("a", "", null, "b"); - - // Invoke - final List 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 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 parents = new ArrayList(); - 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 collection = new ArrayList(); - collection.add(new Parent()); - - // Invoke - final Collection result = CollectionUtils.populate(collection, null); - - // Check - assertEquals(0, result.size()); - } - - @Test - public void testPopulateNonNullCollectionWithNonNullCollection() { - // Set up - final Collection originalCollection = new ArrayList(); - originalCollection.add(new Parent()); - final Child child = new Child(); - - // Invoke - final Collection 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))); - } -} diff --git a/src/test/java/org/springframework/shell/support/util/DomUtilsTest.java b/src/test/java/org/springframework/shell/support/util/DomUtilsTest.java deleted file mode 100644 index 9bee796c..00000000 --- a/src/test/java/org/springframework/shell/support/util/DomUtilsTest.java +++ /dev/null @@ -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 = - "" + - " " + - " " + - " " + - " " + - ""; - private static final String XML_AFTER_REMOVAL = - "\n" + - " \n" + - ""; - - /** - * 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); - } -} diff --git a/src/test/java/org/springframework/shell/support/util/FileUtilsTest.java b/src/test/java/org/springframework/shell/support/util/FileUtilsTest.java index d2c1347f..5847af53 100644 --- a/src/test/java/org/springframework/shell/support/util/FileUtilsTest.java +++ b/src/test/java/org/springframework/shell/support/util/FileUtilsTest.java @@ -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)); diff --git a/src/test/java/org/springframework/shell/support/util/NumberUtilsTest.java b/src/test/java/org/springframework/shell/support/util/NumberUtilsTest.java deleted file mode 100644 index 1d91e504..00000000 --- a/src/test/java/org/springframework/shell/support/util/NumberUtilsTest.java +++ /dev/null @@ -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)); - } -} diff --git a/src/test/java/org/springframework/shell/support/util/ObjectUtilsTest.java b/src/test/java/org/springframework/shell/support/util/ObjectUtilsTest.java deleted file mode 100644 index db7283b9..00000000 --- a/src/test/java/org/springframework/shell/support/util/ObjectUtilsTest.java +++ /dev/null @@ -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)); - } -} diff --git a/src/test/java/org/springframework/shell/support/util/PairListTest.java b/src/test/java/org/springframework/shell/support/util/PairListTest.java deleted file mode 100644 index 0ad11268..00000000 --- a/src/test/java/org/springframework/shell/support/util/PairListTest.java +++ /dev/null @@ -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 PAIR_1 = new Pair(KEY_1, VALUE_1); - private static final Pair PAIR_2 = new Pair(KEY_2, VALUE_2); - - @SuppressWarnings("unchecked") - @Test - public void testConstructFromVarargArrayOfPairs() { - // Invoke - final PairList pairs = new PairList(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[] array = pairs.toArray(); - assertEquals(pairs.size(), array.length); - assertEquals(pairs, Arrays.asList(array)); - } - - @Test - public void testConstructFromListsOfKeysAndValues() { - // Invoke - final PairList pairs = new PairList(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 pairs = new PairList(null, null); - - // Check - assertEquals(0, pairs.size()); - } -} diff --git a/src/test/java/org/springframework/shell/support/util/PairTest.java b/src/test/java/org/springframework/shell/support/util/PairTest.java deleted file mode 100644 index d16b2081..00000000 --- a/src/test/java/org/springframework/shell/support/util/PairTest.java +++ /dev/null @@ -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(null, ""); - } - - @Test - public void testConstructWithNullValue() { - new Pair("", null); - } - - @Test - public void testInstanceEqualsItself() { - final Pair pair = new Pair(1, "a"); - assertEquals(pair, pair); - } - - @Test - public void testEqualKeyAndValueAreEqual() { - assertEquals(new Pair(1, "a"), new Pair(1, "a")); - } - - @Test - public void testUnequalKeyIsNotEqual() { - assertFalse(new Pair(1, "a").equals(new Pair(2, "a"))); - } - - @Test - public void testUnequalValueIsNotEqual() { - assertFalse(new Pair(1, "a").equals(new Pair(1, "b"))); - } - - @Test - public void testOtherClassIsNotAPair() { - assertFalse(new Pair(1, "a").equals("foo")); - } -} diff --git a/src/test/java/org/springframework/shell/support/util/StringUtilsTest.java b/src/test/java/org/springframework/shell/support/util/StringUtilsTest.java deleted file mode 100644 index 7719e825..00000000 --- a/src/test/java/org/springframework/shell/support/util/StringUtilsTest.java +++ /dev/null @@ -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>"); - } -} diff --git a/src/test/java/org/springframework/shell/support/util/WebXmlUtilsTest.java b/src/test/java/org/springframework/shell/support/util/WebXmlUtilsTest.java deleted file mode 100644 index 564e7a57..00000000 --- a/src/test/java/org/springframework/shell/support/util/WebXmlUtilsTest.java +++ /dev/null @@ -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 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 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 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 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 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 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()); - } -}