diff --git a/.github/workflows/github-actions-build.yml b/.github/workflows/github-actions-build.yml
index 0dc721a12..062f1ea42 100644
--- a/.github/workflows/github-actions-build.yml
+++ b/.github/workflows/github-actions-build.yml
@@ -48,7 +48,7 @@ jobs:
echo "Sonar secure variables NOT available"
else
echo "Sonar secure variables ARE available"
- mvn -B sonar:sonar -Dsonar.projectKey="bordertech-wcomponents" -Dsonar.organization="bordertech-github" -Dsonar.host.url="https://sonarcloud.io"
+ mvn -B org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey="bordertech-wcomponents" -Dsonar.organization="bordertech-github" -Dsonar.host.url="https://sonarcloud.io" -Dsonar.qualitygate.wait=true
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 388a1b242..5f2a97d1d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,51 @@ Client Side API:
### Bug Fixes
* SelectToggle label attribute fix, `wc-data-for` > `data-wc-for`.
+## 1.5.39
+
+### API Changes
+* Updated AbstractRequest to remove deprecated methods uploadFileItems and readBytes (were protected static). Use StreamUtils instead.
+### Enhancements
+* Consistent use of try-with-resources when handling streams
+* Replaced org.apache.tika:tika library with org.overviewproject:mime-types in FileUtil to validate uploaded file mime types.
+* Updated the following dependencies:
+ * wcomponents-core:
+ * com.google.code.gson:gson from 2.13.1 to 2.13.2
+ * org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0
+ * commons-io:commons-io from 2.19.0 to 2.21.0
+ * com.google.errorprone:error_prone_annotations from 2.39.0 to 2.46.0
+ * org.apache.httpcomponents.client5:httpclient5 from 5.5 to 5.6
+ * org.apache.httpcomponents.core5:httpcore5 from 5.3.4 to 5.4
+ * wcomponents-test-lib:
+ * io.github.bonigarcia:webdrivermanager from 6.1.0 to 6.3.3
+ * org.apache.commons:commons-compress from 1.27.1 to 1.28.0
+ * commons-codec:commons-codec from 1.18.0 to 1.20.0
+ * com.google.guava:guava from 33.4.8-jre to 33.5.0-jre
+ * net.java.dev.jna:jna from 5.17.0 to 5.18.1
+ * wcomponents-bundle:
+ * org.ehcache:ehcahce from 3.10.8 to 3.11.1
+ * org.glassfish.jaxb:jaxb-runtime from 4.0.5 to 4.0.6
+### Bug Fixes
+* Updated FileUtil to make file extension and mime type validation case insensitive.
+
+## 1.5.38
+
+### Enhancements
+* To improve the robustness of the session token parameter (wc_t), which is used to prevent CSRF attacks, the following changes have been made:
+ * The session token is no longer included on any GET URLs and only posted in the body for POSTS.
+ * Modified the session token interceptors to only accept a session token on a POST and throw an exception if provided on a GET.
+ * Modified Targetable components to use the new createTargetUrl method in WebUtilites that centralises the logic for
+ creating the URLs for Targetable components and excludes the session token.
+ * Moved the adding of the hidden parameters onto the AJAX url from the XSL into the WApplicationRenderer so the session
+ token can be excluded.
+* Updated beanutils version and package names as beanutils had a transient dependency on commons-collections that has security vulnerabilies.
+ * commons-beanutils:commons-beanutils:1.11.0 to org.apache.commons:commons-beanutils2:2.0.0-M2
+* Updated antisamy to latest version 1.7.8 as it has reinstated the xHTML behaviour for tags. Versions 1.7.0 to 1.7.6 did not support xHTML and would break the XML.
+ * org.owasp.antisamy:antismay from 1.6.8 to 1.7.8
+* Updated FileUtil to include MetaData hints when calling tika to help tika identify a files content type.
+
+NOTE - The session token changes are not backwards compatable with older themes.
+
## 1.5.37
### Enhancements
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
new file mode 100644
index 000000000..88cb603bc
--- /dev/null
+++ b/code-coverage/pom.xml
@@ -0,0 +1,70 @@
+
+
+ 4.0.0
+
+
+ com.github.bordertech.wcomponents
+ wcomponents-parent
+ 1.5.40-SNAPSHOT
+ ../pom.xml
+
+
+ code-coverage
+ code-coverage
+
+ jar
+
+
+
+ com.github.bordertech.wcomponents
+ wcomponents-core
+ ${project.version}
+
+
+ com.github.bordertech.wcomponents
+ wcomponents-examples
+ ${project.version}
+
+
+ com.github.bordertech.wcomponents
+ wcomponents-test-lib
+ ${project.version}
+
+
+ com.github.bordertech.wcomponents
+ wcomponents-lde
+ ${project.version}
+
+
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ report-aggregate
+ test
+
+ report-aggregate
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 3.1.4
+
+ true
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 44e58b55a..5edf83bef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOTpom
@@ -85,7 +85,7 @@
org.ehcacheehcache
- 3.10.8
+ 3.11.1
@@ -107,7 +107,7 @@
org.glassfish.jaxbjaxb-runtime
- 4.0.5
+ 4.0.6
@@ -217,6 +217,7 @@
wcomponents-themewcomponents-xsltwcomponents-bundle
+ code-coverage
diff --git a/wcomponents-bundle/pom.xml b/wcomponents-bundle/pom.xml
index df7aff26b..8f63ce162 100755
--- a/wcomponents-bundle/pom.xml
+++ b/wcomponents-bundle/pom.xml
@@ -8,7 +8,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOT../pom.xml
diff --git a/wcomponents-core/pom.xml b/wcomponents-core/pom.xml
index 5734d76f0..fea5e1b4e 100755
--- a/wcomponents-core/pom.xml
+++ b/wcomponents-core/pom.xml
@@ -8,7 +8,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOT../pom.xml
@@ -101,15 +101,19 @@
- commons-beanutils
- commons-beanutils
- 1.11.0
+ org.apache.commons
+ commons-beanutils2
+ 2.0.0-M2commons-loggingcommons-logging
+
+ org.apache.commons
+ commons-lang3
+
@@ -186,7 +190,7 @@
com.google.code.gsongson
- 2.13.1
+ 2.13.2com.google.errorprone
@@ -196,51 +200,36 @@
-
-
+
org.owasp.antisamyantisamy
- 1.6.8
+ 1.7.8
-
- org.slf4j
- slf4j-api
- org.apache.xmlgraphicsbatik-css
-
- commons-io
- commons-io
- org.apache.httpcomponents.client5httpclient5
- org.apache.httpcomponents.core5
- httpcore5
+ xerces
+ xercesImpl
- net.sourceforge.htmlunit
- neko-htmlunit
+ commons-io
+ commons-io
- xerces
- xercesImpl
+ org.apache.httpcomponents.core5
+ httpcore5
-
-
- net.sourceforge.htmlunit
- neko-htmlunit
- 2.70.0
- org.apache.xmlgraphicsbatik-css
@@ -280,20 +269,9 @@
- org.apache.tika
- tika-core
- 2.9.4
-
-
-
- org.slf4j
- slf4j-api
-
-
- commons-io
- commons-io
-
-
+ org.overviewproject
+ mime-types
+ 2.0.0
@@ -310,22 +288,22 @@
org.apache.commonscommons-lang3
- 3.18.0
+ 3.20.0commons-iocommons-io
- 2.19.0
+ 2.21.0com.google.errorproneerror_prone_annotations
- 2.39.0
+ 2.46.0org.apache.httpcomponents.client5httpclient5
- 5.5
+ 5.6org.slf4j
@@ -336,7 +314,7 @@
org.apache.httpcomponents.core5httpcore5
- 5.3.4
+ 5.4
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractBeanBoundTableModel.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractBeanBoundTableModel.java
index c99a53923..b9dd89094 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractBeanBoundTableModel.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractBeanBoundTableModel.java
@@ -1,7 +1,7 @@
package com.github.bordertech.wcomponents;
import com.github.bordertech.wcomponents.WTable.BeanBoundTableModel;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractBeanTableDataModel.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractBeanTableDataModel.java
index e230090bd..d55e9a19b 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractBeanTableDataModel.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractBeanTableDataModel.java
@@ -1,6 +1,6 @@
package com.github.bordertech.wcomponents;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractRequest.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractRequest.java
index 3511feb72..5ed0ab8b6 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractRequest.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/AbstractRequest.java
@@ -1,16 +1,11 @@
package com.github.bordertech.wcomponents;
-import com.github.bordertech.wcomponents.servlet.ServletUtil;
import com.github.bordertech.wcomponents.util.Config;
import com.github.bordertech.wcomponents.util.Enumerator;
-import com.github.bordertech.wcomponents.util.StreamUtil;
import com.github.bordertech.wcomponents.util.Util;
-import java.io.IOException;
-import java.io.InputStream;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import org.apache.commons.fileupload.FileItem;
@@ -69,7 +64,7 @@ public FileItem[] getFileItems(final String key) {
result = deserialized.toArray(new FileItem[]{});
}
}
- */
+ */
return result;
}
@@ -128,41 +123,6 @@ public boolean isLogout() {
return logout;
}
- /**
- *
- * {@link FileItem} classes (if attachements) will be kept as part of the request. The default behaviour of the file
- * item is to store the upload in memory until it reaches a certain size, after which the content is streamed to a
- * temp file.
- *
- *
- * If, in the future, performance of uploads becomes a focus we can instead look into using the Jakarta Commons
- * Streaming API. In this case, the content of the upload isn't stored anywhere. It will be up to the user to
- * read/store the content of the stream.
- *
- * @param fileItems a list of {@link FileItem}s corresponding to POSTed form data.
- * @param parameters the map to store non-file request parameters in.
- * @param files the map to store the uploaded file parameters in.
- * @deprecated Use {@link ServletUtil#uploadFileItems(java.util.List, java.util.Map, java.util.Map)} instead.
- */
- @Deprecated
- protected static void uploadFileItems(final List fileItems, final Map parameters,
- final Map files) {
- ServletUtil.uploadFileItems(fileItems, parameters, files);
- }
-
- /**
- * Returns a byte array containing all the information contained in the given input stream.
- *
- * @param stream the input stream to read from.
- * @return the stream contents as a byte array.
- * @throws IOException if there is an error reading from the stream.
- * @deprecated Use {@link StreamUtil#getBytes(java.io.InputStream)} instead.
- */
- @Deprecated
- protected static byte[] readBytes(final InputStream stream) throws IOException {
- return StreamUtil.getBytes(stream);
- }
-
/**
* This method contains no logic. Subclasses which need to perform event handling logic (eg.
* WPortletRequest) should override this method.
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/ContentEscape.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/ContentEscape.java
index 7706ef0b9..a64759a9e 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/ContentEscape.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/ContentEscape.java
@@ -9,8 +9,7 @@
import org.apache.commons.logging.LogFactory;
/**
- * An Escape subclass that bypasses the usual request -> paint flow by directly producing the binary document
- * content.
+ * An Escape subclass that bypasses the usual request -> paint flow by directly producing the binary document content.
*
* @author Martin Shevchenko
* @since 1.0.0
@@ -81,28 +80,19 @@ public void escape() throws IOException {
}
if (contentAccess instanceof ContentStreamAccess) {
- InputStream stream = null;
-
- try {
- stream = ((ContentStreamAccess) contentAccess).getStream();
-
+ try (InputStream stream = ((ContentStreamAccess) contentAccess).getStream()) {
if (stream == null) {
throw new SystemException(
"ContentAccess returned null stream, access=" + contentAccess);
}
-
StreamUtil.copy(stream, response.getOutputStream());
- } finally {
- StreamUtil.safeClose(stream);
}
} else {
byte[] bytes = contentAccess.getBytes();
-
if (bytes == null) {
throw new SystemException(
"ContentAccess returned null data, access=" + contentAccess);
}
-
response.getOutputStream().write(bytes);
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/InternalResource.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/InternalResource.java
index 42bf2c7be..ef096226f 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/InternalResource.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/InternalResource.java
@@ -56,17 +56,11 @@ public InternalResource(final String resourceName, final String description) {
*/
@Override
public byte[] getBytes() {
- InputStream stream = null;
-
- try {
- stream = getClass().getResourceAsStream(resourceName);
+ try (InputStream stream = getClass().getResourceAsStream(resourceName)) {
return StreamUtil.getBytes(stream);
} catch (Exception e) {
LOG.error("Failed to read resource: " + resourceName, e);
- } finally {
- StreamUtil.safeClose(stream);
}
-
return EMPTY;
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanBoundTableDataModel.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanBoundTableDataModel.java
index defa9d8fc..c1a7949b6 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanBoundTableDataModel.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanBoundTableDataModel.java
@@ -5,7 +5,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanBoundTableModel.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanBoundTableModel.java
index b7e1b17bd..2c579d292 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanBoundTableModel.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanBoundTableModel.java
@@ -7,7 +7,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanListTableDataModel.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanListTableDataModel.java
index aec0d4d43..e56bd45a7 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanListTableDataModel.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanListTableDataModel.java
@@ -6,7 +6,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanTreeTableDataModel.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanTreeTableDataModel.java
index 7562fdffd..cbee423d4 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanTreeTableDataModel.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/SimpleBeanTreeTableDataModel.java
@@ -7,7 +7,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WAudio.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WAudio.java
index e60e3d732..68fcc8efe 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WAudio.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WAudio.java
@@ -2,6 +2,7 @@
import com.github.bordertech.wcomponents.util.Util;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
@@ -324,29 +325,11 @@ public String[] getAudioUrls() {
}
String[] urls = new String[audio.length];
-
- Environment env = getEnvironment();
- Map parameters = env.getHiddenParameters();
- parameters.put(Environment.TARGET_ID, getTargetId());
-
- if (Util.empty(getCacheKey())) {
- // Add some randomness to the URL to prevent caching
- String random = WebUtilities.generateRandom();
- parameters.put(Environment.UNIQUE_RANDOM_PARAM, random);
- } else {
- // Remove step counter as not required for cached content
- parameters.remove(Environment.STEP_VARIABLE);
- parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
- // Add the cache key
- parameters.put(Environment.CONTENT_CACHE_KEY, getCacheKey());
- }
-
- // this variable needs to be set in the portlet environment.
- String url = env.getWServletPath();
-
+ String cacheKey = getCacheKey();
+ Map parameters = new HashMap<>();
for (int i = 0; i < urls.length; i++) {
parameters.put(AUDIO_INDEX_REQUEST_PARAM_KEY, String.valueOf(i));
- urls[i] = WebUtilities.getPath(url, parameters, true);
+ urls[i] = WebUtilities.createTargetUrl(this, cacheKey, parameters);
}
return urls;
@@ -439,7 +422,6 @@ public boolean isRenderControls() {
return getComponentModel().renderControls;
}
-
/**
* Sets whether the browser should render the default controls. The default is true.
* @param renderControls if true then the controls are rendered
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WBeanComponent.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WBeanComponent.java
index ec1cfcb7e..990c77330 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WBeanComponent.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WBeanComponent.java
@@ -6,7 +6,7 @@
import java.io.Serializable;
import java.util.Map;
import java.util.Objects;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WContent.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WContent.java
index 2167a6b06..6c43003bf 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WContent.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WContent.java
@@ -1,7 +1,6 @@
package com.github.bordertech.wcomponents;
import com.github.bordertech.wcomponents.util.Util;
-import java.util.Map;
/**
*
@@ -176,41 +175,19 @@ public String getUrl() {
String mode = DisplayMode.PROMPT_TO_SAVE.equals(getDisplayMode()) ? "attach" : "inline";
+ String url;
// Check for a "static" resource
if (content instanceof InternalResource) {
- String url = ((InternalResource) content).getTargetUrl();
- // This magic parameter is a work-around to the loading indicator becoming
- // "stuck" in certain browsers.
- // It is also used by the static resource handler to set the correct headers
- url = url + "&" + URL_CONTENT_MODE_PARAMETER_KEY + "=" + mode;
- return url;
- }
-
- Environment env = getEnvironment();
- Map parameters = env.getHiddenParameters();
- parameters.put(Environment.TARGET_ID, getTargetId());
-
- if (Util.empty(getCacheKey())) {
- // Add some randomness to the URL to prevent caching
- String random = WebUtilities.generateRandom();
- parameters.put(Environment.UNIQUE_RANDOM_PARAM, random);
+ url = ((InternalResource) content).getTargetUrl();
} else {
- // Remove step counter as not required for cached content
- parameters.remove(Environment.STEP_VARIABLE);
- parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
- // Add the cache key
- parameters.put(Environment.CONTENT_CACHE_KEY, getCacheKey());
+ url = WebUtilities.createTargetUrl(this, getCacheKey());
}
- // This magic parameter is a work-around to the loading indicator becoming
- // "stuck" in certain browsers. It is only read by the theme.
- parameters.put(URL_CONTENT_MODE_PARAMETER_KEY, mode);
-
- // The targetable path needs to be configured for the portal environment.
- String url = env.getWServletPath();
+ // This magic parameter is a work-around to the loading indicator becoming "stuck" in certain browsers.
+ // It is also used by the static resource handler to set the correct headers
+ url = url + "&" + URL_CONTENT_MODE_PARAMETER_KEY + "=" + mode;
- // Note the last parameter. In javascript we don't want to encode "&".
- return WebUtilities.getPath(url, parameters, true);
+ return url;
}
/**
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WImage.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WImage.java
index 2774887d5..386559d97 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WImage.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WImage.java
@@ -2,7 +2,6 @@
import com.github.bordertech.wcomponents.util.Util;
import java.awt.Dimension;
-import java.util.Map;
/**
*
@@ -99,26 +98,7 @@ public String getTargetUrl() {
return ((InternalResource) image).getTargetUrl();
}
- Environment env = getEnvironment();
- Map parameters = env.getHiddenParameters();
- parameters.put(Environment.TARGET_ID, getTargetId());
-
- if (Util.empty(getCacheKey())) {
- // Add some randomness to the URL to prevent caching
- String random = WebUtilities.generateRandom();
- parameters.put(Environment.UNIQUE_RANDOM_PARAM, random);
- } else {
- // Remove step counter as not required for cached content
- parameters.remove(Environment.STEP_VARIABLE);
- parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
- // Add the cache key
- parameters.put(Environment.CONTENT_CACHE_KEY, getCacheKey());
- }
-
- // this variable needs to be set in the portlet environment.
- String url = env.getWServletPath();
-
- return WebUtilities.getPath(url, parameters, true);
+ return WebUtilities.createTargetUrl(this, getCacheKey());
}
/**
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WMultiFileWidget.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WMultiFileWidget.java
index c8319b6ad..c8d49514f 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WMultiFileWidget.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WMultiFileWidget.java
@@ -9,11 +9,13 @@
import com.github.bordertech.wcomponents.util.Util;
import com.github.bordertech.wcomponents.util.thumbnail.ThumbnailUtil;
import java.awt.Dimension;
+import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -737,16 +739,13 @@ protected void doHandleUploadRequest(final Request request) {
// Wrap the file item
FileItemWrap wrap = new FileItemWrap(items[0]);
- // if fileType is supplied then validate it
- if (hasFileTypes() && !FileUtil.validateFileType(wrap, getFileTypes())) {
- String invalidMessage = FileUtil.getInvalidFileTypeMessage(getFileTypes());
- throw new SystemException(invalidMessage);
+ // Validate the file type
+ if (hasFileTypes()) {
+ doHandleUploadedFileTypeValidation(wrap);
}
-
- // if fileSize is supplied then validate it
- if (hasMaxFileSize() && !FileUtil.validateFileSize(wrap, getMaxFileSize())) {
- String invalidMessage = FileUtil.getInvalidFileSizeMessage(getMaxFileSize());
- throw new SystemException(invalidMessage);
+ // Validate the file size
+ if (hasMaxFileSize()) {
+ doHandleUploadedFileSizeValidation(wrap);
}
FileWidgetUpload file = new FileWidgetUpload(fileId, wrap);
@@ -757,6 +756,30 @@ protected void doHandleUploadRequest(final Request request) {
setNewUpload(true);
}
+ /**
+ * Perform file type validation on the uploaded file.
+ *
+ * @param wrap the file item to validate
+ */
+ protected void doHandleUploadedFileTypeValidation(final FileItemWrap wrap) {
+ if (!FileUtil.validateFileType(wrap, getFileTypes())) {
+ String invalidMessage = FileUtil.getInvalidFileTypeMessage(getFileTypes());
+ throw new SystemException(invalidMessage);
+ }
+ }
+
+ /**
+ * Perform file size validation on the uploaded file.
+ *
+ * @param wrap the file item to validate
+ */
+ protected void doHandleUploadedFileSizeValidation(final FileItemWrap wrap) {
+ if (!FileUtil.validateFileSize(wrap, getMaxFileSize())) {
+ String invalidMessage = FileUtil.getInvalidFileSizeMessage(getMaxFileSize());
+ throw new SystemException(invalidMessage);
+ }
+ }
+
/**
* Handle the thumb nail request.
*
@@ -778,8 +801,7 @@ protected void doHandleThumbnailRequest(final FileWidgetUpload file) {
* @param file the file to process
*/
protected void doHandleFileContentRequest(final FileWidgetUpload file) {
- ContentEscape escape = new ContentEscape(file.getFile());
- throw escape;
+ throw new ContentEscape(file.getFile());
}
/**
@@ -787,15 +809,13 @@ protected void doHandleFileContentRequest(final FileWidgetUpload file) {
* @return the thumbnail
*/
protected Image createThumbNail(final File file) {
- Image image = null;
- try {
+ try (InputStream stream = file.getInputStream()) {
Dimension size = getThumbnailSize();
- image = ThumbnailUtil.createThumbnail(file.getInputStream(), file.getName(), size, file.
- getMimeType());
+ return ThumbnailUtil.createThumbnail(stream, file.getName(), size, file.getMimeType());
} catch (Exception e) {
LOG.error("Could not generate thumbnail for file. " + e.getMessage(), e);
+ return null;
}
- return image;
}
/**
@@ -810,30 +830,10 @@ public String getFileUrl(final String fileId) {
return null;
}
- Environment env = getEnvironment();
- Map parameters = env.getHiddenParameters();
- parameters.put(Environment.TARGET_ID, getTargetId());
-
- if (Util.empty(file.getFileCacheKey())) {
- // Add some randomness to the URL to prevent caching
- String random = WebUtilities.generateRandom();
- parameters.put(Environment.UNIQUE_RANDOM_PARAM, random);
- } else {
- // Remove step counter as not required for cached content
- parameters.remove(Environment.STEP_VARIABLE);
- parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
- // Add the cache key
- parameters.put(Environment.CONTENT_CACHE_KEY, file.getFileCacheKey());
- }
-
// File id
+ Map parameters = new HashMap<>();
parameters.put(FILE_UPLOAD_ID_KEY, fileId);
-
- // The targetable path needs to be configured for the portal environment.
- String url = env.getWServletPath();
-
- // Note the last parameter. In javascript we don't want to encode "&".
- return WebUtilities.getPath(url, parameters, true);
+ return WebUtilities.createTargetUrl(this, file.getFileCacheKey(), parameters);
}
/**
@@ -854,33 +854,12 @@ public String getFileThumbnailUrl(final String fileId) {
return ((InternalResource) thumbnail).getTargetUrl();
}
- Environment env = getEnvironment();
- Map parameters = env.getHiddenParameters();
- parameters.put(Environment.TARGET_ID, getTargetId());
-
- if (Util.empty(file.getThumbnailCacheKey())) {
- // Add some randomness to the URL to prevent caching
- String random = WebUtilities.generateRandom();
- parameters.put(Environment.UNIQUE_RANDOM_PARAM, random);
- } else {
- // Remove step counter as not required for cached content
- parameters.remove(Environment.STEP_VARIABLE);
- parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
- // Add the cache key
- parameters.put(Environment.CONTENT_CACHE_KEY, file.getThumbnailCacheKey());
- }
-
+ Map parameters = new HashMap<>();
// File id
parameters.put(FILE_UPLOAD_ID_KEY, fileId);
-
// Thumbnail flag
parameters.put(FILE_UPLOAD_THUMB_NAIL_KEY, "Y");
-
- // The targetable path needs to be configured for the portal environment.
- String url = env.getWServletPath();
-
- // Note the last parameter. In javascript we don't want to encode "&".
- return WebUtilities.getPath(url, parameters, true);
+ return WebUtilities.createTargetUrl(this, file.getThumbnailCacheKey(), parameters);
}
/**
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WRepeater.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WRepeater.java
index 584b4e962..8b15189ab 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WRepeater.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WRepeater.java
@@ -12,7 +12,7 @@
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WTree.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WTree.java
index fc5b15248..33f9c4376 100644
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WTree.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WTree.java
@@ -454,32 +454,10 @@ public String getItemImageUrl(final TreeItemImage item, final String itemId) {
}
// Build targetted url
- Environment env = getEnvironment();
- Map parameters = env.getHiddenParameters();
- parameters.put(Environment.TARGET_ID, getTargetId());
-
- String cacheKey = item.getImageCacheKey();
-
- if (Util.empty(cacheKey)) {
- // Add some randomness to the URL to prevent caching
- String random = WebUtilities.generateRandom();
- parameters.put(Environment.UNIQUE_RANDOM_PARAM, random);
- } else {
- // Remove step counter as not required for cached content
- parameters.remove(Environment.STEP_VARIABLE);
- parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
- // Add the cache key
- parameters.put(Environment.CONTENT_CACHE_KEY, cacheKey);
- }
-
+ Map parameters = new HashMap<>();
// Item id
parameters.put(ITEM_REQUEST_KEY, itemId);
-
- // The targetable path needs to be configured for the portal environment.
- url = env.getWServletPath();
-
- // Note the last parameter. In javascript we don't want to encode "&".
- return WebUtilities.getPath(url, parameters, true);
+ return WebUtilities.createTargetUrl(this, item.getImageCacheKey(), parameters);
}
/**
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WVideo.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WVideo.java
index 38f908a0c..54a2db45a 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WVideo.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WVideo.java
@@ -2,10 +2,10 @@
import com.github.bordertech.wcomponents.util.Util;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -446,14 +446,11 @@ public String[] getVideoUrls() {
}
String[] urls = new String[video.length];
-
- // this variable needs to be set in the portlet environment.
- String url = getEnvironment().getWServletPath();
- Map parameters = getBaseParameterMap();
-
+ String cacheKey = getCacheKey();
+ Map parameters = new HashMap<>();
for (int i = 0; i < urls.length; i++) {
parameters.put(VIDEO_INDEX_REQUEST_PARAM_KEY, String.valueOf(i));
- urls[i] = WebUtilities.getPath(url, parameters, true);
+ urls[i] = WebUtilities.createTargetUrl(this, cacheKey, parameters);
}
return urls;
@@ -474,14 +471,11 @@ public String[] getTrackUrls() {
}
String[] urls = new String[tracks.length];
-
- // this variable needs to be set in the portlet environment.
- String url = getEnvironment().getWServletPath();
- Map parameters = getBaseParameterMap();
-
+ String cacheKey = getCacheKey();
+ Map parameters = new HashMap<>();
for (int i = 0; i < urls.length; i++) {
parameters.put(TRACK_INDEX_REQUEST_PARAM_KEY, String.valueOf(i));
- urls[i] = WebUtilities.getPath(url, parameters, true);
+ urls[i] = WebUtilities.createTargetUrl(this, cacheKey, parameters);
}
return urls;
@@ -501,36 +495,9 @@ public String getPosterUrl() {
return null;
}
- // this variable needs to be set in the portlet environment.
- String url = getEnvironment().getWServletPath();
- Map parameters = getBaseParameterMap();
+ Map parameters = new HashMap<>();
parameters.put(POSTER_REQUEST_PARAM_KEY, "x");
- return WebUtilities.getPath(url, parameters, true);
- }
-
- /**
- * Retrieves the base parameter map for serving content (videos + tracks).
- *
- * @return the base map for serving content.
- */
- private Map getBaseParameterMap() {
- Environment env = getEnvironment();
- Map parameters = env.getHiddenParameters();
- parameters.put(Environment.TARGET_ID, getTargetId());
-
- if (Util.empty(getCacheKey())) {
- // Add some randomness to the URL to prevent caching
- String random = WebUtilities.generateRandom();
- parameters.put(Environment.UNIQUE_RANDOM_PARAM, random);
- } else {
- // Remove step counter as not required for cached content
- parameters.remove(Environment.STEP_VARIABLE);
- parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
- // Add the cache key
- parameters.put(Environment.CONTENT_CACHE_KEY, getCacheKey());
- }
-
- return parameters;
+ return WebUtilities.createTargetUrl(this, getCacheKey(), parameters);
}
/**
@@ -559,7 +526,6 @@ public boolean isVisible() {
public void handleRequest(final Request request) {
super.handleRequest(request);
-
String targ = request.getParameter(Environment.TARGET_ID);
boolean contentReqested = (targ != null && targ.equals(getTargetId()));
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WWindow.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WWindow.java
index 123819e3b..5576d9b89 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WWindow.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WWindow.java
@@ -351,6 +351,8 @@ public String getUrl() {
parameters.put(WWINDOW_REQUEST_PARAM_KEY, getId());
// Override the step count with WWindow step
parameters.put(Environment.STEP_VARIABLE, String.valueOf(getStep()));
+ // Remove session token as this should not be exposed on GET URLs (CSRF Rules)
+ parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
String url = env.getWServletPath();
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WebUtilities.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WebUtilities.java
index 512501bbe..af28ca968 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WebUtilities.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/WebUtilities.java
@@ -428,6 +428,55 @@ public static String doubleDecodeBrackets(final String input) {
return DOUBLE_DECODE_BRACKETS.translate(input);
}
+ /**
+ * Create the URL for a targetable component.
+ *
+ * @param target the targetable component
+ * @param cacheKey the cacheKey or otherwise null
+ * @return the URL for the content of a targetable component
+ */
+ public static String createTargetUrl(final Targetable target, final String cacheKey) {
+ return createTargetUrl(target, cacheKey, null);
+ }
+
+ /**
+ * Create the URL for a targetable component with additional parameters.
+ *
+ * @param target the targetable component
+ * @param cacheKey the cacheKey or otherwise null
+ * @param additionalParams the additional parameters to include on url or otherwise null
+ * @return the URL for the content of a targetable component
+ */
+ public static String createTargetUrl(final Targetable target, final String cacheKey, final Map additionalParams) {
+
+ Environment env = target.getEnvironment();
+
+ Map parameters = env.getHiddenParameters();
+ // Remove session token as this should not be exposed on GET URLs (CSRF Rules)
+ parameters.remove(Environment.SESSION_TOKEN_VARIABLE);
+
+ // Add the target id
+ parameters.put(Environment.TARGET_ID, target.getTargetId());
+
+ if (Util.empty(cacheKey)) {
+ // Add some randomness to the URL to prevent caching
+ parameters.put(Environment.UNIQUE_RANDOM_PARAM, WebUtilities.generateRandom());
+ } else {
+ // Add the cache key
+ parameters.put(Environment.CONTENT_CACHE_KEY, cacheKey);
+ // Remove step counter as not required for cached content
+ parameters.remove(Environment.STEP_VARIABLE);
+ }
+
+ // Add additional parameters
+ if (additionalParams != null) {
+ parameters.putAll(additionalParams);
+ }
+
+ // Build URL
+ return getPath(env.getWServletPath(), parameters, true);
+ }
+
/**
* Adds GET parameters to a path.
*
@@ -449,6 +498,12 @@ public static String getPath(final String url, final Map paramet
*/
public static String getPath(final String url, final Map parameters,
final boolean javascript) {
+
+ // Check URL provided
+ if (url == null) {
+ throw new IllegalArgumentException("URL must be provided.");
+ }
+
// Have we already got some parameters?
int index = url.indexOf('?');
boolean hasVars = false;
@@ -697,8 +752,8 @@ public static String render(final Request request, final WComponent component) {
component.preparePaint(request);
try (PrintWriter writer = new PrintWriter(buffer)) {
component.paint(new WebXmlRenderContext(writer));
+ return buffer.toString();
}
- return buffer.toString();
} finally {
if (needsContext) {
UIContextHolder.popContext();
@@ -752,8 +807,8 @@ public static String renderWithTransformToHTML(final Request request, final WCom
chain.preparePaint(request);
try (PrintWriter writer = new PrintWriter(buffer)) {
chain.paint(new WebXmlRenderContext(writer));
+ return buffer.toString();
}
- return buffer.toString();
} finally {
if (needsContext) {
UIContextHolder.popContext();
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenAjaxInterceptor.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenAjaxInterceptor.java
index 36730e987..d0bcbc9c3 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenAjaxInterceptor.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenAjaxInterceptor.java
@@ -5,6 +5,8 @@
import com.github.bordertech.wcomponents.UIContext;
import com.github.bordertech.wcomponents.UIContextHolder;
import com.github.bordertech.wcomponents.util.Util;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* This session token interceptor makes sure the ajax request being processed is for the correct session.
@@ -17,6 +19,11 @@
*/
public class SessionTokenAjaxInterceptor extends InterceptorComponent {
+ /**
+ * The logger instance for this class.
+ */
+ private static final Log LOG = LogFactory.getLog(SessionTokenAjaxInterceptor.class);
+
/**
* Override to check whether the session token variable in the incoming request matches what we expect.
*
@@ -38,14 +45,19 @@ public void serviceRequest(final Request request) {
// Get the session token from the AJAX request
String got = request.getParameter(Environment.SESSION_TOKEN_VARIABLE);
- // Check tokens match (both must be provided)
- if (Util.equals(expected, got)) {
+ // Session token should not be provided on a GET URL (CSRF Rules)
+ if (got != null && "GET".equals(request.getMethod())) {
+ throw new IllegalStateException("A session token should not be provided on a GET");
+ }
+
+ // Check processing a GET or tokens must match
+ if ("GET".equals(request.getMethod()) || (got != null && Util.equals(expected, got))) {
// Process AJAX request
getBackingComponent().serviceRequest(request);
} else {
// Invalid token on AJAX request
- throw new SessionTokenException("Wrong session token detected for AJAX request. Expected token ["
- + expected + "] but got token [" + got + "].");
+ LOG.debug("Wrong session token detected for AJAX request. Expected token [" + expected + "] but got token [" + got + "].");
+ throw new SessionTokenException("Wrong session token detected for AJAX request.");
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenContentInterceptor.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenContentInterceptor.java
index 6d35fc0a2..d12b4776f 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenContentInterceptor.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenContentInterceptor.java
@@ -4,16 +4,9 @@
import com.github.bordertech.wcomponents.Request;
import com.github.bordertech.wcomponents.UIContext;
import com.github.bordertech.wcomponents.UIContextHolder;
-import com.github.bordertech.wcomponents.WImage;
-import com.github.bordertech.wcomponents.util.StepCountUtil;
-import com.github.bordertech.wcomponents.util.Util;
/**
- * This session token interceptor makes sure the content request being processed is for the correct session.
- *
- * Similar to {@link SessionTokenInterceptor} but caters for setting error codes for content requests such as
- * {@link WImage} when a token error is detected.
- *
+ * This session token interceptor makes sure the session token on content requests are handled correctly for CSRF.
*
* @author Jonathan Austin
* @since 1.0.0
@@ -21,14 +14,14 @@
public class SessionTokenContentInterceptor extends InterceptorComponent {
/**
- * Override to check whether the session token variable in the incoming request matches what we expect.
+ * Override to check whether the session token is handled correctly for CSRF.
*
* @param request the request being serviced.
*/
@Override
public void serviceRequest(final Request request) {
- // Get the expected session token
+ // Get the current session token
UIContext uic = UIContextHolder.getCurrent();
String expected = uic.getEnvironment().getSessionToken();
@@ -38,19 +31,19 @@ public void serviceRequest(final Request request) {
+ " Can be due to the session timing out.");
}
- // Get the session token from the content request
- String got = request.getParameter(Environment.SESSION_TOKEN_VARIABLE);
+ // Content requests should only be a GET (CSRF Rules)
+ if (!"GET".equals(request.getMethod())) {
+ throw new IllegalStateException("Content request should only be a GET");
+ }
- // Check tokens match (both must be provided) or check if cached content (no session token on request)
- if (Util.equals(expected, got) || (got == null && StepCountUtil.isCachedContentRequest(request))) {
- // Process content request
- getBackingComponent().serviceRequest(request);
- } else {
- // Invalid token on content request
- throw new SessionTokenException("Wrong session token detected for content request. Expected token ["
- + expected + "] but got token [" + got + "].");
+ // Check no session token on the content request (CSRF Rules)
+ String got = request.getParameter(Environment.SESSION_TOKEN_VARIABLE);
+ if (got != null) {
+ throw new IllegalStateException("A session token should not be provided on a GET");
}
+ getBackingComponent().serviceRequest(request);
+
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenInterceptor.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenInterceptor.java
index 20430b516..737b2a613 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenInterceptor.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/SessionTokenInterceptor.java
@@ -6,12 +6,13 @@
import com.github.bordertech.wcomponents.UIContextHolder;
import com.github.bordertech.wcomponents.util.Util;
import java.util.UUID;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* This session token interceptor makes sure the request being processed is for the correct session.
*
- * As the token is a UUID, it will be much harder for CSRF attacks. No request processing will occur without the correct
- * UUID.
+ * As the token is a UUID, it will be much harder for CSRF attacks. No request processing will occur without the correct UUID.
*
*
* @author Jonathan Austin
@@ -19,6 +20,11 @@
*/
public class SessionTokenInterceptor extends InterceptorComponent {
+ /**
+ * The logger instance for this class.
+ */
+ private static final Log LOG = LogFactory.getLog(SessionTokenInterceptor.class);
+
/**
* Override to check whether the session token variable in the incoming request matches what we expect.
*
@@ -26,27 +32,31 @@ public class SessionTokenInterceptor extends InterceptorComponent {
*/
@Override
public void serviceRequest(final Request request) {
- // Get the expected session token
+
+ // Get the expected session token (could be null for new session)
UIContext uic = UIContextHolder.getCurrent();
String expected = uic.getEnvironment().getSessionToken();
// Get the session token from the request
String got = request.getParameter(Environment.SESSION_TOKEN_VARIABLE);
- // Check tokens match (Both null if new session)
- // or processing a GET and no token
- if (Util.equals(expected, got) || (got == null && "GET".equals(request.getMethod()))) {
+ // Session token should not be provided on a GET URL (CSRF Rules)
+ if (got != null && "GET".equals(request.getMethod())) {
+ throw new IllegalStateException("A session token should not be provided on a GET");
+ }
+
+ // Check processing a GET or tokens must match
+ if ("GET".equals(request.getMethod()) || (got != null && Util.equals(expected, got))) {
// Process request
getBackingComponent().serviceRequest(request);
- } else { // Invalid token
- String msg;
- if (expected == null && got != null) {
- msg = "Session for token [" + got + "] is no longer valid or timed out.";
- } else {
- msg = "Wrong session token detected for servlet request. Expected token [" + expected
- + "] but got token [" + got + "].";
- }
- throw new SessionTokenException(msg);
+ } else if (expected == null && got != null) {
+ // Expired token
+ LOG.debug("Session for token [" + got + "] is no longer valid or timed out.");
+ throw new SessionTokenException("Session for token is no longer valid or timed out.");
+ } else {
+ // Wrong token
+ LOG.debug("Wrong session token detected for servlet request. Expected token [" + expected + "] but got token [" + got + "].");
+ throw new SessionTokenException("Wrong session token detected for servlet request.");
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/TransformXMLInterceptor.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/TransformXMLInterceptor.java
index cb872de8a..37c697982 100644
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/TransformXMLInterceptor.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/container/TransformXMLInterceptor.java
@@ -186,15 +186,14 @@ public void paint(final RenderContext renderContext) {
private void transform(final String xml, final UIContext uic, final PrintWriter writer) {
Transformer transformer = newTransformer();
- Source inputXml;
- try {
- inputXml = new StreamSource(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
+ try (InputStream inStream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
+ Source inputXml = new StreamSource(inStream);
StreamResult result = new StreamResult(writer);
if (debugRequested) {
transformer.setParameter("isDebug", 1);
}
transformer.transform(inputXml, result);
- } catch (TransformerException ex) {
+ } catch (TransformerException | IOException ex) {
throw new SystemException("Could not transform xml", ex);
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/file/FileItemWrap.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/file/FileItemWrap.java
index e99802be5..4d53417e2 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/file/FileItemWrap.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/file/FileItemWrap.java
@@ -26,6 +26,13 @@ public FileItemWrap(final FileItem item) {
backing = item;
}
+ /**
+ * @return the backing file item.
+ */
+ public FileItem getBacking() {
+ return backing;
+ }
+
/**
* The name of the file as supplied by the client. Depending on the client this may or may not include the full path
* to the file.
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/monitor/UicStats.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/monitor/UicStats.java
index 675eb91ba..7d29e96f1 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/monitor/UicStats.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/monitor/UicStats.java
@@ -86,8 +86,7 @@ public Iterator getWCsAnalysed() {
}
/**
- * Retrieves the map wchich contains all the WComponent instances that make up the WComponent tree starting from the
- * given root component.
+ * Retrieves the map wchich contains all the WComponent instances that make up the WComponent tree starting from the given root component.
*
* @param root the root component.
* @return the map of Stats for the components under the given root component.
@@ -205,12 +204,8 @@ private Stat createStat(final WComponent comp) {
* @return the serialized size of the given object, or -1 on error.
*/
private int getSerializationSize(final Object obj) {
- try {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(bos);
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(obj);
- oos.close();
-
byte[] bytes = bos.toByteArray();
return bytes.length;
} catch (IOException ex) {
@@ -225,17 +220,18 @@ private int getSerializationSize(final Object obj) {
*/
private void addSerializationStat(final ComponentModel model, final Stat stat) {
try {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(bos);
- oos.writeObject(model);
- oos.close();
-
- byte[] bytes = bos.toByteArray();
+ // Calc size
+ byte[] bytes;
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+ oos.writeObject(model);
+ bytes = bos.toByteArray();
+ }
stat.setSerializedSize(bytes.length);
- ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
- ObjectInputStream ois = new ObjectInputStream(bis);
- ois.readObject();
+ // Check serializable
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis)) {
+ ois.readObject();
+ }
stat.setModelState(Stat.MDL_SERIALIZABLE);
} catch (Exception ex) {
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/render/webxml/WApplicationRenderer.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/render/webxml/WApplicationRenderer.java
index 082c812af..3fe4030bb 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/render/webxml/WApplicationRenderer.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/render/webxml/WApplicationRenderer.java
@@ -1,10 +1,12 @@
package com.github.bordertech.wcomponents.render.webxml;
+import com.github.bordertech.wcomponents.Environment;
import com.github.bordertech.wcomponents.Renderer;
import com.github.bordertech.wcomponents.UIContext;
import com.github.bordertech.wcomponents.UIContextHolder;
import com.github.bordertech.wcomponents.WApplication;
import com.github.bordertech.wcomponents.WComponent;
+import com.github.bordertech.wcomponents.WebUtilities;
import com.github.bordertech.wcomponents.XmlStringBuilder;
import com.github.bordertech.wcomponents.servlet.WebXmlRenderContext;
import com.github.bordertech.wcomponents.util.TrackingUtil;
@@ -45,11 +47,20 @@ public void doRender(final WComponent component, final WebXmlRenderContext rende
LOG.warn("WApplication component should be the top level component.");
}
+ // Build AJAX url (add hidden parameters that was previously added by XSL)
+ String ajaxUrl = uic.getEnvironment().getWServletPath();
+ if (ajaxUrl != null) {
+ Map params = uic.getEnvironment().getHiddenParameters();
+ // Dont add session token on URL (CSRF Rules)
+ params.remove(Environment.SESSION_TOKEN_VARIABLE);
+ ajaxUrl = WebUtilities.getPath(ajaxUrl, params, true);
+ }
+
xml.appendTagOpen("ui:application");
xml.appendAttribute("id", component.getId());
xml.appendOptionalAttribute("class", component.getHtmlClass());
xml.appendUrlAttribute("applicationUrl", uic.getEnvironment().getPostPath());
- xml.appendUrlAttribute("ajaxUrl", uic.getEnvironment().getWServletPath());
+ xml.appendUrlAttribute("ajaxUrl", ajaxUrl);
xml.appendOptionalAttribute("unsavedChanges", application.hasUnsavedChanges(), "true");
xml.appendOptionalAttribute("title", application.getTitle());
xml.appendOptionalAttribute("defaultFocusId", uic.isFocusRequired() && !Util.empty(focusId),
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/servlet/ServletUtil.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/servlet/ServletUtil.java
index 1a7442bdc..74cc73634 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/servlet/ServletUtil.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/servlet/ServletUtil.java
@@ -20,7 +20,6 @@
import com.github.bordertech.wcomponents.container.DataListInterceptor;
import com.github.bordertech.wcomponents.container.DebugStructureInterceptor;
import com.github.bordertech.wcomponents.container.FormInterceptor;
-import com.github.bordertech.wcomponents.container.TemplateRenderInterceptor;
import com.github.bordertech.wcomponents.container.InterceptorComponent;
import com.github.bordertech.wcomponents.container.PageShellInterceptor;
import com.github.bordertech.wcomponents.container.ResponseCacheInterceptor;
@@ -31,6 +30,7 @@
import com.github.bordertech.wcomponents.container.SubordinateControlInterceptor;
import com.github.bordertech.wcomponents.container.TargetableErrorInterceptor;
import com.github.bordertech.wcomponents.container.TargetableInterceptor;
+import com.github.bordertech.wcomponents.container.TemplateRenderInterceptor;
import com.github.bordertech.wcomponents.container.TransformXMLInterceptor;
import com.github.bordertech.wcomponents.container.UIContextDumpInterceptor;
import com.github.bordertech.wcomponents.container.ValidateXMLInterceptor;
@@ -229,38 +229,39 @@ public static void handleStaticResourceRequest(final HttpServletRequest request,
return;
}
- InputStream resourceStream = staticResource.getStream();
- if (resourceStream == null) {
- LOG.warn(
- "Static resource [" + staticRequest + "] not found. Stream for content is null.");
- response.setStatus(HttpServletResponse.SC_NOT_FOUND);
- return;
- }
-
- int size = resourceStream.available();
- String fileName = WebUtilities.encodeForContentDispositionHeader(staticRequest.
- substring(staticRequest
- .lastIndexOf('/') + 1));
+ try (InputStream resourceStream = staticResource.getStream()) {
+ if (resourceStream == null) {
+ LOG.warn(
+ "Static resource [" + staticRequest + "] not found. Stream for content is null.");
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ return;
+ }
- if (size > 0) {
- response.setContentLength(size);
- }
+ int size = resourceStream.available();
+ String fileName = WebUtilities.encodeForContentDispositionHeader(staticRequest.
+ substring(staticRequest
+ .lastIndexOf('/') + 1));
- response.setContentType(WebUtilities.getContentType(staticRequest));
- response.setHeader("Cache-Control", CacheType.CONTENT_CACHE.getSettings());
+ if (size > 0) {
+ response.setContentLength(size);
+ }
- String param = request.getParameter(WContent.URL_CONTENT_MODE_PARAMETER_KEY);
- if ("inline".equals(param)) {
- response.setHeader("Content-Disposition", "inline; filename=" + fileName);
- } else if ("attach".equals(param)) {
- response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
- } else {
- // added "filename=" to comply with https://tools.ietf.org/html/rfc6266
- response.setHeader("Content-Disposition", "filename=" + fileName);
- }
+ response.setContentType(WebUtilities.getContentType(staticRequest));
+ response.setHeader("Cache-Control", CacheType.CONTENT_CACHE.getSettings());
+
+ String param = request.getParameter(WContent.URL_CONTENT_MODE_PARAMETER_KEY);
+ if ("inline".equals(param)) {
+ response.setHeader("Content-Disposition", "inline; filename=" + fileName);
+ } else if ("attach".equals(param)) {
+ response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
+ } else {
+ // added "filename=" to comply with https://tools.ietf.org/html/rfc6266
+ response.setHeader("Content-Disposition", "filename=" + fileName);
+ }
- if (!headersOnly) {
- StreamUtil.copy(resourceStream, response.getOutputStream());
+ if (!headersOnly) {
+ StreamUtil.copy(resourceStream, response.getOutputStream());
+ }
}
} catch (IOException e) {
LOG.warn("Could not process static resource [" + staticRequest + "]. ", e);
@@ -312,34 +313,33 @@ public static void handleThemeResourceRequest(final HttpServletRequest req,
return;
}
- InputStream resourceStream = null;
+ URL url = null;
- try {
- URL url = null;
+ // Check for project translation file
+ if (fileName.startsWith(THEME_TRANSLATION_RESOURCE_PREFIX)) {
+ String resourceFileName = fileName.substring(THEME_TRANSLATION_RESOURCE_PREFIX.length());
+ url = ServletUtil.class.getResource(THEME_PROJECT_TRANSLATION_RESOURCE_PATH + resourceFileName);
+ }
- // Check for project translation file
- if (fileName.startsWith(THEME_TRANSLATION_RESOURCE_PREFIX)) {
- String resourceFileName = fileName.substring(THEME_TRANSLATION_RESOURCE_PREFIX.length());
- url = ServletUtil.class.getResource(THEME_PROJECT_TRANSLATION_RESOURCE_PATH + resourceFileName);
- }
+ // Load from the theme path
+ if (url == null) {
+ String resourceName = ThemeUtil.getThemeBase() + fileName;
+ url = ServletUtil.class.getResource(resourceName);
+ }
- // Load from the theme path
- if (url == null) {
- String resourceName = ThemeUtil.getThemeBase() + fileName;
- url = ServletUtil.class.getResource(resourceName);
- }
+ if (url == null) {
+ resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ return;
+ }
- if (url == null) {
- resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
- } else {
- URLConnection connection = url.openConnection();
- resourceStream = connection.getInputStream();
- int size = resourceStream.available();
- if (size > 0) {
- resp.setContentLength(size);
- }
+ URLConnection connection = url.openConnection();
+ try (InputStream resourceStream = connection.getInputStream()) {
+ int size = resourceStream.available();
+ if (size > 0) {
+ resp.setContentLength(size);
+ }
- /*
+ /*
I have commented out the setting of the Content-Disposition on static theme resources because, well why is it there?
If this needs to be reinstated please provide a thorough justification comment here so the reasons are clear.
@@ -349,19 +349,16 @@ public static void handleThemeResourceRequest(final HttpServletRequest req,
substring(fileName
.lastIndexOf('/') + 1));
resp.setHeader("Content-Disposition", "filename=" + encodedName); // "filename=" to comply with https://tools.ietf.org/html/rfc6266
- */
- resp.setContentType(WebUtilities.getContentType(fileName));
- resp.setHeader("Cache-Control", CacheType.THEME_CACHE.getSettings());
-
- resp.setHeader("Expires", "31536000");
- resp.setHeader("ETag", "\"" + WebUtilities.getProjectVersion() + "\"");
- // resp.setHeader("Last-Modified", "Mon, 02 Jan 2015 01:00:00 GMT");
- long modified = connection.getLastModified();
- resp.setDateHeader("Last-Modified", modified);
- StreamUtil.copy(resourceStream, resp.getOutputStream());
- }
- } finally {
- StreamUtil.safeClose(resourceStream);
+ */
+ resp.setContentType(WebUtilities.getContentType(fileName));
+ resp.setHeader("Cache-Control", CacheType.THEME_CACHE.getSettings());
+
+ resp.setHeader("Expires", "31536000");
+ resp.setHeader("ETag", "\"" + WebUtilities.getProjectVersion() + "\"");
+ // resp.setHeader("Last-Modified", "Mon, 02 Jan 2015 01:00:00 GMT");
+ long modified = connection.getLastModified();
+ resp.setDateHeader("Last-Modified", modified);
+ StreamUtil.copy(resourceStream, resp.getOutputStream());
}
}
@@ -650,6 +647,7 @@ public static void extractParameterMap(final HttpServletRequest request, final M
/**
* Find the value of a cookie on the request, by name.
+ *
* @param request The request on which to check for the cookie.
* @param name The name of the cookie we want the value of.
* @return The value of the cookie, if present, otherwise null.
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/template/PlainTextRendererImpl.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/template/PlainTextRendererImpl.java
index ec7cd2e9e..4d3b0b360 100644
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/template/PlainTextRendererImpl.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/template/PlainTextRendererImpl.java
@@ -71,8 +71,6 @@ public void renderTemplate(final String templateName, final Map
boolean xmlEncode = options.containsKey(XML_ENCODE);
String cacheKey = templateName + "-" + xmlEncode;
- InputStream stream = null;
-
// Caching
Object value = options.get(USE_CACHE);
boolean cache = (isCaching() && value == null) || (value != null && "true".equalsIgnoreCase(value.toString()));
@@ -83,11 +81,12 @@ public void renderTemplate(final String templateName, final Map
output = getCache().get(cacheKey);
}
if (output == null) {
- stream = getClass().getResourceAsStream(name);
- if (stream == null) {
- throw new SystemException("Could not find plain text template [" + templateName + "].");
+ try (InputStream stream = getClass().getResourceAsStream(name)) {
+ if (stream == null) {
+ throw new SystemException("Could not find plain text template [" + templateName + "].");
+ }
+ output = new String(StreamUtil.getBytes(stream), StandardCharsets.UTF_8);
}
- output = new String(StreamUtil.getBytes(stream), StandardCharsets.UTF_8);
if (xmlEncode) {
output = WebUtilities.encode(output);
}
@@ -100,8 +99,6 @@ public void renderTemplate(final String templateName, final Map
throw e;
} catch (Exception e) {
throw new SystemException("Problems with plain text template [" + templateName + "]. " + e.getMessage(), e);
- } finally {
- StreamUtil.safeClose(stream);
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/DefaultInternalConfiguration.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/DefaultInternalConfiguration.java
index e0f1ca9ae..571953393 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/DefaultInternalConfiguration.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/DefaultInternalConfiguration.java
@@ -435,11 +435,11 @@ private void load(final String resourceName) {
byte[] buff = contentsList.get(i);
URL url = urlList.get(i);
recordMessage("Loading from url " + url + "...");
- ByteArrayInputStream in = new ByteArrayInputStream(buff);
-
// Use the "IncludeProperties" to load properties into us one at a time....
IncludeProperties properties = new IncludeProperties(url.toString());
- properties.load(in);
+ try (ByteArrayInputStream in = new ByteArrayInputStream(buff)) {
+ properties.load(in);
+ }
}
File file = new File(resourceName);
@@ -451,7 +451,9 @@ private void load(final String resourceName) {
// Use the "IncludeProperties" to load properties into us, one at a time....
IncludeProperties properties = new IncludeProperties("file:" + filename(file));
- properties.load(new BufferedInputStream(new FileInputStream(file)));
+ try (InputStream fileStream = new FileInputStream(file); InputStream stream = new BufferedInputStream(fileStream)) {
+ properties.load(stream);
+ }
}
if (!found) {
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/FileUtil.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/FileUtil.java
index 248bcffec..0afc420a8 100644
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/FileUtil.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/FileUtil.java
@@ -2,14 +2,17 @@
import com.github.bordertech.wcomponents.file.File;
import com.github.bordertech.wcomponents.file.FileItemWrap;
+import java.io.BufferedInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.tika.Tika;
+import org.overviewproject.mime_types.GetBytesException;
+import org.overviewproject.mime_types.MimeTypeDetector;
/**
* Utility methods for {@link File}.
@@ -31,13 +34,11 @@ private FileUtil() {
private static final Log LOG = LogFactory.getLog(FileUtil.class);
/**
- * Checks if the file item is one among the supplied file types.
- * This first checks against file extensions, then against file mime types
+ * Checks if the file item is one among the supplied file types. This first checks against file extensions, then
+ * against file mime types
*
- * @param newFile the file to be checked, if null then return false
- * otherwise validate
- * @param fileTypes allowed file types, if null or empty return true,
- * otherwise validate
+ * @param newFile the file to be checked, if null then return false otherwise validate
+ * @param fileTypes allowed file types, if null or empty return true, otherwise validate
* @return {@code true} if either extension or mime-type match is successful
*/
public static boolean validateFileType(final FileItemWrap newFile, final List fileTypes) {
@@ -50,36 +51,41 @@ public static boolean validateFileType(final FileItemWrap newFile, final List fileExts = fileTypes.stream()
- .filter(fileType -> fileType.startsWith("."))
- .collect(Collectors.toList());
- // filter mime types from fileTypes.
+ .filter(fileType -> fileType.startsWith("."))
+ .collect(Collectors.toList());
+ // Filter mime types
final List fileMimes = fileTypes.stream()
- .filter(fileType -> !fileExts.contains(fileType))
- .collect(Collectors.toList());
+ .filter(fileType -> !fileExts.contains(fileType))
+ .collect(Collectors.toList());
// First validate newFile against fileExts list
// If extensions are supplied, then check if newFile has a name
- if (fileExts.size() > 0 && newFile.getName() != null) {
+ if (!fileExts.isEmpty() && newFile.getName() != null) {
// Then see if newFile has an extension
String[] split = newFile.getName().split(("\\.(?=[^\\.]+$)"));
// If it exists, then check if it matches supplied extension(s)
if (split.length == 2
- && fileExts.stream().anyMatch(fileExt -> fileExt.equals("." + split[1]))) {
+ && fileExts.stream().anyMatch(fileExt -> fileExt.equalsIgnoreCase("." + split[1]))) {
return true;
}
}
// If extension match is unsucessful, then move to fileMimes list
- if (fileMimes.size() > 0) {
+ if (!fileMimes.isEmpty()) {
final String mimeType = getFileMimeType(newFile);
+ if (mimeType == null) {
+ return false;
+ }
LOG.debug("File mime-type is: " + mimeType);
for (String fileMime : fileMimes) {
- if (StringUtils.equals(mimeType, fileMime)) {
+ if (mimeType.equalsIgnoreCase(fileMime)) {
return true;
}
if (fileMime.indexOf("*") == fileMime.length() - 1) {
- fileMime = fileMime.substring(0, fileMime.length() - 1);
- if (mimeType.indexOf(fileMime) == 0) {
+ String fileMimePrefix = fileMime.substring(0, fileMime.length() - 1).toLowerCase();
+ String lcMimeType = mimeType.toLowerCase();
+ if (lcMimeType.startsWith(fileMimePrefix)) {
return true;
}
}
@@ -92,14 +98,13 @@ public static boolean validateFileType(final FileItemWrap newFile, final List fileTypes) {
return null;
}
return String.format(I18nUtilities.format(null,
- InternalMessages.DEFAULT_VALIDATION_ERROR_FILE_WRONG_TYPE),
- StringUtils.join(fileTypes.toArray(new Object[fileTypes.size()]), ","));
+ InternalMessages.DEFAULT_VALIDATION_ERROR_FILE_WRONG_TYPE),
+ StringUtils.join(fileTypes.toArray(new Object[fileTypes.size()]), ","));
}
/**
@@ -166,6 +169,6 @@ public static String getInvalidFileTypeMessage(final List fileTypes) {
*/
public static String getInvalidFileSizeMessage(final long maxFileSize) {
return String.format(I18nUtilities.format(null, InternalMessages.DEFAULT_VALIDATION_ERROR_FILE_WRONG_SIZE),
- FileUtil.readableFileSize(maxFileSize));
+ FileUtil.readableFileSize(maxFileSize));
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/HtmlSanitizerUtil.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/HtmlSanitizerUtil.java
index 885d26d1d..9422607dc 100644
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/HtmlSanitizerUtil.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/HtmlSanitizerUtil.java
@@ -1,6 +1,7 @@
package com.github.bordertech.wcomponents.util;
import com.github.bordertech.wcomponents.WebUtilities;
+import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
@@ -151,13 +152,12 @@ public static Policy createPolicy(final String resourceName) {
if (StringUtils.isBlank(resourceName)) {
throw new SystemException("AntiSamy Policy resourceName cannot be null ");
}
- InputStream resource = HtmlSanitizerUtil.class.getClassLoader().getResourceAsStream(resourceName);
- if (resource == null) {
- throw new SystemException("Could not find AntiSamy Policy XML resource.");
- }
- try {
+ try (InputStream resource = HtmlSanitizerUtil.class.getClassLoader().getResourceAsStream(resourceName)) {
+ if (resource == null) {
+ throw new SystemException("Could not find AntiSamy Policy XML resource.");
+ }
return Policy.getInstance(resource);
- } catch (PolicyException ex) {
+ } catch (IOException | PolicyException ex) {
throw new SystemException("Could not create AntiSamy Policy" + ex.getMessage(), ex);
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/SerializationUtil.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/SerializationUtil.java
index c6a8e42db..e04b9d1a8 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/SerializationUtil.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/SerializationUtil.java
@@ -26,16 +26,15 @@ private SerializationUtil() {
*/
public static Object pipe(final Object in) {
try {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream os = new ObjectOutputStream(bos);
- os.writeObject(in);
- os.close();
+ byte[] bytes;
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(bos)) {
+ os.writeObject(in);
+ bytes = bos.toByteArray();
+ }
- byte[] bytes = bos.toByteArray();
- ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
- ObjectInputStream is = new ObjectInputStream(bis);
- Object out = is.readObject();
- return out;
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream is = new ObjectInputStream(bis)) {
+ return is.readObject();
+ }
} catch (Exception ex) {
throw new SystemException("Failed to pipe " + in, ex);
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/StreamUtil.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/StreamUtil.java
index 5c6bffc43..7b9e2521f 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/StreamUtil.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/StreamUtil.java
@@ -72,10 +72,10 @@ public static void copy(final InputStream in, final OutputStream out, final int
* @throws IOException if there is an error reading from the stream.
*/
public static byte[] getBytes(final InputStream in) throws IOException {
- ByteArrayOutputStream result = new ByteArrayOutputStream();
- copy(in, result);
- result.close();
- return result.toByteArray();
+ try (ByteArrayOutputStream result = new ByteArrayOutputStream()) {
+ copy(in, result);
+ return result.toByteArray();
+ }
}
/**
@@ -101,9 +101,9 @@ public static void safeClose(final Closeable stream) {
* @throws IOException If there is an error reading from the is.
*/
public static byte[] streamToByteArray(final InputStream is) throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- copy(is, baos);
- byte[] bytes = baos.toByteArray();
- return bytes;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ copy(is, baos);
+ return baos.toByteArray();
+ }
}
}
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/ThemeUtil.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/ThemeUtil.java
index 10b4f41d9..812c9120d 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/ThemeUtil.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/ThemeUtil.java
@@ -55,12 +55,10 @@ public final class ThemeUtil {
String resourceName = THEME_BASE + THEME_VERSION_FILE_NAME;
// Get theme version property file (if in classpath)
- InputStream resourceStream = null;
Properties prop = new Properties();
String themeBuild = null;
String themeWcVersion = null;
- try {
- resourceStream = ThemeUtil.class.getResourceAsStream(resourceName);
+ try (InputStream resourceStream = ThemeUtil.class.getResourceAsStream(resourceName)) {
prop.load(resourceStream);
// Theme build property
themeBuild = prop.getProperty(THEME_BUILD_NUMBER_PARAM);
@@ -68,8 +66,6 @@ public final class ThemeUtil {
themeWcVersion = prop.getProperty(THEME_WC_BUILD_NUMBER_PARAM);
} catch (Exception e) {
LOG.warn("Could not load theme version properties file \"" + resourceName + "\"");
- } finally {
- StreamUtil.safeClose(resourceStream);
}
// If theme build not available, then use the wcomponents project version
diff --git a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/thumbnail/ThumbnailUtil.java b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/thumbnail/ThumbnailUtil.java
index d84b1e55c..455c0aab7 100755
--- a/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/thumbnail/ThumbnailUtil.java
+++ b/wcomponents-core/src/main/java/com/github/bordertech/wcomponents/util/thumbnail/ThumbnailUtil.java
@@ -113,6 +113,11 @@ public final class ThumbnailUtil {
*/
private static final String IMAGE_JPEG_FORMAT = "jpeg";
+ /**
+ * JPEG Mime Type.
+ */
+ private static final String MIMETYPE_JPEG = "image/jpeg";
+
/**
* Don't allow this utility class to be constructed.
*/
@@ -136,19 +141,27 @@ public static com.github.bordertech.wcomponents.Image createThumbnail(final Inpu
final Dimension scaledSize, final String mimeType) {
final Dimension scale = scaledSize == null ? THUMBNAIL_SCALE_SIZE : scaledSize;
- // Generate thumbnail for image files
- if (is != null && mimeType != null && (mimeType.equals("image/jpeg") || mimeType.equals(
- "image/bmp")
- || mimeType.equals("image/png") || mimeType.equals("image/gif"))) {
+ // Attempt to generate thumbnail for image files
+ if (is != null && isImageMimeType(mimeType)) {
byte[] bytes = createImageThumbnail(is, scale);
if (bytes != null) {
- return new BytesImage(bytes, "image/jpeg", "Thumbnail of " + name, null);
+ return new BytesImage(bytes, MIMETYPE_JPEG, "Thumbnail of " + name, null);
}
}
// Use default thumbnail depending on mime type
- com.github.bordertech.wcomponents.Image image = handleDefaultImage(mimeType, name, scale);
- return image;
+ return handleDefaultImage(mimeType, name, scale);
+ }
+
+ /**
+ * @param mimeType the mime type to check
+ * @return true if mime type is for an image
+ */
+ private static boolean isImageMimeType(final String mimeType) {
+ return mimeType != null && (mimeType.equals(MIMETYPE_JPEG)
+ || mimeType.equals("image/bmp")
+ || mimeType.equals("image/png")
+ || mimeType.equals("image/gif"));
}
/**
@@ -191,9 +204,13 @@ private static com.github.bordertech.wcomponents.Image handleDefaultImage(final
boolean sameWidth = scale.width == -1 || scale.width == THUMBNAIL_DEFAULT_SIZE.width;
if (!sameHeight || !sameWidth) {
// Scale to correct size
- ByteArrayInputStream byteIs = new ByteArrayInputStream(image.getBytes());
- byte[] bytes = createImageThumbnail(byteIs, scale);
- image = new BytesImage(bytes, "image/jpeg", "Thumbnail of " + name, null);
+ try (ByteArrayInputStream byteIs = new ByteArrayInputStream(image.getBytes())) {
+ byte[] bytes = createImageThumbnail(byteIs, scale);
+ image = new BytesImage(bytes, MIMETYPE_JPEG, "Thumbnail of " + name, null);
+ } catch (IOException ex) {
+ image = null;
+ LOG.error("Error creating scaled thumbnail from image", ex);
+ }
}
return image;
}
@@ -207,32 +224,28 @@ private static com.github.bordertech.wcomponents.Image handleDefaultImage(final
* @return a byte[] representing the JPEG thumb nail.
*/
private static byte[] createImageThumbnail(final InputStream is, final Dimension scaledSize) {
+ // Create buffered image from input stream
BufferedImage image;
- MemoryCacheImageInputStream mciis;
-
try {
- mciis = new MemoryCacheImageInputStream(is);
- image = ImageIO.read(mciis);
+ // ImageIO closes cache stream
+ image = ImageIO.read(new MemoryCacheImageInputStream(is));
+ if (image == null) {
+ return null;
+ }
} catch (Exception e) {
LOG.warn("Unable to read input image", e);
return null;
}
- if (image == null) {
- return null;
- }
-
+ // Create scaled image
try {
- byte[] jpeg = createScaledJPEG(image, scaledSize);
- return jpeg;
+ return createScaledJPEG(image, scaledSize);
} catch (Exception e) {
LOG.error("Error creating thumbnail from image", e);
+ return null;
} finally {
image.flush();
}
-
- return null;
-
}
/**
@@ -247,12 +260,10 @@ private static byte[] createImageThumbnail(final InputStream is, final Dimension
private static byte[] createScaledJPEG(final Image image, final Dimension scaledSize) throws
IOException {
// Scale the image.
- Image scaledImage = image.getScaledInstance(scaledSize.width, scaledSize.height,
- Image.SCALE_SMOOTH);
+ Image scaledImage = image.getScaledInstance(scaledSize.width, scaledSize.height, Image.SCALE_SMOOTH);
// Create a BufferedImage copy of the scaledImage.
- BufferedImage bufferedImage = new BufferedImage(scaledImage.getWidth(null), scaledImage.
- getHeight(null),
+ BufferedImage bufferedImage = new BufferedImage(scaledImage.getWidth(null), scaledImage.getHeight(null),
BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = bufferedImage.createGraphics();
graphics.drawImage(scaledImage, 0, 0, null);
@@ -260,17 +271,12 @@ private static byte[] createScaledJPEG(final Image image, final Dimension scaled
graphics.dispose();
// Convert the scaled image to a JPEG byte array.
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- MemoryCacheImageOutputStream mciis = new MemoryCacheImageOutputStream(baos);
- ImageIO.write(bufferedImage, IMAGE_JPEG_FORMAT, mciis);
- mciis.flush();
- bufferedImage.flush();
-
- byte[] jpeg = baos.toByteArray();
- mciis.close();
-
- return jpeg;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); MemoryCacheImageOutputStream mciis = new MemoryCacheImageOutputStream(baos)) {
+ ImageIO.write(bufferedImage, IMAGE_JPEG_FORMAT, mciis);
+ mciis.flush();
+ bufferedImage.flush();
+ return baos.toByteArray();
+ }
}
}
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/AbstractWComponentTestCase.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/AbstractWComponentTestCase.java
index 97f880d56..95619f3c7 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/AbstractWComponentTestCase.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/AbstractWComponentTestCase.java
@@ -12,7 +12,7 @@
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
-import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.beanutils2.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/MockWEnvironment.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/MockWEnvironment.java
index 123dffbc0..b42328efd 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/MockWEnvironment.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/MockWEnvironment.java
@@ -1,6 +1,6 @@
package com.github.bordertech.wcomponents;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
/**
@@ -14,7 +14,7 @@ public class MockWEnvironment extends AbstractEnvironment {
/**
* The hidden parameters map.
*/
- private Map hiddenParameters = new HashMap<>();
+ private Map hiddenParameters = new LinkedHashMap<>();
/**
* Sets the post path. Overriden in order to make method public, as it's useful for unit testing.
@@ -33,7 +33,8 @@ public void setPostPath(final String postPath) {
*/
@Override
public Map getHiddenParameters() {
- return hiddenParameters;
+ // Simulate behaviour to create new map each time
+ return new LinkedHashMap<>(hiddenParameters);
}
/**
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/SerializationPerformance_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/SerializationPerformance_Test.java
index ceea8ba06..1cd79b01b 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/SerializationPerformance_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/SerializationPerformance_Test.java
@@ -23,8 +23,8 @@
import org.junit.experimental.categories.Category;
/**
- * Tests to check the performance of WComponent graph serialization. This test does not check for correct serialization
- * - see {@link Serialization_Test} instead.
+ * Tests to check the performance of WComponent graph serialization. This test does not check for correct serialization - see
+ * {@link Serialization_Test} instead.
*
* @author Yiannis Paschalidis
* @since 1.0.0
@@ -180,12 +180,10 @@ private int getUISize(final UIContext uic, final WComponent comp) throws IOExcep
* @throws IOException an IO exception
*/
private static byte[] serialize(final Serializable obj) throws IOException {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(bos);
- oos.writeObject(obj);
- oos.close();
-
- return bos.toByteArray();
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+ oos.writeObject(obj);
+ return bos.toByteArray();
+ }
}
/**
@@ -226,7 +224,6 @@ private void sendRequest(final WComponent comp, final UIContext uic) {
PrintWriter writer = new PrintWriter(new NullWriter());
uic.setEnvironment(new WServlet.WServletEnvironment("", "http://localhost", ""));
uic.setUI(comp);
-
InterceptorComponent root = ServletUtil.createInterceptorChain(new MockHttpServletRequest());
root.attachUI(comp);
@@ -235,6 +232,7 @@ private void sendRequest(final WComponent comp, final UIContext uic) {
setActiveContext(uic);
MockRequest request = new MockRequest();
+ request.setMethod("GET");
try {
root.serviceRequest(request);
@@ -288,8 +286,7 @@ private void findWComponents(final WComponent comp, final List resul
}
/**
- * AllComponents instantiated with 10 repetitions. This needs to be created as a subclass as the UIRegistry uses the
- * class name.
+ * AllComponents instantiated with 10 repetitions. This needs to be created as a subclass as the UIRegistry uses the class name.
*/
public static final class AllComponents10 extends AllComponents {
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/Serialization_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/Serialization_Test.java
index 9645d5add..d7e2fe1c9 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/Serialization_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/Serialization_Test.java
@@ -7,8 +7,8 @@
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import org.junit.Assert;
import org.apache.commons.logging.LogFactory;
+import org.junit.Assert;
import org.junit.Test;
/**
@@ -129,22 +129,20 @@ private void assertSerializable(final Object obj) {
*/
private static Object pipe(final Object obj) {
try {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(bos);
- oos.writeObject(obj);
- oos.close();
-
- byte[] bytes = bos.toByteArray();
-
- FileOutputStream fos = new FileOutputStream("SerializeText.txt");
- fos.write(bytes);
- fos.flush();
- fos.close();
-
- ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
- ObjectInputStream ois = new ObjectInputStream(bis);
- Object out = ois.readObject();
- return out;
+ byte[] bytes;
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+ oos.writeObject(obj);
+ bytes = bos.toByteArray();
+ }
+
+ try (FileOutputStream fos = new FileOutputStream("SerializeText.txt")) {
+ fos.write(bytes);
+ fos.flush();
+ }
+
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis)) {
+ return ois.readObject();
+ }
} catch (Exception ex) {
throw new SystemException("Failed to pipe " + obj, ex);
}
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WComponentsPerformance_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WComponentsPerformance_Test.java
index 0cb81141a..e729673b6 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WComponentsPerformance_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WComponentsPerformance_Test.java
@@ -11,7 +11,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.beanutils2.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assert;
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WMultiFileWidget_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WMultiFileWidget_Test.java
index 91e1c6ec9..a7126fd0e 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WMultiFileWidget_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WMultiFileWidget_Test.java
@@ -10,7 +10,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.fileupload.FileItem;
import org.junit.Assert;
import org.junit.Test;
@@ -124,8 +124,6 @@ public void testGetFile() {
Assert.assertEquals("File2 should be returned for index 1", TEST_FILE_ITEM_WRAP2, widget.
getFile("2"));
}
-
-
@Test
public void testGetMimeType() {
@@ -323,18 +321,18 @@ public void testSetFileTypesAsNullOrEmptyList() {
@Test
public void testMaxFileSizeAccessors() {
assertAccessorsCorrect(new WMultiFileWidget(), WMultiFileWidget::getMaxFileSize, WMultiFileWidget::setMaxFileSize,
- 10240000L, 1L, 2L);
+ 10240000L, 1L, 2L);
}
@Test
public void testDuplicateComponentModels() {
WMultiFileWidget multiFileWidget = new WMultiFileWidget();
- assertNoDuplicateComponentModels(multiFileWidget,"maxFileSize", 2012312312);
+ assertNoDuplicateComponentModels(multiFileWidget, "maxFileSize", 2012312312);
assertNoDuplicateComponentModels(multiFileWidget, "maxFiles", 123);
assertNoDuplicateComponentModels(multiFileWidget, "newUpload", true);
assertNoDuplicateComponentModels(multiFileWidget, "useThumbnails", true);
assertNoDuplicateComponentModels(multiFileWidget, "thumbnailPosition", WLink.ImagePosition.SOUTH);
- assertNoDuplicateComponentModels(multiFileWidget, "thumbnailSize", new Dimension(22,33));
+ assertNoDuplicateComponentModels(multiFileWidget, "thumbnailSize", new Dimension(22, 33));
// TODO: See issue #1574 https://github.com/BorderTech/wcomponents/issues/1574
// assertNoDuplicateComponentModels(multiFileWidget, "fileUploadRequestId", "testId"); // No such method exception as it's a private method
}
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WebUtilities_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WebUtilities_Test.java
index d4b8fd57d..80e9dde3e 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WebUtilities_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/WebUtilities_Test.java
@@ -7,11 +7,13 @@
import com.github.bordertech.wcomponents.util.mock.MockRequest;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import org.junit.Assert;
import org.junit.AfterClass;
+import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -118,124 +120,6 @@ public void testGetTop() {
Assert.assertEquals("Incorrect top component returned for top", root, WebUtilities.getTop(root));
}
- // @Test
- // public void testGetWComponentPath()
- // {
- // // Simple test, one root element.
- // WContainer root = new WContainer();
- // UIContext uic = new UIContextImpl();
- // uic.setUI(root);
- //
- // List path = WebUtilities.getWComponentPath(root, root.getId(), false);
- // List expected = Arrays.asList(new WComponentPathElement[]
- // {
- // new WComponentPathElement(root)
- // });
- // Assert.assertEquals("Incorrect path", expected, path);
- //
- // // Add a static child
- // WContainer staticChild = new WContainer();
- // root.add(staticChild);
- //
- // path = WebUtilities.getWComponentPath(root, staticChild.getId(), false);
- // expected = Arrays.asList(new WComponentPathElement[]
- // {
- // new WComponentPathElement(root),
- // new WComponentPathElement(staticChild)
- // });
- // Assert.assertEquals("Incorrect path", expected, path);
- //
- // // Add a dynamic child
- // root.setLocked(true);
- // setActiveContext(uic);
- // WComponent dynamicChild = new DefaultWComponent();
- // staticChild.add( dynamicChild);
- //
- // path = WebUtilities.getWComponentPath(root, dynamicChild.getId(), false);
- // expected = Arrays.asList(new WComponentPathElement[]
- // {
- // new WComponentPathElement(root),
- // new WComponentPathElement(staticChild),
- // new WComponentPathElement(dynamicChild),
- // });
- // Assert.assertEquals("Incorrect path", expected, path);
- //
- // // Test against another context with strict - should not find dynamic child
- // String dynamicChildId = dynamicChild.getId();
- // UIContext otherUic = new UIContextImpl();
- // otherUic.setUI(root);
- // setActiveContext(otherUic);
- //
- // path = WebUtilities.getWComponentPath(root, dynamicChildId, false);
- // Assert.assertNull("Path should not have been found", path);
- //
- // // Test against another context with tolerant - should return up to the static child
- // path = WebUtilities.getWComponentPath(root, dynamicChildId, true);
- // expected = Arrays.asList(new WComponentPathElement[]
- // {
- // new WComponentPathElement(root),
- // new WComponentPathElement(staticChild)
- // });
- // Assert.assertEquals("Incorrect path", expected, path);
- // }
- //
- // @Test
- // public void testGetWComponentPathWithRepeater()
- // {
- // WContainer root = new WContainer();
- // UIContext uic = new UIContextImpl();
- // uic.setUI(root);
- // WRepeater repeater = new WRepeater();
- // WComponent repeatedComponent = new WText();
- // List data = new ArrayList(Arrays.asList(new String[] { "a", "b", "c" }));
- //
- // repeater.setRepeatedComponent(repeatedComponent);
- // root.add(repeater);
- //
- // setActiveContext(uic);
- // repeater.setData(data);
- // List contexts = repeater.getRowContexts();
- //
- // for (int i = 0; i < data.size(); i++)
- // {
- // UIContext rowContext = contexts.get(i);
- // String repeatedComponentId = getComponentId(repeatedComponent, rowContext);
- //
- // List path = WebUtilities.getWComponentPath(root, repeatedComponentId, false);
- // List expected = Arrays.asList(new WComponentPathElement[]
- // {
- // new WComponentPathElement(root),
- // new WComponentPathElement(repeater, i),
- // new WComponentPathElement(repeater.getRepeatRoot()),
- // new WComponentPathElement(repeatedComponent)
- // });
- //
- // Assert.assertEquals("Incorrect path for row " + i, expected, path);
- // }
- //
- // // Test when a row is removed from the repeater
- // UIContext rowContext = contexts.get(contexts.size() - 1);
- // data.remove(data.size() - 1);
- //
- // // Strict should return null
- // UIContextHolder.pushContext(rowContext);
- // String repeatedComponentId = getComponentId(repeatedComponent, rowContext);
- //
- // List path = WebUtilities.getWComponentPath(root, repeatedComponentId, false);
- // Assert.assertNull("Path should not have been found in strict mode after row removal", path);
- //
- // // Tolerant should return up to the repeater
- // path = WebUtilities.getWComponentPath(root, repeatedComponentId, true);
- // List expected = Arrays.asList(new WComponentPathElement[]
- // {
- // new WComponentPathElement(root),
- // new WComponentPathElement(repeater),
- // new WComponentPathElement(repeater.getRepeatRoot()),
- // new WComponentPathElement(repeatedComponent)
- // });
- //
- // Assert.assertEquals("Incorrect tolerant path after row removal", expected, path);
- // }
@Test
public void testFindClosestContext() {
WContainer root = new WContainer();
@@ -465,36 +349,53 @@ public void testDecode() {
encoded));
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetPathNullURL() {
+ // Should not allow null base URL
+ WebUtilities.getPath(null, Collections.emptyMap());
+ }
+
@Test
- public void testGetPath() {
- // Simple case
- String url = "/foo";
- String expected = "/foo";
- Assert.assertEquals("Incorrect path returned for " + url, expected, WebUtilities.
- getPath(url, null));
+ public void testGetPathSimple() {
+ String baseUrl = "/foo";
+ String url = WebUtilities.getPath(baseUrl, null);
+ Assert.assertEquals("Incorrect path returned for base URL", baseUrl, url);
+ }
- // Simple case with one param
+ @Test
+ public void testGetPathWithParameter() {
+ // Simple case with adding one param
+ String baseUrl = "/foo";
Map params = new HashMap<>();
params.put("a", "b");
+ String url = WebUtilities.getPath(baseUrl, params);
+ String expected = "/foo?a=b";
+ Assert.assertEquals("Incorrect path returned for base URL with one parameter", expected, url);
+ }
- url = "/foo";
- expected = "/foo?a=b";
- Assert.assertEquals("Incorrect path returned for " + url + " with a=b", expected,
- WebUtilities.getPath(url, params));
-
+ @Test
+ public void testGetPathWithExistingParameter() {
// Case with existing params and two in the map
- params = new HashMap<>();
+ String baseUrl = "/foo?a=b";
+ Map params = new LinkedHashMap<>();
params.put("c", "d");
params.put("e", "f");
+ String url = WebUtilities.getPath(baseUrl, params);
+ String expected = "/foo?a=b&c=d&e=f";
+ Assert.assertEquals("Incorrect path returned for base URL with existing parameters", expected, url);
+ }
- url = "/foo?a=b";
- expected = "/foo?a=b&c=d&e=f";
-
- assertURLEquals(expected, WebUtilities.getPath(url, params), "&");
-
+ @Test
+ public void testGetPathWithAsJavascriptURL() {
+ // Case with existing params and two in the map
+ String baseUrl = "/foo?a=b";
+ Map params = new HashMap<>();
+ params.put("c", "d");
+ params.put("e", "f");
// As a javascript url
- expected = "/foo?a=b&c=d&e=f";
- assertURLEquals(expected, WebUtilities.getPath(url, params, true), "&");
+ String url = WebUtilities.getPath(baseUrl, params, true);
+ String expected = "/foo?a=b&c=d&e=f";
+ Assert.assertEquals("Incorrect path returned for URL for javascript", expected, url);
}
@Test
@@ -594,26 +495,6 @@ public void testRenderToHtmlWithXML() {
Assert.assertEquals("Invalid html output with XML", TransformXMLTestHelper.EXPECTED, output);
}
-// @Test
-// public void testContainsBrackets() {
-// Assert.assertTrue("Contains a open bracket", WebUtilities.containsBrackets("{"));
-// Assert.assertTrue("Contains a closed bracket", WebUtilities.containsBrackets("}"));
-// Assert.assertFalse("Contains an encoded open bracket", WebUtilities.containsBrackets("{"));
-// Assert.assertFalse("Contains an encoded closed bracket", WebUtilities.containsBrackets("}"));
-// Assert.assertFalse("Contains a double encoded open bracket", WebUtilities.containsBrackets("{"));
-// Assert.assertFalse("Contains a double encoded closed bracket", WebUtilities.containsBrackets("}"));
-// }
-
-// @Test
-// public void testContainsEncodeBrackets() {
-// Assert.assertTrue("Contains an encoded open bracket", WebUtilities.containsEncodedBrackets("{"));
-// Assert.assertTrue("Contains an encoded closed bracket", WebUtilities.containsEncodedBrackets("}"));
-// Assert.assertFalse("Contains a double encoded open bracket", WebUtilities.containsEncodedBrackets("{"));
-// Assert.assertFalse("Contains a double encoded closed bracket", WebUtilities.containsEncodedBrackets("}"));
-// Assert.assertFalse("Contains a open bracket", WebUtilities.containsEncodedBrackets("{"));
-// Assert.assertFalse("Contains a closed bracket", WebUtilities.containsEncodedBrackets("}"));
-// }
-
@Test
public void testEncodeBrackets() {
String in = "{}<{}>";
@@ -677,8 +558,110 @@ public void testDoubleDecodeBracketsWithNoMatches() {
Assert.assertEquals("Double decode brackets not correct", out, WebUtilities.doubleDecodeBrackets(in));
}
+ @Test
+ public void testCreateTargetUrl() {
+
+ String baseUrl = "/path";
+
+ // Setup context
+ UIContext uic = createUIContext();
+ MockWEnvironment env = new MockWEnvironment();
+ env.setPostPath(baseUrl);
+ uic.setEnvironment(env);
+ setActiveContext(uic);
+
+ // Target URL with no hidden or additional parameters
+ Targetable target = new MyTargetable();
+ HashMap expectedParams = new LinkedHashMap<>();
+ expectedParams.put("wc_target", "TARGET");
+ expectedParams.put("no-cache", null);
+ String url = WebUtilities.createTargetUrl(target, null);
+ assertCreatedURLCorrect("Target URL with no hidden or additional parameters. ", url, baseUrl, expectedParams, "&");
+
+ // Target URL with hidden parameters
+ // Setup hidden parameters
+ HashMap hiddenParams = new LinkedHashMap<>();
+ hiddenParams.put(Environment.SESSION_TOKEN_VARIABLE, "session");
+ hiddenParams.put(Environment.STEP_VARIABLE, "1");
+ env.setHiddenParameters(hiddenParams);
+ uic.setEnvironment(env);
+ // Expected params
+ expectedParams = new LinkedHashMap<>();
+ expectedParams.put("wc_s", "1");
+ expectedParams.put("wc_target", "TARGET");
+ expectedParams.put("no-cache", null);
+ url = WebUtilities.createTargetUrl(target, null);
+ assertCreatedURLCorrect("Target URL with hidden parameter. ", url, baseUrl, expectedParams, "&");
+
+ // Target URL with hidden parameters and additional
+ // Setup additional params
+ HashMap additionalParams = new LinkedHashMap<>();
+ additionalParams = new HashMap<>();
+ additionalParams.put("c", "d");
+ additionalParams.put("e", "f");
+ // Expected params
+ expectedParams = new LinkedHashMap<>();
+ expectedParams.put("wc_s", "1");
+ expectedParams.put("wc_target", "TARGET");
+ expectedParams.put("no-cache", null);
+ expectedParams.putAll(additionalParams);
+ url = WebUtilities.createTargetUrl(target, null, additionalParams);
+ assertCreatedURLCorrect("Target URL with hidden parameters and additional. ", url, baseUrl, expectedParams, "&");
+ }
+
+ @Test
+ public void testCreateTargetUrlWithCache() {
+
+ String baseUrl = "/path";
+ String cacheKey = "CACHE";
+
+ // Setup context
+ UIContext uic = createUIContext();
+ MockWEnvironment env = new MockWEnvironment();
+ env.setPostPath(baseUrl);
+ uic.setEnvironment(env);
+ setActiveContext(uic);
+
+ // Target URL with no hidden or additional parameters
+ Targetable target = new MyTargetable();
+ HashMap expectedParams = new LinkedHashMap<>();
+ expectedParams.put("wc_target", "TARGET");
+ expectedParams.put("contentCacheKey", cacheKey);
+ String url = WebUtilities.createTargetUrl(target, cacheKey);
+ assertCreatedURLCorrect("Target URL with no hidden or additional parameters and CACHE. ", url, baseUrl, expectedParams, "&");
+
+ // Target URL with hidden parameters
+ // Setup hidden parameters
+ HashMap hiddenParams = new LinkedHashMap<>();
+ hiddenParams.put(Environment.SESSION_TOKEN_VARIABLE, "session");
+ hiddenParams.put(Environment.STEP_VARIABLE, "1");
+ env.setHiddenParameters(hiddenParams);
+ uic.setEnvironment(env);
+ // Expected params
+ expectedParams = new LinkedHashMap<>();
+ expectedParams.put("wc_target", "TARGET");
+ expectedParams.put("contentCacheKey", cacheKey);
+ url = WebUtilities.createTargetUrl(target, cacheKey);
+ assertCreatedURLCorrect("Target URL with hidden parameter and CACHE. ", url, baseUrl, expectedParams, "&");
+
+ // Target URL with hidden parameters and additional
+ // Setup additional params
+ HashMap additionalParams = new LinkedHashMap<>();
+ additionalParams = new HashMap<>();
+ additionalParams.put("c", "d");
+ additionalParams.put("e", "f");
+ // Expected params
+ expectedParams = new LinkedHashMap<>();
+ expectedParams.put("wc_target", "TARGET");
+ expectedParams.put("contentCacheKey", cacheKey);
+ expectedParams.putAll(additionalParams);
+ url = WebUtilities.createTargetUrl(target, cacheKey, additionalParams);
+ assertCreatedURLCorrect("Target URL with hidden parameters and additional and CACHE. ", url, baseUrl, expectedParams, "&");
+ }
+
/**
* Generates a range of characters.
+ *
* @param from The first character in the range (must be > 0).
* @param to The last character in the range (must be >= from).
* @return A string containing the character range.
@@ -691,99 +674,48 @@ private static String characterRange(final int from, final int to) {
return result.toString();
}
-// /**
-// * Set up and execute the updateBeanValue method with the given parameter.
-// * If the parameter is null then the default updateBeanValue(component) method will be invoked.
-// *
-// * @param visibleOnly the parameter to pass to WebUtilities.updateBeanValue(component, visibleOnly).
-// */
-// private void runUpdateBeanValue(final Boolean visibleOnly) {
-// final String directChild = "directChild";
-// final String grandChild = "grandChild";
-// final String invisibleGrandChild = "invisibleGrandChild";
-// final String childOfInvisibleContainer = "childOfInvisibleContainer";
-//
-// Map beanMap = new HashMap<>();
-// beanMap.put(directChild, null);
-// beanMap.put(grandChild, null);
-// beanMap.put(invisibleGrandChild, null);
-// beanMap.put(childOfInvisibleContainer, null);
-//
-// WContainer root = new WContainer();
-// root.setBean(beanMap);
-// WTextField childTextField = new WTextField();
-// childTextField.setBeanProperty(directChild);
-// root.add(childTextField);
-//
-// WContainer childContainer = new WContainer();
-// root.add(childContainer);
-// WTextField grandChildTextField = new WTextField();
-// grandChildTextField.setBeanProperty(grandChild);
-// childContainer.add(grandChildTextField);
-//
-// WTextField invisibleGrandChildTextField = new WTextField();
-// invisibleGrandChildTextField.setBeanProperty(invisibleGrandChild);
-// invisibleGrandChildTextField.setVisible(false);
-// childContainer.add(invisibleGrandChildTextField);
-//
-// WContainer invisibleContainer = new WContainer();
-// invisibleContainer.setVisible(false);
-// root.add(invisibleContainer);
-// WTextField childOfInivisbleContainerTextField = new WTextField();
-// childOfInivisbleContainerTextField.setBeanProperty(childOfInvisibleContainer);
-// invisibleContainer.add(childOfInivisbleContainerTextField);
-//
-// root.setLocked(true);
-// setActiveContext(createUIContext());
-//
-// childTextField.setData(directChild);
-// grandChildTextField.setData(grandChild);
-// invisibleGrandChildTextField.setData(invisibleGrandChild);
-// childOfInivisbleContainerTextField.setData(childOfInvisibleContainer);
-//
-// if (visibleOnly == null) {
-// WebUtilities.updateBeanValue(root);
-// } else {
-// WebUtilities.updateBeanValue(root, visibleOnly);
-// }
-//
-// Assert.assertEquals("updateBeanValue failed to update directChild with visibleOnly=[" + visibleOnly + "]", directChild, beanMap.get(directChild));
-// Assert.assertEquals("updateBeanValue failed to update grandChild with visibleOnly=[" + visibleOnly + "]", grandChild, beanMap.get(grandChild));
-// Assert.assertEquals("updateBeanValue updated an incorrect value for invisibleGrandChild with visibleOnly=[" + visibleOnly + "]", BooleanUtils.isNotFalse(visibleOnly) ? null : invisibleGrandChild, beanMap.get(invisibleGrandChild));
-// Assert.assertEquals("updateBeanValue updated an incorrect value for childOfInvisibleContainer with visibleOnly=[" + visibleOnly + "]", BooleanUtils.isNotFalse(visibleOnly) ? null : childOfInvisibleContainer, beanMap.get(childOfInvisibleContainer));
-// }
/**
* Compare the URLS. The parameters of the URL must be equal but they do not have to be in the same order.
*
- * @param actual the actual value
- * @param expected the expected value
+ * @param msgPrefix message prefix for assert messages
+ * @param actualUrl the actual value
+ * @param expectedBase the expected value
+ * @param expectedParams the expected parameters
* @param separator the separator
*/
- private void assertURLEquals(final String actual, final String expected, final String separator) {
+ private void assertCreatedURLCorrect(final String msgPrefix, final String actualUrl, final String expectedBase, final Map expectedParams, final String separator) {
// compare the path section of urls (string compare)
- int paramStartIndex = actual.indexOf('?');
-
- // if the path elements of the url are not equal bail out now.
- Assert.assertTrue("The path elements of the URLs are not equal",
- expected.startsWith(actual.substring(0, paramStartIndex)));
-
- // now compare the parameters of each URL
- String expectedURLParams = expected.substring(paramStartIndex + 1);
- String actualURLParams = actual.substring(paramStartIndex + 1);
-
- String[] expectedParams = expectedURLParams.split(separator);
- String[] actualParams = actualURLParams.split(separator);
+ int paramStartIndex = actualUrl.indexOf('?');
- int params = expectedParams.length;
+ String actualURLBase = actualUrl.substring(0, paramStartIndex);
+ String actualURLParams = actualUrl.substring(paramStartIndex + 1);
- Assert.assertEquals("The number of parameters in URLs are not equal", params,
- actualParams.length);
-
- List expectedParamArray = Arrays.asList(expectedParams);
- List actualParamArray = Arrays.asList(actualParams);
+ // if the path elements of the url are not equal bail out now.
+ Assert.assertEquals(msgPrefix + "The path elements of the URLs are not equal", expectedBase, actualURLBase);
+
+ // Extract actual parameters
+ Map actualParams = new LinkedHashMap<>();
+ String[] actualParamsSplit = actualURLParams.split(separator);
+ for (String actual : actualParamsSplit) {
+ String split[] = actual.split("=");
+ actualParams.put(split[0], split[1]);
+ }
- Assert.assertTrue("The parameters contained in the URLs are not equal",
- actualParamArray.containsAll(expectedParamArray));
+ // Check parameter keys
+ Assert.assertEquals(msgPrefix + "Expected parameter keys not on URL", expectedParams.keySet(), actualParams.keySet());
+
+ // Check parameter values
+ for (Map.Entry entry : expectedParams.entrySet()) {
+ String key = entry.getKey();
+ String actualValue = actualParams.get(key);
+ String expectedValue = entry.getValue();
+ if (expectedValue == null) {
+ // Null value used to indicate value is random and cannot be checked but is at least present
+ Assert.assertNotNull(msgPrefix + "Parameter [" + key + "] has no value", actualValue);
+ } else {
+ Assert.assertEquals(msgPrefix + "Parameter [" + key + "] has incorrect value", expectedValue, actualValue);
+ }
+ }
}
/**
@@ -802,4 +734,13 @@ private static String getComponentId(final WComponent component, final UIContext
UIContextHolder.popContext();
}
}
+
+ private static class MyTargetable extends AbstractWComponent implements Targetable {
+
+ @Override
+ public String getTargetId() {
+ return "TARGET";
+ }
+
+ }
}
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenAjaxInterceptor_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenAjaxInterceptor_Test.java
index 0ccbbc5d7..8803ba58c 100644
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenAjaxInterceptor_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenAjaxInterceptor_Test.java
@@ -17,63 +17,77 @@
*/
public class SessionTokenAjaxInterceptor_Test extends AbstractWComponentTestCase {
+ private static final String VALID_TOKEN = "X";
+ private static final String INVALID_TOKEN = "Y";
+
@Before
public void setupUIC() {
+ // Set up user context and session token
+ MockWEnvironment env = new MockWEnvironment();
+ env.setSessionToken(VALID_TOKEN);
UIContext uic = createUIContext();
- uic.setEnvironment(new MockWEnvironment());
+ uic.setEnvironment(env);
setActiveContext(uic);
}
@Test(expected = SessionTokenException.class)
public void testServiceRequestNoTokenOnUIC() {
- SessionTokenAjaxInterceptor interceptor = new SessionTokenAjaxInterceptor();
- interceptor.serviceRequest(new MockRequest());
+ // Clear session token on UIC
+ UIContextHolder.getCurrent().getEnvironment().setSessionToken(null);
+ // Should not process with a UIC with no session token
+ new SessionTokenAjaxInterceptor().serviceRequest(new MockRequest());
}
@Test
- public void testServiceRequestCorrectToken() {
+ public void testServiceRequestWithPOSTandCorrectToken() {
// Setup interceptor
SessionTokenAjaxInterceptor interceptor = new SessionTokenAjaxInterceptor();
MyBackingComponent component = new MyBackingComponent();
interceptor.attachUI(component);
- // Setup session token
- UIContext uic = UIContextHolder.getCurrent();
- uic.getEnvironment().setSessionToken("X");
// Setup request
MockRequest request = new MockRequest();
- request.setParameter(Environment.SESSION_TOKEN_VARIABLE, "X");
- // Process request
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, VALID_TOKEN);
+ // Should process with POST request and valid token
interceptor.serviceRequest(request);
- Assert.assertTrue("Action phase should have occurred for corret token", component.handleRequestCalled);
+ Assert.assertTrue("Action phase should have occurred for POST and correct token", component.handleRequestCalled);
}
@Test(expected = SessionTokenException.class)
- public void testServiceRequestInvalidToken() {
- // Setup interceptor
- SessionTokenAjaxInterceptor interceptor = new SessionTokenAjaxInterceptor();
- MyBackingComponent component = new MyBackingComponent();
- interceptor.attachUI(component);
- // Setup session token
- UIContext uic = UIContextHolder.getCurrent();
- uic.getEnvironment().setSessionToken("X");
+ public void testServiceRequestWithPOSTandInvalidToken() {
// Setup invalid request
MockRequest request = new MockRequest();
- request.setParameter(Environment.SESSION_TOKEN_VARIABLE, "Y");
- // Process request
- interceptor.serviceRequest(request);
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, INVALID_TOKEN);
+ // Should not process with a POST request and invalid token
+ new SessionTokenAjaxInterceptor().serviceRequest(request);
}
@Test(expected = SessionTokenException.class)
- public void testServiceRequestNoTokenOnRequest() {
- // Setup interceptor
+ public void testServiceRequestWithPOSTandNoTokenOnRequest() {
+ // Should not process with a POST request and no token
+ new SessionTokenAjaxInterceptor().serviceRequest(new MockRequest());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testServiceRequestWithGETandToken() {
+ // Setup GET request with token
+ MockRequest request = new MockRequest();
+ request.setMethod("GET");
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, VALID_TOKEN);
+ // Should not allow GET request with token parameter
+ new SessionTokenAjaxInterceptor().serviceRequest(request);
+ }
+
+ @Test
+ public void testServiceRequestWithGETandNoToken() {
SessionTokenAjaxInterceptor interceptor = new SessionTokenAjaxInterceptor();
MyBackingComponent component = new MyBackingComponent();
interceptor.attachUI(component);
- // Setup session token
- UIContext uic = UIContextHolder.getCurrent();
- uic.getEnvironment().setSessionToken("X");
- // Process request
- interceptor.serviceRequest(new MockRequest());
+ // Setup GET request with no token
+ MockRequest request = new MockRequest();
+ request.setMethod("GET");
+ // Should allow GET request with no token parameter
+ interceptor.serviceRequest(request);
+ Assert.assertTrue("Action phase should have occurred for GET request with no token", component.handleRequestCalled);
}
/**
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenContentInterceptor_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenContentInterceptor_Test.java
index 2c62105ac..b9425d353 100644
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenContentInterceptor_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenContentInterceptor_Test.java
@@ -1,7 +1,6 @@
package com.github.bordertech.wcomponents.container;
import com.github.bordertech.wcomponents.AbstractWComponentTestCase;
-import com.github.bordertech.wcomponents.ContentEscape;
import com.github.bordertech.wcomponents.Environment;
import com.github.bordertech.wcomponents.MockWEnvironment;
import com.github.bordertech.wcomponents.Request;
@@ -18,82 +17,54 @@
*/
public class SessionTokenContentInterceptor_Test extends AbstractWComponentTestCase {
+ private static final String VALID_TOKEN = "X";
+
@Before
public void setupUIC() {
+ // Set up user context and session token
+ Environment env = new MockWEnvironment();
+ env.setSessionToken(VALID_TOKEN);
UIContext uic = createUIContext();
- uic.setEnvironment(new MockWEnvironment());
+ uic.setEnvironment(env);
setActiveContext(uic);
}
@Test(expected = SessionTokenException.class)
public void testServiceRequestNoTokenOnUIC() {
- SessionTokenContentInterceptor interceptor = new SessionTokenContentInterceptor();
- interceptor.serviceRequest(new MockRequest());
+ // Clear token on Context
+ UIContextHolder.getCurrent().getEnvironment().setSessionToken(null);
+ // Should not process if UIC has no session token
+ new SessionTokenContentInterceptor().serviceRequest(new MockRequest());
}
- @Test
- public void testServiceRequestCorrectToken() {
- // Setup interceptor
- SessionTokenContentInterceptor interceptor = new SessionTokenContentInterceptor();
- MyBackingContent component = new MyBackingContent();
- interceptor.attachUI(component);
- // Setup session token
- UIContext uic = UIContextHolder.getCurrent();
- uic.getEnvironment().setSessionToken("X");
- // Setup request
- MockRequest request = new MockRequest();
- request.setParameter(Environment.SESSION_TOKEN_VARIABLE, "X");
- // Process request
- interceptor.serviceRequest(request);
- Assert.assertTrue("Action phase should have occurred for corret token", component.handleRequestCalled);
+ @Test(expected = IllegalStateException.class)
+ public void testServiceRequestWithPOST() {
+ // Should not process with a POST request
+ new SessionTokenContentInterceptor().serviceRequest(new MockRequest());
}
- @Test(expected = SessionTokenException.class)
- public void testServiceRequestInvalidToken() {
- // Setup interceptor
- SessionTokenContentInterceptor interceptor = new SessionTokenContentInterceptor();
- MyBackingContent component = new MyBackingContent();
- interceptor.attachUI(component);
- // Setup session token
- UIContext uic = UIContextHolder.getCurrent();
- uic.getEnvironment().setSessionToken("X");
- // Setup invalid request
+ @Test(expected = IllegalStateException.class)
+ public void testServiceRequestWithGETandToken() {
+ // Setup GET request with token
MockRequest request = new MockRequest();
- request.setParameter(Environment.SESSION_TOKEN_VARIABLE, "Y");
- // Process request
- interceptor.serviceRequest(request);
- }
-
- @Test(expected = SessionTokenException.class)
- public void testServiceRequestNoTokenOnRequest() {
- // Setup interceptor
- SessionTokenContentInterceptor interceptor = new SessionTokenContentInterceptor();
- MyBackingContent component = new MyBackingContent();
- interceptor.attachUI(component);
- // Setup session token
- UIContext uic = UIContextHolder.getCurrent();
- uic.getEnvironment().setSessionToken("X");
- // Process request
- interceptor.serviceRequest(new MockRequest());
+ request.setMethod("GET");
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, VALID_TOKEN);
+ // Should not process with a GET request with a token
+ new SessionTokenContentInterceptor().serviceRequest(request);
}
- @Test(expected = ContentEscape.class)
- public void testServiceRequestNoTokenWIthCachedContent() {
+ @Test
+ public void testServiceRequestWithGETandNoToken() {
// Setup interceptor
SessionTokenContentInterceptor interceptor = new SessionTokenContentInterceptor();
MyBackingContent component = new MyBackingContent();
interceptor.attachUI(component);
- // Setup session token
- UIContext uic = UIContextHolder.getCurrent();
- uic.getEnvironment().setSessionToken("X");
- uic.setUI(component);
- // Setup request - TargetID makes the WContent trigger the ContentEscape
+ // Setup request
MockRequest request = new MockRequest();
- request.setParameter(Environment.TARGET_ID, component.getId());
- // Set cached content
- component.setCacheKey("mykey");
- // Process request
+ request.setMethod("GET");
+ // Should process with a GET request and no token
interceptor.serviceRequest(request);
+ Assert.assertTrue("Action phase should have occurred for GET request and no token", component.handleRequestCalled);
}
/**
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenInterceptor_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenInterceptor_Test.java
index 2328a4a9a..5c9efdd89 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenInterceptor_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/container/SessionTokenInterceptor_Test.java
@@ -6,10 +6,10 @@
import com.github.bordertech.wcomponents.Request;
import com.github.bordertech.wcomponents.UIContext;
import com.github.bordertech.wcomponents.UIContextHolder;
-import com.github.bordertech.wcomponents.UIContextImpl;
import com.github.bordertech.wcomponents.WApplication;
import com.github.bordertech.wcomponents.util.mock.MockRequest;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
/**
@@ -20,90 +20,112 @@
*/
public class SessionTokenInterceptor_Test extends AbstractWComponentTestCase {
- @Test
- public void testServiceRequestCorrectToken() {
+ private static final String VALID_TOKEN = "X";
+ private static final String INVALID_TOKEN = "Y";
+ @Before
+ public void setupUIC() {
+ // Set up user context and session token
+ MockWEnvironment env = new MockWEnvironment();
+ env.setSessionToken(VALID_TOKEN);
+ UIContext uic = createUIContext();
+ uic.setEnvironment(env);
+ setActiveContext(uic);
+ }
+
+ @Test
+ public void testServiceRequestWithPOSTandCorrectToken() {
// Setup interceptor
- SessionTokenInterceptor interceptor = setupInterceptor();
- MyBackingComponent component = (MyBackingComponent) interceptor.getBackingComponent();
- UIContext uic = UIContextHolder.getCurrent();
+ SessionTokenInterceptor interceptor = new SessionTokenInterceptor();
+ MyBackingComponent component = new MyBackingComponent();
+ interceptor.attachUI(component);
+ // Setup request with valid token
MockRequest request = new MockRequest();
-
- // Setup matching tokens on session and request
- uic.getEnvironment().setSessionToken("X");
- request.setParameter(Environment.SESSION_TOKEN_VARIABLE, "X");
-
- // Process request
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, VALID_TOKEN);
+ // Should process POST request with correct token
interceptor.serviceRequest(request);
Assert.assertTrue("Action phase should have occurred for corret token", component.handleRequestCalled);
}
- @Test
- public void testServiceRequestIncorrectToken() {
- // Setup interceptor
- SessionTokenInterceptor interceptor = setupInterceptor();
- MyBackingComponent component = (MyBackingComponent) interceptor.getBackingComponent();
- UIContext uic = UIContextHolder.getCurrent();
+ @Test(expected = SessionTokenException.class)
+ public void testServiceRequestWithPOSTandIncorrectToken() {
+ // Setup request with invalid token
MockRequest request = new MockRequest();
-
- // Setup tokens that dont match on session and request
- uic.getEnvironment().setSessionToken("X");
- request.setParameter(Environment.SESSION_TOKEN_VARIABLE, "Y");
-
- try {
- // Process request
- interceptor.serviceRequest(request);
- Assert.fail("Should have thrown an excpetion for incorrect token");
- } catch (SessionTokenException e) {
- Assert.assertFalse("Action phase should not have occurred for token error", component.handleRequestCalled);
- }
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, INVALID_TOKEN);
+ // Should not process POST request with incorrect token
+ new SessionTokenInterceptor().serviceRequest(request);
}
- @Test
+ @Test(expected = SessionTokenException.class)
public void testSessionTimeout() {
- // Setup interceptor
- SessionTokenInterceptor interceptor = setupInterceptor();
- MyBackingComponent component = (MyBackingComponent) interceptor.getBackingComponent();
- UIContext uic = UIContextHolder.getCurrent();
+ // Clear session token on UIC (simulate new session from timeout)
+ UIContextHolder.getCurrent().getEnvironment().setSessionToken(null);
+ // Simulate request parameter from previous session (new session has null token)
MockRequest request = new MockRequest();
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, VALID_TOKEN);
+ // Should not process a POST request with a token and null session token
+ new SessionTokenInterceptor().serviceRequest(request);
+ }
- // Simulate request parameter from previous session (new session has null token)
- request.setParameter(Environment.SESSION_TOKEN_VARIABLE, "X");
- try {
- // Process request
- interceptor.serviceRequest(request);
- Assert.fail("Should have thrown an excpetion for incorrect token");
- } catch (SessionTokenException e) {
- Assert.assertFalse("Action phase should not have occurred for session timeout", component.handleRequestCalled);
- Assert.assertEquals("Step count should not have been incremented for session timeout", 0, uic.getEnvironment().getStep());
- }
+ @Test(expected = SessionTokenException.class)
+ public void testNewSessionWithPOSTRequestWithToken() {
+ // Clear session token on UIC (simulate new session)
+ UIContextHolder.getCurrent().getEnvironment().setSessionToken(null);
+ // Setup POST request with a token
+ MockRequest request = new MockRequest();
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, VALID_TOKEN);
+ // Should not process a POST request with a token and a new session
+ new SessionTokenInterceptor().serviceRequest(request);
+ }
+
+ @Test(expected = SessionTokenException.class)
+ public void testNewSessionWithPOSTRequestWithNoToken() {
+ // Clear session token on UIC (simulate new session)
+ UIContextHolder.getCurrent().getEnvironment().setSessionToken(null);
+ // Should not process a POST request with no token and a new session
+ new SessionTokenInterceptor().serviceRequest(new MockRequest());
}
@Test
- public void testNewSession() {
+ public void testNewSessionWithGETRequest() {
// Setup interceptor
- SessionTokenInterceptor interceptor = setupInterceptor();
+ SessionTokenInterceptor interceptor = new SessionTokenInterceptor();
+ MyBackingComponent component = new MyBackingComponent();
+ interceptor.attachUI(component);
UIContext uic = UIContextHolder.getCurrent();
-
- // Check no session token (ie new session)
- Assert.assertNull("Session token should be null for new session", uic.getEnvironment().getSessionToken());
-
- // Test default state (ie no params and new session)
+ // Clear session token on UIC (simulate new session)
+ uic.getEnvironment().setSessionToken(null);
+ // Setup GET Request with no token
MockRequest request = new MockRequest();
+ request.setMethod("GET");
interceptor.serviceRequest(request);
interceptor.preparePaint(request);
+ Assert.assertTrue("Action phase should have occurred for new session", component.handleRequestCalled);
Assert.assertNotNull("Session token should be set for new session", uic.getEnvironment().getSessionToken());
}
- private SessionTokenInterceptor setupInterceptor() {
- MyBackingComponent component = new MyBackingComponent();
+ @Test(expected = IllegalStateException.class)
+ public void testServiceRequestWithGETandToken() {
+ // Setup GET request with a token
+ MockRequest request = new MockRequest();
+ request.setMethod("GET");
+ request.setParameter(Environment.SESSION_TOKEN_VARIABLE, VALID_TOKEN);
+ // Should not process a GET request with a token
+ new SessionTokenInterceptor().serviceRequest(request);
+ }
+
+ @Test
+ public void testServiceRequestWithGETandNoToken() {
+ // Setup interceptor
SessionTokenInterceptor interceptor = new SessionTokenInterceptor();
- interceptor.setBackingComponent(component);
- UIContext uic = new UIContextImpl();
- uic.setUI(component);
- uic.setEnvironment(new MockWEnvironment());
- setActiveContext(uic);
- return interceptor;
+ MyBackingComponent component = new MyBackingComponent();
+ interceptor.attachUI(component);
+ // Setup GET request with no token
+ MockRequest request = new MockRequest();
+ request.setMethod("GET");
+ // Should process GET request with no token
+ interceptor.serviceRequest(request);
+ Assert.assertTrue("Action phase should have occurred for new session", component.handleRequestCalled);
}
/**
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WApplicationRenderer_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WApplicationRenderer_Test.java
index a7fbf90e0..75f265317 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WApplicationRenderer_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WApplicationRenderer_Test.java
@@ -1,5 +1,6 @@
package com.github.bordertech.wcomponents.render.webxml;
+import com.github.bordertech.wcomponents.Environment;
import com.github.bordertech.wcomponents.MockWEnvironment;
import com.github.bordertech.wcomponents.UIContext;
import com.github.bordertech.wcomponents.WApplication;
@@ -12,10 +13,11 @@
import com.github.bordertech.wcomponents.util.ConfigurationProperties;
import java.io.IOException;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
-import org.junit.Assert;
import org.apache.commons.configuration.Configuration;
import org.custommonkey.xmlunit.exceptions.XpathException;
+import org.junit.Assert;
import org.junit.Test;
import org.xml.sax.SAXException;
@@ -103,6 +105,30 @@ public void testBasicRenderedFormat() throws XpathException, IOException, SAXExc
assertXpathNotExists("//ui:application/@defaultFocusId", application);
}
+ @Test
+ public void testAjaxUrlWithParameters() throws XpathException, IOException, SAXException {
+ // Basic component (no optional fields)
+ MockWEnvironment environment = new MockWEnvironment();
+ WApplication application = new WApplication();
+ environment.setPostPath("WApplicationRendererTest.postPath");
+ HashMap hiddenParams = new LinkedHashMap<>();
+ hiddenParams.put("A", "B");
+ hiddenParams.put("X", "Y");
+ // This should be ignored and not added to the AJAX url
+ hiddenParams.put(Environment.SESSION_TOKEN_VARIABLE, "SESSION");
+ environment.setHiddenParameters(hiddenParams);
+
+ String expectedUrl = "WApplicationRendererTest.postPath?A=B&X=Y";
+
+ UIContext uic = createUIContext();
+ uic.setEnvironment(environment);
+ uic.setUI(application);
+ setActiveContext(uic);
+
+ assertSchemaMatch(application);
+ assertXpathEvaluatesTo(expectedUrl, "//ui:application/@ajaxUrl", application);
+ }
+
@Test
public void testRenderedFormatWithFocussedComponent() throws XpathException, IOException,
SAXException {
@@ -180,8 +206,10 @@ public void testXssEscaping() throws IOException, SAXException, XpathException {
application.setTitle(getMaliciousAttribute("ui:application"));
assertSafeContent(application);
- uic.getEnvironment().getHiddenParameters().put(getMaliciousAttribute("ui:param"), "dummy");
- uic.getEnvironment().getHiddenParameters().put("dummy", getMaliciousAttribute("ui:param"));
+ HashMap hiddenParams = new LinkedHashMap<>();
+ hiddenParams.put(getMaliciousAttribute("ui:param"), "dummy");
+ hiddenParams.put("dummy", getMaliciousAttribute("ui:param"));
+ environment.setHiddenParameters(hiddenParams);
assertSafeContent(application);
}
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WLabelRenderer_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WLabelRenderer_Test.java
index a2b2cf9cc..89506e316 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WLabelRenderer_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WLabelRenderer_Test.java
@@ -94,12 +94,12 @@ public void testDoPaintAllOptions() throws IOException, SAXException, XpathExcep
@Test
public void testSanitizedText() throws IOException, SAXException, XpathException {
MyInput comp = new MyInput();
- WLabel label = new WLabel(" ", comp);
+ WLabel label = new WLabel(" ", comp);
label.setEncodeText(false);
label.setSanitizeOnOutput(true);
assertSchemaMatch(label);
String xml = toXHtml(label);
- Assert.assertTrue("Label text should contain sanitized xml", xml.contains("content "));
+ Assert.assertTrue("Label text should contain sanitized xml", xml.contains("content "));
}
@Test
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WebXmlRenderingPerformance_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WebXmlRenderingPerformance_Test.java
index bd2fb7182..c39aa128d 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WebXmlRenderingPerformance_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/render/webxml/WebXmlRenderingPerformance_Test.java
@@ -28,8 +28,8 @@
import org.junit.experimental.categories.Category;
/**
- * Tests to check the performance of WComponent XML rendering. This test does not check that the XML output is correct -
- * see the tests for each Renderer.
+ * Tests to check the performance of WComponent XML rendering. This test does not check that the XML output is correct - see the tests for each
+ * Renderer.
*
* @author Yiannis Paschalidis
* @since 1.0.0
@@ -236,6 +236,7 @@ private void sendRequest(final WComponent comp, final UIContext uic) {
setActiveContext(uic);
MockRequest request = new MockRequest();
+ request.setMethod("GET");
try {
root.serviceRequest(request);
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/servlet/WServletPerformance_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/servlet/WServletPerformance_Test.java
index 703b75a55..09ee638ce 100755
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/servlet/WServletPerformance_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/servlet/WServletPerformance_Test.java
@@ -29,7 +29,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.beanutils2.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assert;
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/util/FileUtil_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/util/FileUtil_Test.java
index 73403c10e..0b7bfde24 100644
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/util/FileUtil_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/util/FileUtil_Test.java
@@ -1,5 +1,6 @@
package com.github.bordertech.wcomponents.util;
+import com.github.bordertech.wcomponents.file.File;
import com.github.bordertech.wcomponents.file.FileItemWrap;
import com.github.bordertech.wcomponents.util.mock.MockFileItem;
import java.io.IOException;
@@ -12,6 +13,7 @@
/**
* FileUtil_Test - unit test for {@link FileUtil}.
+ *
* @author Aswin Kandula
* @since 1.5
*/
@@ -32,7 +34,7 @@ public void testValidateFileTypeImageFile() throws IOException {
public void testValidateFileTypeAnyFile() throws IOException {
boolean validateFileType = FileUtil.validateFileType(null, null);
Assert.assertFalse(validateFileType);
-
+
FileItem newFileItem = createFileItem(null);
validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Collections.EMPTY_LIST);
Assert.assertTrue(validateFileType);
@@ -44,35 +46,35 @@ public void testValidateFileTypePdfFile() throws IOException {
boolean validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Arrays.asList("application/pdf"));
Assert.assertTrue(validateFileType);
}
-
+
@Test
public void testValidateFileTypeTr5File() throws IOException {
// 'tr5' file has no mime type, so validation will pass with extension only.
FileItem newFileItem = createFileItem("/content/test.tr5");
boolean validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Arrays.asList(".tr5"));
Assert.assertTrue(validateFileType);
-
+
newFileItem = createFileItem("/content/test.tr5");
validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Arrays.asList("text/plain"));
Assert.assertTrue(validateFileType);
-
+
newFileItem = createFileItem("/content/test.tr5");
validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Arrays.asList("image/jpg"));
Assert.assertFalse(validateFileType);
}
-
+
@Test
public void testValidateFileTypeDodgyTr5File() throws IOException {
// 'tr5' file has no mime type, so validation will pass with extension only.
FileItem newFileItem = createFileItem("/content/dodgy.pdf.tr5");
boolean validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Arrays.asList(".tr5"));
Assert.assertTrue(validateFileType);
-
+
newFileItem = createFileItem("/content/dodgy.pdf.tr5");
validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Arrays.asList("text/plain"));
Assert.assertFalse(validateFileType);
}
-
+
@Test
public void testValidateFileSize() throws IOException {
FileItem newFileItem = createFileItem(null);
@@ -81,20 +83,20 @@ public void testValidateFileSize() throws IOException {
validateFileSize = FileUtil.validateFileSize(new FileItemWrap(newFileItem), 50);
Assert.assertFalse(validateFileSize);
-
+
FileUtil.validateFileSize(null, 0);
Assert.assertFalse(validateFileSize);
-
+
validateFileSize = FileUtil.validateFileSize(new FileItemWrap(newFileItem), -1000);
Assert.assertTrue(validateFileSize);
}
-
+
@Test
public void testReadableFileSize() {
String readableFileSize = FileUtil.readableFileSize(10101);
Assert.assertEquals("10.1 KB", readableFileSize);
}
-
+
@Test
public void testGetInvalidFileTypeMessage() {
String invalidFileTypeMessage = FileUtil.getInvalidFileTypeMessage(null);
@@ -103,16 +105,59 @@ public void testGetInvalidFileTypeMessage() {
invalidFileTypeMessage = FileUtil.getInvalidFileTypeMessage(Arrays.asList("*"));
Assert.assertEquals("The file you have selected is not of an accepted type. Only the following type/s are accepted: *.", invalidFileTypeMessage);
}
-
+
@Test
public void testGetInvalidFileSizeMessage() {
String invalidFileSizeMessage = FileUtil.getInvalidFileSizeMessage(1111);
Assert.assertEquals("The file you have selected is too large. Maximum file size is 1.1 KB.", invalidFileSizeMessage);
}
-
+
+ @Test
+ public void testGetMimeTypeForTextFileAndNoHint() throws IOException {
+ // Test detects the file as text with no hint
+ MyMockFile file = new MyMockFile("/content/text-non-ascii-less-10-per.txt", null, null);
+ Assert.assertEquals("Incorrect type for text file that should have been detected as text with no hints", "text/plain", FileUtil.getFileMimeType(file));
+ }
+
+ @Test
+ public void testGetMimeTypeForTextFileWithAsciiAndNoHint() throws IOException {
+ // Test providing no hint of the file name will detect as text
+ MyMockFile file = new MyMockFile("/content/text-non-ascii-more-10-per.txt", null, null);
+ Assert.assertEquals("Incorrect type for text file that should be detected as text with no hints", "text/plain", FileUtil.getFileMimeType(file));
+ }
+
+ @Test
+ public void testGetMimeTypeForTextFileWithAsciiAndNameHint() throws IOException {
+ // Test providing a hint of the file name will detect it as text
+ MyMockFile file = new MyMockFile("/content/text-non-ascii-more-10-per.txt", "text-non-ascii-more-10-per.txt", null);
+ Assert.assertEquals("Incorrect type for text file that should be detected as text with name hint", "text/plain", FileUtil.getFileMimeType(file));
+ }
+
+ @Test
+ public void testValidateFileExtensionInCaseSensitive() throws IOException {
+ MockFileItem file = new MockFileItem();
+ file.setName("test.DocX");
+ boolean validateFileType = FileUtil.validateFileType(new FileItemWrap(file), Arrays.asList(".dOCx"));
+ Assert.assertTrue(validateFileType);
+ }
+
+ @Test
+ public void testValidateFileTypeCaseInSensitive() throws IOException {
+ FileItem newFileItem = createFileItem("/content/test.pdf");
+ boolean validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Arrays.asList("AppLICATION/PDF"));
+ Assert.assertTrue(validateFileType);
+ }
+
+ @Test
+ public void testValidateFileTypeCaseInSensitiveWildCard() throws IOException {
+ FileItem newFileItem = createFileItem("/content/test.pdf");
+ boolean validateFileType = FileUtil.validateFileType(new FileItemWrap(newFileItem), Arrays.asList("AppLICATION/*"));
+ Assert.assertTrue(validateFileType);
+ }
+
/**
* Create a new fileitem.
- *
+ *
* @param fileResource if {@code null} dummy byte[] are set on file, otherwise given file resource.
* @return a file item
*/
@@ -123,21 +168,71 @@ private FileItem createFileItem(String fileResource) throws IOException {
for (int i = 0; i < testFileContent.length; i++) {
testFileContent[i] = (byte) (i & 0xff);
}
- }
- else {
- InputStream stream = getClass().getResourceAsStream(fileResource);
- if (stream == null) {
- throw new IOException("File resource not found: " + fileResource);
+ } else {
+ try (InputStream stream = getClass().getResourceAsStream(fileResource)) {
+ if (stream == null) {
+ throw new IOException("File resource not found: " + fileResource);
+ }
+ testFileContent = StreamUtil.getBytes(stream);
}
- testFileContent = StreamUtil.getBytes(stream);
}
MockFileItem fileItem = new MockFileItem();
fileItem.set(testFileContent);
fileItem.setFieldName(fileResource);
- if (fileResource != null) {
+ if (fileResource != null) {
String[] tokens = fileResource.split(".+?/(?=[^/]+$)");
fileItem.setName(tokens[1]);
}
return fileItem;
}
+
+ private static class MyMockFile implements File {
+
+ private final String fileResource;
+ private final String name;
+ private final String mimeType;
+
+ public MyMockFile(String fileResource, String name, String mimeType) {
+ this.fileResource = fileResource;
+ this.name = name;
+ this.mimeType = mimeType;
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return getClass().getResourceAsStream(fileResource);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ @Override
+ public long getSize() {
+ throw new UnsupportedOperationException("Not used in test");
+ }
+
+ @Override
+ public String getFileName() {
+ throw new UnsupportedOperationException("Not used in test");
+ }
+
+ @Override
+ public byte[] getBytes() {
+ throw new UnsupportedOperationException("Not used in test");
+ }
+
+ @Override
+ public String getDescription() {
+ throw new UnsupportedOperationException("Not used in test");
+ }
+
+ }
+
}
diff --git a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/util/HtmlSanitizerUtil_Test.java b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/util/HtmlSanitizerUtil_Test.java
index d24f50392..1d9865d4e 100644
--- a/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/util/HtmlSanitizerUtil_Test.java
+++ b/wcomponents-core/src/test/java/com/github/bordertech/wcomponents/util/HtmlSanitizerUtil_Test.java
@@ -174,8 +174,8 @@ public void testStrictSanitizerElement() throws ScanException, PolicyException {
@Test
public void testLaxScanVoidElements() throws ScanException, PolicyException {
- // Antisamy as of 1.7.X does not support xhtml and will remove the closing tag on "void" elements which will break the XML
- String input = " ";
+ // Note - Antisamy 1.7.0 to 1.7.6 does not support xhtml and will remove the closing tag on "void" elements which will break the XML
+ String input = " ";
Assert.assertEquals(input, HtmlSanitizerUtil.sanitize(input, true));
}
diff --git a/wcomponents-core/src/test/resources/content/text-non-ascii-less-10-per.txt b/wcomponents-core/src/test/resources/content/text-non-ascii-less-10-per.txt
new file mode 100644
index 000000000..d791c2131
--- /dev/null
+++ b/wcomponents-core/src/test/resources/content/text-non-ascii-less-10-per.txt
@@ -0,0 +1 @@
+““XXXXXXXXXXXXXXXXXX
diff --git a/wcomponents-core/src/test/resources/content/text-non-ascii-more-10-per.txt b/wcomponents-core/src/test/resources/content/text-non-ascii-more-10-per.txt
new file mode 100644
index 000000000..95e5b808e
--- /dev/null
+++ b/wcomponents-core/src/test/resources/content/text-non-ascii-more-10-per.txt
@@ -0,0 +1 @@
+“““““XX
diff --git a/wcomponents-examples-lde/pom.xml b/wcomponents-examples-lde/pom.xml
index 932637062..2af6be6c9 100755
--- a/wcomponents-examples-lde/pom.xml
+++ b/wcomponents-examples-lde/pom.xml
@@ -8,7 +8,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOT../pom.xml
diff --git a/wcomponents-examples/pom.xml b/wcomponents-examples/pom.xml
index 651b7e195..60c8e8cdd 100755
--- a/wcomponents-examples/pom.xml
+++ b/wcomponents-examples/pom.xml
@@ -8,7 +8,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOT../pom.xml
@@ -57,19 +57,6 @@
${project.version}
-
- commons-validator
- commons-validator
- 1.10.0
-
-
-
- commons-logging
- commons-logging
-
-
-
-
com.github.bordertech.wcomponents
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/DynamicImage.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/DynamicImage.java
index ecfa4f580..01edd5b5f 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/DynamicImage.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/DynamicImage.java
@@ -55,8 +55,7 @@ public String getMimeType() {
}
/**
- * Retrieves the natural size of the image. If only one dimension is known, a negative value will be returned for
- * the other dimension.
+ * Retrieves the natural size of the image. If only one dimension is known, a negative value will be returned for the other dimension.
*
* @return the image size, or null if unknown.
*/
@@ -98,12 +97,11 @@ public byte[] getBytes() {
// Write the image to a byte array.
Iterator writers = ImageIO.getImageWritersByMIMEType(getMimeType());
ImageWriter writer = writers.next();
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- ImageOutputStream ios = ImageIO.createImageOutputStream(os);
- writer.setOutput(ios);
- writer.write(image);
-
- return os.toByteArray();
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageOutputStream ios = ImageIO.createImageOutputStream(os)) {
+ writer.setOutput(ios);
+ writer.write(image);
+ return os.toByteArray();
+ }
} catch (IOException ex) {
LOG.error("Unable to generate client image.", ex);
}
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/LinkOptionsExample.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/LinkOptionsExample.java
index f72556a38..0eac430a5 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/LinkOptionsExample.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/LinkOptionsExample.java
@@ -17,10 +17,12 @@
import com.github.bordertech.wcomponents.WTextField;
import com.github.bordertech.wcomponents.validation.ValidatingAction;
import com.github.bordertech.wcomponents.validation.WValidationErrors;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.apache.commons.validator.routines.UrlValidator;
/**
* LinkOptionsExample contains a series of controls for displaying and manipulating an example link.
@@ -151,8 +153,12 @@ public void executeOnValid(final ActionEvent event) {
* @return true if valid
*/
private boolean isValidUrl(final String url) {
- UrlValidator validator = new UrlValidator();
- return validator.isValid(url);
+ try {
+ new URL(url).toURI();
+ return true;
+ } catch (MalformedURLException | URISyntaxException e) {
+ return false;
+ }
}
/**
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/TextImage.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/TextImage.java
index 5ca169898..934c51502 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/TextImage.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/TextImage.java
@@ -112,12 +112,11 @@ public TextImage(final String text, final Dimension size) {
// Write the image to a byte array.
Iterator writers = ImageIO.getImageWritersByMIMEType(MIME_TYPE);
ImageWriter writer = writers.next();
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- ImageOutputStream ios = ImageIO.createImageOutputStream(os);
- writer.setOutput(ios);
- writer.write(image);
-
- imageBytes = os.toByteArray();
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageOutputStream ios = ImageIO.createImageOutputStream(os)) {
+ writer.setOutput(ios);
+ writer.write(image);
+ imageBytes = os.toByteArray();
+ }
} catch (IOException ex) {
LOG.error("Unable to generate client image.", ex);
}
@@ -135,8 +134,7 @@ public String getMimeType() {
}
/**
- * Retrieves the natural size of the image. If only one dimension is known, a negative value will be returned for
- * the other dimension.
+ * Retrieves the natural size of the image. If only one dimension is known, a negative value will be returned for the other dimension.
*
* @return the image size, or null if unknown.
*/
@@ -146,8 +144,8 @@ public Dimension getSize() {
}
/**
- * Sets the natural size of the image. If only one dimension is known, use a negative value for the other dimension.
- * If the image size is unknown, set the size to null.
+ * Sets the natural size of the image. If only one dimension is known, use a negative value for the other dimension. If the image size is unknown,
+ * set the size to null.
*
* @param size the image size.
*/
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/WComponentRenderPerfTest.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/WComponentRenderPerfTest.java
index 77fa85b74..315bd3a2e 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/WComponentRenderPerfTest.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/WComponentRenderPerfTest.java
@@ -109,16 +109,15 @@ private static void launchTest(final String testName) throws IOException {
testName
});
- InputStream stdout = process.getInputStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
-
- // Pipe the input from the process to the logger
- for (String line = reader.readLine(); line != null; line = reader.readLine()) {
- int index = line.indexOf(LINE_PREFIX);
-
- if (index != -1) {
- line = line.substring(index + LINE_PREFIX.length());
- LOG.info(line);
+ try (InputStream stdout = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(stdout))) {
+ // Pipe the input from the process to the logger
+ for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+ int index = line.indexOf(LINE_PREFIX);
+
+ if (index != -1) {
+ line = line.substring(index + LINE_PREFIX.length());
+ LOG.info(line);
+ }
}
}
}
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/WImageExample.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/WImageExample.java
index 7585e1f3b..bbc96d5f2 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/WImageExample.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/WImageExample.java
@@ -126,16 +126,12 @@ public static class ExampleImage implements Image {
* @param resource the path to the image file.
*/
public ExampleImage(final String resource) {
- InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(
- resource);
-
- if (in != null) {
- try {
+ try (InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource)) {
+ if (in != null) {
imageBytes = StreamUtil.getBytes(in);
- in.close();
- } catch (IOException ex) {
- LOG.error("Cannot load example image.", ex);
}
+ } catch (IOException ex) {
+ LOG.error("Cannot load example image.", ex);
}
}
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/datatable/DataTableOptionsExample.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/datatable/DataTableOptionsExample.java
index 734ac6c95..ae275dcc6 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/datatable/DataTableOptionsExample.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/datatable/DataTableOptionsExample.java
@@ -31,7 +31,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-import org.apache.commons.beanutils.BeanComparator;
+import org.apache.commons.beanutils2.BeanComparator;
/**
* This class demonstrates the options available on a {@link WDataTable}.
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/picker/ExampleSection.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/picker/ExampleSection.java
index 4370dc87a..62dde9707 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/picker/ExampleSection.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/picker/ExampleSection.java
@@ -215,27 +215,14 @@ public void resetExample() {
private static String getSource(final String className) {
String sourceName = '/' + className.replace('.', '/') + ".java";
- InputStream stream = null;
-
- try {
- stream = ExampleSection.class.getResourceAsStream(sourceName);
-
+ try (InputStream stream = ExampleSection.class.getResourceAsStream(sourceName)) {
if (stream != null) {
byte[] sourceBytes = StreamUtil.getBytes(stream);
-
// we need to do some basic formatting of the source now.
return new String(sourceBytes, "UTF-8");
}
} catch (IOException e) {
LOG.warn("Unable to read source code for class " + className, e);
- } finally {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException e) {
- LOG.error("Error closing stream", e);
- }
- }
}
return null;
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/theme/WMultiFileWidgetExample.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/theme/WMultiFileWidgetExample.java
index f2d4df488..b8a9f5119 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/theme/WMultiFileWidgetExample.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/theme/WMultiFileWidgetExample.java
@@ -204,9 +204,7 @@ private void appendFileDetails(final StringBuffer buf, final WMultiFileWidget fi
for (FileWidgetUpload file : files) {
String streamedSize;
- try {
- InputStream in = file.getFile().getInputStream();
-
+ try (InputStream in = file.getFile().getInputStream()) {
int size = 0;
while (in.read() >= 0) {
size++;
diff --git a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/theme/XsltTestComponent.java b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/theme/XsltTestComponent.java
index bd7f75ccb..aa7cbcb9f 100755
--- a/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/theme/XsltTestComponent.java
+++ b/wcomponents-examples/src/main/java/com/github/bordertech/wcomponents/examples/theme/XsltTestComponent.java
@@ -95,33 +95,14 @@ private void runTransform() {
*/
private void transform(final File xsltFile, final File inputFile, final File outputFile) throws
Exception {
- FileReader xsltIn = null;
- FileReader in = null;
- FileWriter out = null;
-
- try {
- xsltIn = new FileReader(xsltFile);
+ try (FileReader xsltIn = new FileReader(xsltFile); FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile)) {
Source xsltSource = new StreamSource(xsltIn);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xsltSource);
// transformer.setOutputProperty("disable-empty-element-collapsing", "true");
-
- in = new FileReader(inputFile);
Source source = new StreamSource(in);
- out = new FileWriter(outputFile);
StreamResult result = new StreamResult(out);
transformer.transform(source, result);
- } finally {
- if (xsltIn != null) {
- xsltIn.close();
- }
- if (in != null) {
- in.close();
- }
- if (out != null) {
- out.flush();
- out.close();
- }
}
}
}
diff --git a/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/SimpleFileUpload_Test.java b/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/SimpleFileUpload_Test.java
index 18d1ec05b..592b7b16f 100755
--- a/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/SimpleFileUpload_Test.java
+++ b/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/SimpleFileUpload_Test.java
@@ -65,10 +65,9 @@ private static File createTempFile(final String content) throws IOException {
File tempFile = File.createTempFile("SimpleFileUpload_Test", "tmp");
tempFile.deleteOnExit();
- OutputStream out = new FileOutputStream(tempFile);
- out.write(content.getBytes());
- out.close();
-
+ try (OutputStream out = new FileOutputStream(tempFile)) {
+ out.write(content.getBytes());
+ }
return tempFile;
}
}
diff --git a/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/WMultiSelectPairTestingExample_Test.java b/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/WMultiSelectPairTestingExample_Test.java
index 431c3a874..7ef87a5dd 100644
--- a/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/WMultiSelectPairTestingExample_Test.java
+++ b/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/WMultiSelectPairTestingExample_Test.java
@@ -5,7 +5,7 @@
import com.github.bordertech.wcomponents.test.selenium.driver.SeleniumWComponentsWebDriver;
import com.github.bordertech.wcomponents.test.selenium.element.SeleniumWMultiSelectPairWebElement;
import java.util.List;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;
diff --git a/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/theme/WCheckBoxSelectExample_Test.java b/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/theme/WCheckBoxSelectExample_Test.java
index facecc4bb..4763278af 100644
--- a/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/theme/WCheckBoxSelectExample_Test.java
+++ b/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/theme/WCheckBoxSelectExample_Test.java
@@ -7,7 +7,7 @@
import com.github.bordertech.wcomponents.test.selenium.driver.SeleniumWComponentsWebDriver;
import com.github.bordertech.wcomponents.test.selenium.element.SeleniumWCheckBoxSelectWebElement;
import com.github.bordertech.wcomponents.util.SystemException;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;
diff --git a/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/theme/WRadioButtonSelectExample_Test.java b/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/theme/WRadioButtonSelectExample_Test.java
index 75c91604b..e03a6f5a1 100644
--- a/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/theme/WRadioButtonSelectExample_Test.java
+++ b/wcomponents-examples/src/test/java/com/github/bordertech/wcomponents/examples/theme/WRadioButtonSelectExample_Test.java
@@ -6,7 +6,7 @@
import com.github.bordertech.wcomponents.test.selenium.MultiBrowserRunner;
import com.github.bordertech.wcomponents.test.selenium.driver.SeleniumWComponentsWebDriver;
import com.github.bordertech.wcomponents.test.selenium.element.SeleniumWRadioButtonSelectWebElement;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;
diff --git a/wcomponents-i18n/pom.xml b/wcomponents-i18n/pom.xml
index d3c37fe82..94717304b 100755
--- a/wcomponents-i18n/pom.xml
+++ b/wcomponents-i18n/pom.xml
@@ -8,7 +8,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOT../pom.xml
diff --git a/wcomponents-lde/pom.xml b/wcomponents-lde/pom.xml
index 995486500..348194a9d 100755
--- a/wcomponents-lde/pom.xml
+++ b/wcomponents-lde/pom.xml
@@ -8,7 +8,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOT../pom.xml
diff --git a/wcomponents-lde/src/main/java/com/github/bordertech/wcomponents/lde/LdeSessionUtil.java b/wcomponents-lde/src/main/java/com/github/bordertech/wcomponents/lde/LdeSessionUtil.java
index f4106d6f9..fad7ccb3d 100755
--- a/wcomponents-lde/src/main/java/com/github/bordertech/wcomponents/lde/LdeSessionUtil.java
+++ b/wcomponents-lde/src/main/java/com/github/bordertech/wcomponents/lde/LdeSessionUtil.java
@@ -1,7 +1,6 @@
package com.github.bordertech.wcomponents.lde;
import com.github.bordertech.wcomponents.util.ConfigurationProperties;
-import com.github.bordertech.wcomponents.util.StreamUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -47,16 +46,9 @@ private LdeSessionUtil() {
*/
public static void deserializeSessionAttributes(final HttpSession session) {
File file = new File(SERIALIZE_SESSION_NAME);
- FileInputStream fis = null;
- ObjectInputStream ois = null;
-
if (file.canRead()) {
- try {
- fis = new FileInputStream(file);
- ois = new ObjectInputStream(fis);
-
+ try (FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis)) {
List data = (List) ois.readObject();
-
for (Iterator i = data.iterator(); i.hasNext();) {
String key = (String) i.next();
Object value = i.next();
@@ -64,12 +56,6 @@ public static void deserializeSessionAttributes(final HttpSession session) {
}
} catch (Exception e) {
LOG.error("Failed to read serialized session from " + file, e);
- } finally {
- if (ois != null) {
- StreamUtil.safeClose(ois);
- } else {
- StreamUtil.safeClose(fis);
- }
}
} else {
LOG.warn("Unable to read serialized session from " + file);
@@ -105,22 +91,10 @@ public static synchronized void serializeSessionAttributes(final HttpSession ses
}
// Write them to the file
- FileOutputStream fos = null;
- ObjectOutputStream oos = null;
-
- try {
- fos = new FileOutputStream(file);
- oos = new ObjectOutputStream(fos);
-
+ try (FileOutputStream fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(data);
} catch (Exception e) {
LOG.error("Failed to write serialized session to " + file, e);
- } finally {
- if (oos != null) {
- StreamUtil.safeClose(oos);
- } else {
- StreamUtil.safeClose(fos);
- }
}
} else {
LOG.warn("Unable to write serialized session to " + file);
diff --git a/wcomponents-lde/src/test/java/com/github/bordertech/wcomponents/lde/PlainLauncher_Test.java b/wcomponents-lde/src/test/java/com/github/bordertech/wcomponents/lde/PlainLauncher_Test.java
index e0eda7c14..69370c3da 100755
--- a/wcomponents-lde/src/test/java/com/github/bordertech/wcomponents/lde/PlainLauncher_Test.java
+++ b/wcomponents-lde/src/test/java/com/github/bordertech/wcomponents/lde/PlainLauncher_Test.java
@@ -11,10 +11,11 @@
import com.github.bordertech.wcomponents.util.ConfigurationProperties;
import com.github.bordertech.wcomponents.util.StreamUtil;
import com.github.bordertech.wcomponents.util.mock.servlet.MockHttpServletRequest;
+import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
-import org.junit.Assert;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Test;
/**
@@ -95,8 +96,11 @@ public void testServer() throws Exception {
// Access the server and record the output
URL url = new URL(launcher.getUrl());
URLConnection conn = url.openConnection();
- byte[] result = StreamUtil.getBytes(conn.getInputStream());
- String content = new String(result, "UTF-8");
+ String content;
+ try (InputStream stream = conn.getInputStream()) {
+ byte[] result = StreamUtil.getBytes(stream);
+ content = new String(result, "UTF-8");
+ }
Assert.assertEquals("HandleRequest should have been called once", 1,
MyTestApp.handleRequestCount);
diff --git a/wcomponents-test-lib/pom.xml b/wcomponents-test-lib/pom.xml
index d138affd5..e08aad3c4 100755
--- a/wcomponents-test-lib/pom.xml
+++ b/wcomponents-test-lib/pom.xml
@@ -8,7 +8,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOT../pom.xml
@@ -79,7 +79,7 @@
io.github.bonigarciawebdrivermanager
- 6.1.0
+ 6.3.3
@@ -131,7 +131,7 @@
org.apache.commonscommons-compress
- 1.27.1
+ 1.28.0
@@ -151,12 +151,12 @@
commons-codeccommons-codec
- 1.18.0
+ 1.20.0com.google.guavaguava
- 33.4.8-jre
+ 33.5.0-jrecom.google.errorprone
@@ -167,7 +167,7 @@
net.java.dev.jnajna
- 5.17.0
+ 5.18.1
diff --git a/wcomponents-test-lib/src/main/java/com/github/bordertech/wcomponents/test/selenium/ByLabel.java b/wcomponents-test-lib/src/main/java/com/github/bordertech/wcomponents/test/selenium/ByLabel.java
index f5d740464..fe1eb8c30 100644
--- a/wcomponents-test-lib/src/main/java/com/github/bordertech/wcomponents/test/selenium/ByLabel.java
+++ b/wcomponents-test-lib/src/main/java/com/github/bordertech/wcomponents/test/selenium/ByLabel.java
@@ -4,7 +4,7 @@
import com.github.bordertech.wcomponents.test.selenium.element.SeleniumWComponentWebProperties;
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.SearchContext;
diff --git a/wcomponents-test-lib/src/main/java/com/github/bordertech/wcomponents/test/selenium/element/SeleniumCheckableGroupInputWebElement.java b/wcomponents-test-lib/src/main/java/com/github/bordertech/wcomponents/test/selenium/element/SeleniumCheckableGroupInputWebElement.java
index e37caf0e4..25ad92f1b 100644
--- a/wcomponents-test-lib/src/main/java/com/github/bordertech/wcomponents/test/selenium/element/SeleniumCheckableGroupInputWebElement.java
+++ b/wcomponents-test-lib/src/main/java/com/github/bordertech/wcomponents/test/selenium/element/SeleniumCheckableGroupInputWebElement.java
@@ -5,7 +5,7 @@
import com.github.bordertech.wcomponents.util.SystemException;
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
diff --git a/wcomponents-theme/package.json b/wcomponents-theme/package.json
index d756bb1cc..009b7f740 100755
--- a/wcomponents-theme/package.json
+++ b/wcomponents-theme/package.json
@@ -1,6 +1,6 @@
{
"name": "wc",
- "version": "1.5.38-SNAPSHOT",
+ "version": "1.5.40-SNAPSHOT",
"description": "Client side code for WComponents UI tool kit.",
"private": true,
"type": "module",
diff --git a/wcomponents-theme/pom.xml b/wcomponents-theme/pom.xml
index 1107d310f..3c88a320d 100755
--- a/wcomponents-theme/pom.xml
+++ b/wcomponents-theme/pom.xml
@@ -7,7 +7,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOTjar
diff --git a/wcomponents-theme/src/main/js/wc/ajax/Trigger.mjs b/wcomponents-theme/src/main/js/wc/ajax/Trigger.mjs
index 884430555..bfbc9b954 100755
--- a/wcomponents-theme/src/main/js/wc/ajax/Trigger.mjs
+++ b/wcomponents-theme/src/main/js/wc/ajax/Trigger.mjs
@@ -630,6 +630,9 @@ function getFormParams(element, instance) {
result = addToQueryString(result, serializeElements(region, "select"));
result = addToQueryString(result, serializeElements(region, "textarea"));
result = addToQueryString(result, serializeElements(stateContainer, "input"));
+ if (instance.method !== instance.METHODS.GET) {
+ result = addToQueryString(result, serialize.serialize(document.getElementsByName("wc_t")));
+ }
} else {
formUpdateManager.update(form);
result = /** @type String */(serialize.serialize(form));
diff --git a/wcomponents-theme/src/main/js/wc/ui/multiFileUploader.mjs b/wcomponents-theme/src/main/js/wc/ui/multiFileUploader.mjs
index 5ef4d4400..3094e5cac 100755
--- a/wcomponents-theme/src/main/js/wc/ui/multiFileUploader.mjs
+++ b/wcomponents-theme/src/main/js/wc/ui/multiFileUploader.mjs
@@ -853,6 +853,7 @@ function TrueAjax() {
*/
function sendFile(uri, uploadName, fileId, file, callback) {
const formData = new FormData(),
+ token = document.getElementById("wc_t"),
onProgress = progressEventFactory(fileId),
onError = errorHandlerFactory(fileId),
onAbort = abortHandlerFactory(fileId);
@@ -865,6 +866,10 @@ function TrueAjax() {
* The name, however, is a readonly property of blob and while we may appear to have overridden the value we probably haven't.
*/
formData.append(uploadName, file, file.name);
+ // Add session token
+ if (token) {
+ formData.append("wc_t", token.value);
+ }
const request = {
url: uri,
diff --git a/wcomponents-theme/src/test/spec/wc.date.parser.test.mjs b/wcomponents-theme/src/test/spec/wc.date.parser.test.mjs
index e12602588..b45855632 100644
--- a/wcomponents-theme/src/test/spec/wc.date.parser.test.mjs
+++ b/wcomponents-theme/src/test/spec/wc.date.parser.test.mjs
@@ -102,11 +102,11 @@ describe("wc/date/Parser", function() {
});
it("testParserStndExpandYearPast", function() {
const parser = getParser(standardMasks, true, false),
- result = parser.parse("281025");
+ result = parser.parse("281035");
expect(result.length).toBe(1);
expect(result[0].day).toBe(28);
expect(result[0].month).toBe(10);
- expect(result[0].year).toBe(1925);
+ expect(result[0].year).toBe(1935);
});
it("testParserStndMonthAbbr", function() {
const parser = getParser(standardMasks, false, false),
diff --git a/wcomponents-xslt/pom.xml b/wcomponents-xslt/pom.xml
index 0f07a0a43..375eec640 100644
--- a/wcomponents-xslt/pom.xml
+++ b/wcomponents-xslt/pom.xml
@@ -7,7 +7,7 @@
com.github.bordertech.wcomponentswcomponents-parent
- 1.5.38-SNAPSHOT
+ 1.5.40-SNAPSHOTjar
diff --git a/wcomponents-xslt/src/main/xslt/wc.ui.application.xsl b/wcomponents-xslt/src/main/xslt/wc.ui.application.xsl
index 0bb337c78..97133ed63 100644
--- a/wcomponents-xslt/src/main/xslt/wc.ui.application.xsl
+++ b/wcomponents-xslt/src/main/xslt/wc.ui.application.xsl
@@ -1,8 +1,8 @@
+ xmlns:ui="https://github.com/bordertech/wcomponents/namespace/ui/v1.0"
+ xmlns:html="http://www.w3.org/1999/xhtml" version="2.0"
+ exclude-result-prefixes="xsl ui html">
@@ -18,17 +18,6 @@
@@ -40,6 +29,9 @@
hidden
+
+
+