diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 793327e005..dca17b94af 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -25,37 +25,37 @@ updates:
open-pull-requests-limit: 50
ignore:
- dependency-name: "jakarta.platform:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "jakarta.activation:jakarta.activation-api"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "jakarta.annotation:jakarta.annotation-api"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "jakarta.enterprise:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "jakarta.xml.bind:jakarta.xml.bind-api"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "jakarta.servlet.*:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "jakarta.ws.rs:jakarta.ws.rs-api"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "jakarta.validation:jakarta.validation-api"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.glassfish.web:jakarta.servlet.jsp.jstl"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.glassfish.jaxb:jaxb-runtime"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.omnifaces:omnifaces"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.springframework*:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "com.flowlogix:flowlogix-jee"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.eclipse.jetty:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
# Dependencies for Maven - on 1.12.x
- package-ecosystem: 'maven'
@@ -66,34 +66,34 @@ updates:
open-pull-requests-limit: 50
ignore:
- dependency-name: "jakarta.servlet.*:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "javax.servlet:javax.servlet-api"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.glassfish.web:jakarta.servlet.jsp.jstl"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.glassfish.jersey.*:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.jasig.cas.client:*"
- update-types: ["version-update:semver-minor"]
+ update-types: [ "version-update:semver-minor" ]
- dependency-name: "org.slf4j:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.codehaus.groovy:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "ch.qos.logback:logback-classic"
- update-types: ["version-update:semver-minor"]
+ update-types: [ "version-update:semver-minor" ]
- dependency-name: "com.hazelcast:hazelcast"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.aspectj:*"
- update-types: ["version-update:semver-patch"]
+ update-types: [ "version-update:semver-patch" ]
- dependency-name: "org.springframework*:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "org.eclipse.jetty:*"
- update-types: ["version-update:semver-major"]
+ update-types: [ "version-update:semver-major" ]
- dependency-name: "com.github.mjeanroy:junit-servers-jetty"
- update-types: ["version-update:semver-minor"]
+ update-types: [ "version-update:semver-minor" ]
# Dependencies for GitHub Actions
- package-ecosystem: 'github-actions'
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 3e013005c9..52f81d7f2d 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -59,45 +59,45 @@ jobs:
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- - name: Checkout repository
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
+ - name: Checkout repository
+ uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
- - name: Cache local Maven repository
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
- with:
- path: ~/.m2
- key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
- restore-keys: ${{ runner.os }}-m2
+ - name: Cache local Maven repository
+ uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ restore-keys: ${{ runner.os }}-m2
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
- with:
- languages: ${{ matrix.language }}
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
- # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
- # queries: security-extended,security-and-quality
+ # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
- # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
+ # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
- # âšī¸ Command-line programs to run using the OS shell.
- # đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+ # âšī¸ Command-line programs to run using the OS shell.
+ # đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- # If the Autobuild fails above, remove it and uncomment the following three lines.
- # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
+ # If the Autobuild fails above, remove it and uncomment the following three lines.
+ # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
- # - run: |
- # echo "Run, Build Application using script"
- # ./location_of_script_within_repo/buildscript.sh
+ # - run: |
+ # echo "Run, Build Application using script"
+ # ./location_of_script_within_repo/buildscript.sh
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
- with:
- category: "/language:${{matrix.language}}"
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 88e7d12cfd..ed008be6cb 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -21,7 +21,7 @@ permissions:
contents: read
on:
- workflow_dispatch: {}
+ workflow_dispatch: { }
push:
branches: [ main, '1.12.x', '1.11.x', '1.10.x' ]
pull_request:
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index ce2bee231c..026404e6b4 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -24,7 +24,7 @@ permissions:
pull-requests: write
on:
- workflow_dispatch: {}
+ workflow_dispatch: { }
schedule:
# every day 5min after midnight, UTC.
- cron: "5 0 * * *"
diff --git a/cache/pom.xml b/cache/pom.xml
index efbdae8eec..63b35d83ae 100644
--- a/cache/pom.xml
+++ b/cache/pom.xml
@@ -17,7 +17,8 @@
~ specific language governing permissions and limitations
~ under the License.
-->
-
+org.apache.shiro
diff --git a/cache/src/main/java/org/apache/shiro/cache/Cache.java b/cache/src/main/java/org/apache/shiro/cache/Cache.java
index 2b6f887f29..cea5e03d8c 100644
--- a/cache/src/main/java/org/apache/shiro/cache/Cache.java
+++ b/cache/src/main/java/org/apache/shiro/cache/Cache.java
@@ -29,6 +29,8 @@
* cache framework's cache instance (e.g. JCache, Ehcache, JCS, OSCache, JBossCache, TerraCotta, Coherence,
* GigaSpaces, etc., etc.), allowing a Shiro user to configure any cache mechanism they choose.
*
+ * @param K
+ * @param V
* @since 0.2
*/
public interface Cache {
@@ -41,7 +43,7 @@ public interface Cache {
* @return the cached object or {@code null} if there is no entry for the specified {@code key}
* @throws CacheException if there is a problem accessing the underlying cache system
*/
- public V get(K key) throws CacheException;
+ V get(K key) throws CacheException;
/**
* Adds a Cache entry.
@@ -51,7 +53,7 @@ public interface Cache {
* @return the previous value associated with the given {@code key} or {@code null} if there was previous value
* @throws CacheException if there is a problem accessing the underlying cache system
*/
- public V put(K key, V value) throws CacheException;
+ V put(K key, V value) throws CacheException;
/**
* Remove the cache entry corresponding to the specified key.
@@ -60,33 +62,33 @@ public interface Cache {
* @return the previous value associated with the given {@code key} or {@code null} if there was previous value
* @throws CacheException if there is a problem accessing the underlying cache system
*/
- public V remove(K key) throws CacheException;
+ V remove(K key) throws CacheException;
/**
* Clear all entries from the cache.
*
* @throws CacheException if there is a problem accessing the underlying cache system
*/
- public void clear() throws CacheException;
+ void clear() throws CacheException;
/**
* Returns the number of entries in the cache.
*
* @return the number of entries in the cache.
*/
- public int size();
+ int size();
/**
* Returns a view of all the keys for entries contained in this cache.
*
* @return a view of all the keys for entries contained in this cache.
*/
- public Set keys();
+ Set keys();
/**
* Returns a view of all of the values contained in this cache.
*
* @return a view of all of the values contained in this cache.
*/
- public Collection values();
+ Collection values();
}
diff --git a/cache/src/main/java/org/apache/shiro/cache/CacheException.java b/cache/src/main/java/org/apache/shiro/cache/CacheException.java
index e998dfed28..b91cdfa347 100644
--- a/cache/src/main/java/org/apache/shiro/cache/CacheException.java
+++ b/cache/src/main/java/org/apache/shiro/cache/CacheException.java
@@ -26,8 +26,7 @@
*
* @since 0.2
*/
-public class CacheException extends ShiroException
-{
+public class CacheException extends ShiroException {
/**
* Creates a new CacheException.
diff --git a/cache/src/main/java/org/apache/shiro/cache/CacheManager.java b/cache/src/main/java/org/apache/shiro/cache/CacheManager.java
index f50f06fa42..0b96b93071 100644
--- a/cache/src/main/java/org/apache/shiro/cache/CacheManager.java
+++ b/cache/src/main/java/org/apache/shiro/cache/CacheManager.java
@@ -38,5 +38,5 @@ public interface CacheManager {
* @return the Cache with the given name
* @throws CacheException if there is an error acquiring the Cache instance.
*/
- public Cache getCache(String name) throws CacheException;
+ Cache getCache(String name) throws CacheException;
}
diff --git a/cache/src/main/java/org/apache/shiro/cache/MapCache.java b/cache/src/main/java/org/apache/shiro/cache/MapCache.java
index 06dfde9105..23a4e1641a 100644
--- a/cache/src/main/java/org/apache/shiro/cache/MapCache.java
+++ b/cache/src/main/java/org/apache/shiro/cache/MapCache.java
@@ -27,6 +27,8 @@
* A MapCache is a {@link Cache Cache} implementation that uses a backing {@link Map} instance to store
* and retrieve cached data.
*
+ * @param K
+ * @param V
* @since 1.0
*/
public class MapCache implements Cache {
diff --git a/config/core/pom.xml b/config/core/pom.xml
index c41b941265..4f9e031d5d 100644
--- a/config/core/pom.xml
+++ b/config/core/pom.xml
@@ -17,7 +17,8 @@
~ specific language governing permissions and limitations
~ under the License.
-->
-
+org.apache.shiro
diff --git a/config/core/src/main/java/org/apache/shiro/config/ConfigurationException.java b/config/core/src/main/java/org/apache/shiro/config/ConfigurationException.java
index 2ae352bb95..1fdb5a7bb0 100644
--- a/config/core/src/main/java/org/apache/shiro/config/ConfigurationException.java
+++ b/config/core/src/main/java/org/apache/shiro/config/ConfigurationException.java
@@ -26,8 +26,7 @@
*
* @since 0.9
*/
-public class ConfigurationException extends ShiroException
-{
+public class ConfigurationException extends ShiroException {
/**
* Creates a new ConfigurationException.
diff --git a/config/core/src/main/java/org/apache/shiro/config/Ini.java b/config/core/src/main/java/org/apache/shiro/config/Ini.java
index a42d4a7df4..b854c5e7b4 100644
--- a/config/core/src/main/java/org/apache/shiro/config/Ini.java
+++ b/config/core/src/main/java/org/apache/shiro/config/Ini.java
@@ -44,19 +44,41 @@
*
* @since 1.0
*/
-public class Ini implements Map {
+@SuppressWarnings({"checkstyle:MethodCount", "checkstyle:CyclomaticComplexity"})
+public final class Ini implements Map {
- private static transient final Logger log = LoggerFactory.getLogger(Ini.class);
+ /**
+ * empty string means the first unnamed section
+ */
+ public static final String DEFAULT_SECTION_NAME = "";
- public static final String DEFAULT_SECTION_NAME = ""; //empty string means the first unnamed section
+ /**
+ * default charset name.
+ */
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
+ /**
+ * comment pound.
+ */
public static final String COMMENT_POUND = "#";
+
+ /**
+ * comment semicolon.
+ */
public static final String COMMENT_SEMICOLON = ";";
+
+ /**
+ * section prefix
+ */
public static final String SECTION_PREFIX = "[";
+ /**
+ * section suffix
+ */
public static final String SECTION_SUFFIX = "]";
- protected static final char ESCAPE_TOKEN = '\\';
+ private static final char ESCAPE_TOKEN = '\\';
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Ini.class);
private final Map sections;
@@ -88,7 +110,7 @@ public Ini(Ini defaults) {
* are all empty, {@code false} otherwise.
*
* @return {@code true} if no sections have been configured, or if there are sections, but the sections themselves
- * are all empty, {@code false} otherwise.
+ * are all empty, {@code false} otherwise.
*/
public boolean isEmpty() {
Collection sections = this.sections.values();
@@ -107,7 +129,7 @@ public boolean isEmpty() {
* no sections.
*
* @return the names of all sections managed by this {@code Ini} instance or an empty collection if there are
- * no sections.
+ * no sections.
*/
public Set getSectionNames() {
return Collections.unmodifiableSet(sections.keySet());
@@ -118,7 +140,7 @@ public Set getSectionNames() {
* no sections.
*
* @return the sections managed by this {@code Ini} instance or an empty collection if there are
- * no sections.
+ * no sections.
*/
public Collection getSections() {
return Collections.unmodifiableCollection(sections.values());
@@ -165,7 +187,7 @@ public Section removeSection(String sectionName) {
private static String cleanName(String sectionName) {
String name = StringUtils.clean(sectionName);
if (name == null) {
- log.trace("Specified name was null or empty. Defaulting to the default section (name = \"\")");
+ LOGGER.trace("Specified name was null or empty. Defaulting to the default section (name = \"\")");
name = DEFAULT_SECTION_NAME;
}
return name;
@@ -209,7 +231,7 @@ public String getSectionProperty(String sectionName, String propertyName) {
* @param propertyName the name of the property to add
* @param defaultValue the default value to return if the section or property do not exist.
* @return the value of the specified section property, or the {@code defaultValue} if the section or
- * property do not exist.
+ * property do not exist.
*/
public String getSectionProperty(String sectionName, String propertyName, String defaultValue) {
String value = getSectionProperty(sectionName, propertyName);
@@ -297,7 +319,7 @@ public void load(Reader reader) {
try {
scanner.close();
} catch (Exception e) {
- log.debug("Unable to cleanly close the InputStream scanner. Non-critical - ignoring.", e);
+ LOGGER.debug("Unable to cleanly close the InputStream scanner. Non-critical - ignoring.", e);
}
}
}
@@ -315,7 +337,7 @@ public void load(Reader reader) {
* [section2]
* key2 = value2
*
- *
+ *
* To be merged:
*
* [section1]
@@ -324,7 +346,7 @@ public void load(Reader reader) {
* [section2]
* key2 = new value
*
- *
+ *
* Result:
*
* [section1]
@@ -397,8 +419,8 @@ public void load(Scanner scanner) {
sectionName = newSectionName;
- if (log.isDebugEnabled()) {
- log.debug("Parsing " + SECTION_PREFIX + sectionName + SECTION_SUFFIX);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Parsing " + SECTION_PREFIX + sectionName + SECTION_SUFFIX);
}
} else {
//normal line - add it to the existing content buffer:
@@ -501,7 +523,7 @@ public Set> entrySet() {
* An {@code Ini.Section} is String-key-to-String-value Map, identifiable by a
* {@link #getName() name} unique within an {@link Ini} instance.
*/
- public static class Section implements Map {
+ public static final class Section implements Map {
private final String name;
private final Map props;
@@ -518,17 +540,13 @@ private Section(String name, String sectionContent) {
throw new NullPointerException("name");
}
this.name = name;
- Map props;
- if (StringUtils.hasText(sectionContent) ) {
+ Map props;
+ if (StringUtils.hasText(sectionContent)) {
props = toMapProps(sectionContent);
} else {
- props = new LinkedHashMap();
- }
- if ( props != null ) {
- this.props = props;
- } else {
- this.props = new LinkedHashMap();
+ props = new LinkedHashMap<>();
}
+ this.props = props;
}
private Section(Section defaults) {
@@ -573,21 +591,21 @@ protected static String[] splitKeyValue(String keyValueLine) {
StringBuilder keyBuffer = new StringBuilder();
StringBuilder valueBuffer = new StringBuilder();
- boolean buildingKey = true; //we'll build the value next:
+ //we'll build the value next:
+ boolean buildingKey = true;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (buildingKey) {
- if (isKeyValueSeparatorChar(c) && !isCharEscaped(line, i) && !isCharEscaped(line, i-1)) {
- buildingKey = false;//now start building the value
- } else if (!isCharEscaped(line, i)){
+ if (isKeyValueSeparatorChar(c) && !isCharEscaped(line, i) && !isCharEscaped(line, i - 1)) {
+ //now start building the value
+ buildingKey = false;
+ } else if (!isCharEscaped(line, i)) {
keyBuffer.append(c);
}
} else {
- if (valueBuffer.length() == 0 && isKeyValueSeparatorChar(c) && !isCharEscaped(line, i)) {
- //swallow the separator chars before we start building the value
- } else {
+ if (valueBuffer.length() != 0 || !isKeyValueSeparatorChar(c) || isCharEscaped(line, i)) {
valueBuffer.append(c);
}
}
@@ -601,9 +619,9 @@ protected static String[] splitKeyValue(String keyValueLine) {
throw new IllegalArgumentException(msg);
}
- log.trace("Discovered key/value pair: {} = {}", key, value);
+ LOGGER.trace("Discovered key/value pair: {} = {}", key, value);
- return new String[]{key, value};
+ return new String[] {key, value};
}
private static Map toMapProps(String content) {
diff --git a/config/core/src/test/groovy/org/apache/shiro/config/IniTest.groovy b/config/core/src/test/groovy/org/apache/shiro/config/IniTest.groovy
index ab1cddf9bd..c913285b82 100644
--- a/config/core/src/test/groovy/org/apache/shiro/config/IniTest.groovy
+++ b/config/core/src/test/groovy/org/apache/shiro/config/IniTest.groovy
@@ -36,8 +36,8 @@ public class IniTest {
@Test
public void testNoSections() {
String test =
- "prop1 = value1" + NL +
- "prop2 = value2";
+ "prop1 = value1" + NL +
+ "prop2 = value2";
Ini ini = new Ini();
ini.load(test);
diff --git a/config/ogdl/pom.xml b/config/ogdl/pom.xml
index dceb2065e1..c853df9154 100644
--- a/config/ogdl/pom.xml
+++ b/config/ogdl/pom.xml
@@ -17,7 +17,8 @@
~ specific language governing permissions and limitations
~ under the License.
-->
-
+org.apache.shiro
@@ -29,7 +30,8 @@
shiro-config-ogdlApache Shiro :: Configuration :: OGDLSupport for Shiro's Object Graph Definition Language (mostly used in Ini configuration) where
- declared name/value pairs are interpreted to create an object graph
+ declared name/value pairs are interpreted to create an object graph
+
bundleconfig.ogdl
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/CommonsInterpolator.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/CommonsInterpolator.java
index bd0c42b267..5b4da74a46 100644
--- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/CommonsInterpolator.java
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/CommonsInterpolator.java
@@ -55,7 +55,7 @@
*/
public class CommonsInterpolator implements Interpolator {
- final private ConfigurationInterpolator interpolator;
+ private final ConfigurationInterpolator interpolator;
public CommonsInterpolator() {
this.interpolator = new ConfigurationInterpolator();
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/Interpolator.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/Interpolator.java
index 879e61f879..84f517ce97 100644
--- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/Interpolator.java
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/Interpolator.java
@@ -28,6 +28,7 @@ public interface Interpolator {
/**
* Interpolates value and returns the result.
+ *
* @param value the source text
* @return the String result of the interpolation, or value, if there was not change.
*/
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/ReflectionBuilder.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/ReflectionBuilder.java
index f198eba0d6..06950105ec 100644
--- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/ReflectionBuilder.java
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/ReflectionBuilder.java
@@ -67,11 +67,10 @@
*
* @since 0.9
*/
+@SuppressWarnings("checkstyle:MethodCount")
public class ReflectionBuilder {
- //TODO - complete JavaDoc
-
- private static final Logger log = LoggerFactory.getLogger(ReflectionBuilder.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ReflectionBuilder.class);
private static final String OBJECT_REFERENCE_BEGIN_TOKEN = "$";
private static final String ESCAPED_OBJECT_REFERENCE_BEGIN_TOKEN = "\\$";
@@ -90,6 +89,7 @@ public class ReflectionBuilder {
/**
* Interpolation allows for ${key} substitution of values.
+ *
* @since 1.4
*/
private Interpolator interpolator;
@@ -98,6 +98,7 @@ public class ReflectionBuilder {
* @since 1.3
*/
private EventBus eventBus;
+
/**
* Keeps track of event subscribers that were automatically registered by this ReflectionBuilder during
* object construction. This is used in case a new EventBus is discovered during object graph
@@ -106,20 +107,13 @@ public class ReflectionBuilder {
*
* @since 1.3
*/
- private final Map registeredEventSubscribers;
+ private final Map registeredEventSubscribers;
/**
* @since 1.4
*/
private final BeanUtilsBean beanUtilsBean;
- //@since 1.3
- private Map createDefaultObjectMap() {
- Map map = new LinkedHashMap();
- map.put(EVENT_BUS_NAME, new DefaultEventBus());
- return map;
- }
-
private Function alternateObjectSupplier = name -> null;
public ReflectionBuilder() {
@@ -133,9 +127,9 @@ public ReflectionBuilder(Map defaults) {
beanUtilsBean = new BeanUtilsBean(new ConvertUtilsBean() {
@Override
public Object convert(String value, Class clazz) {
- if (clazz.isEnum()){
+ if (clazz.isEnum()) {
return Enum.valueOf(clazz, value);
- }else{
+ } else {
return super.convert(value, clazz);
}
}
@@ -146,12 +140,12 @@ public Object convert(String value, Class clazz) {
this.interpolator = createInterpolator();
this.objects = createDefaultObjectMap();
- this.registeredEventSubscribers = new LinkedHashMap();
+ this.registeredEventSubscribers = new LinkedHashMap<>();
apply(defaults);
}
private void apply(Map objects) {
- if(!isEmpty(objects)) {
+ if (!isEmpty(objects)) {
this.objects.putAll(objects);
}
EventBus found = findEventBus(this.objects);
@@ -159,6 +153,13 @@ private void apply(Map objects) {
enableEvents(found);
}
+ //@since 1.3
+ private Map createDefaultObjectMap() {
+ Map map = new LinkedHashMap();
+ map.put(EVENT_BUS_NAME, new DefaultEventBus());
+ return map;
+ }
+
public Map getObjects() {
return objects;
}
@@ -183,7 +184,7 @@ private void enableEvents(EventBus eventBus) {
this.eventBus = eventBus;
- for(Map.Entry entry : this.objects.entrySet()) {
+ for (Map.Entry entry : this.objects.entrySet()) {
enableEventsIfNecessary(entry.getValue(), entry.getKey());
}
}
@@ -213,6 +214,7 @@ private boolean isEventSubscriber(Object bean, String name) {
/**
* Plug in another way to get objects into configuration, ex: CDI
+ *
* @param alternateObjectSupplier not null (empty lambda ok)
* @since 2.0
*/
@@ -221,7 +223,7 @@ public void setAlternateObjectSupplier(Function alternateObjectSuppli
}
//@since 1.3
- protected EventBus findEventBus(Map objects) {
+ protected EventBus findEventBus(Map objects) {
if (isEmpty(objects)) {
return null;
@@ -229,14 +231,14 @@ protected EventBus findEventBus(Map objects) {
//prefer a named object first:
Object value = objects.get(EVENT_BUS_NAME);
- if (value != null && value instanceof EventBus) {
- return (EventBus)value;
+ if (value instanceof EventBus) {
+ return (EventBus) value;
}
//couldn't find a named 'eventBus' EventBus object. Try to find the first typed value we can:
- for( Object v : objects.values()) {
+ for (Object v : objects.values()) {
if (v instanceof EventBus) {
- return (EventBus)v;
+ return (EventBus) v;
}
}
@@ -245,7 +247,7 @@ protected EventBus findEventBus(Map objects) {
private boolean applyEventBusIfNecessary(Object value) {
if (value instanceof EventBusAware) {
- ((EventBusAware)value).setEventBus(this.eventBus);
+ ((EventBusAware) value).setEventBus(this.eventBus);
return true;
}
return false;
@@ -294,9 +296,11 @@ private String parseBeanId(String lhs) {
String rhs = interpolator.interpolate(entry.getValue());
String beanId = parseBeanId(lhs);
- if (beanId != null) { //a beanId could be parsed, so the line is a bean instance definition
+ //a beanId could be parsed, so the line is a bean instance definition
+ if (beanId != null) {
processor.add(new InstantiationStatement(beanId, rhs));
- } else { //the line must be a property configuration
+ //the line must be a property configuration
+ } else {
processor.add(new AssignmentStatement(lhs, rhs));
}
}
@@ -319,19 +323,21 @@ public void destroy() {
final Map immutableObjects = Collections.unmodifiableMap(objects);
//destroy objects in the opposite order they were initialized:
- List> entries = new ArrayList>(objects.entrySet());
+ List> entries = new ArrayList>(objects.entrySet());
Collections.reverse(entries);
- for(Map.Entry entry: entries) {
+ for (Map.Entry entry : entries) {
String id = entry.getKey();
Object bean = entry.getValue();
//don't destroy the eventbus until the end - we need it to still be 'alive' while publishing destroy events:
- if (bean != this.eventBus) { //memory equality check (not .equals) on purpose
+ //memory equality check (not .equals) on purpose
+ if (bean != this.eventBus) {
LifecycleUtils.destroy(bean);
BeanEvent event = new DestroyedBeanEvent(id, bean, immutableObjects);
eventBus.publish(event);
- this.eventBus.unregister(bean); //bean is now destroyed - it should not receive any other events
+ //bean is now destroyed - it should not receive any other events
+ this.eventBus.unregister(bean);
}
}
//only now destroy the event bus:
@@ -342,11 +348,12 @@ protected void createNewInstance(Map objects, String name, Strin
Object currentInstance = objects.get(name);
if (currentInstance != null) {
- log.info("An instance with name '{}' already exists. " +
- "Redefining this object as a new instance of type {}", name, value);
+ LOGGER.info("An instance with name '{}' already exists. "
+ + "Redefining this object as a new instance of type {}", name, value);
}
- Object instance;//name with no property, assume right hand side of equals sign is the class name:
+ //name with no property, assume right hand side of equals sign is the class name:
+ Object instance;
try {
instance = ClassUtils.newInstance(value);
if (instance instanceof Nameable) {
@@ -378,8 +385,8 @@ protected void applyProperty(String key, String value, Map objects) {
}
} else {
- throw new IllegalArgumentException("All property keys must contain a '.' character. " +
- "(e.g. myBean.property = value) These should already be separated out by buildObjects().");
+ throw new IllegalArgumentException("All property keys must contain a '.' character. "
+ + "(e.g. myBean.property = value) These should already be separated out by buildObjects().");
}
}
@@ -391,9 +398,9 @@ protected void applyGlobalProperty(Map objects, String property, String value) {
applyProperty(instance, property, value);
}
} catch (Exception e) {
- String msg = "Error retrieving property descriptor for instance " +
- "of type [" + instance.getClass().getName() + "] " +
- "while setting property [" + property + "]";
+ String msg = "Error retrieving property descriptor for instance "
+ + "of type [" + instance.getClass().getName() + "] "
+ + "while setting property [" + property + "]";
throw new ConfigurationException(msg, e);
}
}
@@ -402,14 +409,14 @@ protected void applyGlobalProperty(Map objects, String property, String value) {
protected void applySingleProperty(Map objects, String name, String property, String value) {
Object instance = objects.get(name);
if (property.equals("class")) {
- throw new IllegalArgumentException("Property keys should not contain 'class' properties since these " +
- "should already be separated out by buildObjects().");
+ throw new IllegalArgumentException("Property keys should not contain 'class' properties since these "
+ + "should already be separated out by buildObjects().");
} else if (instance == null) {
- String msg = "Configuration error. Specified object [" + name + "] with property [" +
- property + "] without first defining that object's class. Please first " +
- "specify the class property first, e.g. myObject = fully_qualified_class_name " +
- "and then define additional properties.";
+ String msg = "Configuration error. Specified object [" + name + "] with property ["
+ + property + "] without first defining that object's class. Please first "
+ + "specify the class property first, e.g. myObject = fully_qualified_class_name "
+ + "and then define additional properties.";
throw new IllegalArgumentException(msg);
} else {
@@ -428,9 +435,9 @@ protected String getId(String referenceToken) {
protected Object getReferencedObject(String id) {
Object o = objects != null && !objects.isEmpty() ? objects.get(id) : null;
if (o == null) {
- String msg = "The object with id [" + id + "] has not yet been defined and therefore cannot be " +
- "referenced. Please ensure objects are defined in the order in which they should be " +
- "created and made available for future reference.";
+ String msg = "The object with id [" + id + "] has not yet been defined and therefore cannot be "
+ + "referenced. Please ensure objects are defined in the order in which they should be "
+ + "created and made available for future reference.";
throw new UnresolveableReferenceException(msg);
}
return o;
@@ -445,7 +452,7 @@ protected String unescapeIfNecessary(String value) {
protected Object resolveReference(String reference) {
String id = getId(reference);
- log.debug("Encountered object reference '{}'. Looking up object with id '{}'", reference, id);
+ LOGGER.debug("Encountered object reference '{}'. Looking up object with id '{}'", reference, id);
final Object referencedObject = getReferencedObject(id);
if (referencedObject instanceof Factory) {
return ((Factory) referencedObject).getInstance();
@@ -460,8 +467,8 @@ protected boolean isTypedProperty(Object object, String propertyName, Class claz
try {
PropertyDescriptor descriptor = beanUtilsBean.getPropertyUtils().getPropertyDescriptor(object, propertyName);
if (descriptor == null) {
- String msg = "Property '" + propertyName + "' does not exist for object of " +
- "type " + object.getClass().getName() + ".";
+ String msg = "Property '" + propertyName + "' does not exist for object of "
+ + "type " + object.getClass().getName() + ".";
throw new ConfigurationException(msg);
}
Class propertyClazz = descriptor.getPropertyType();
@@ -485,7 +492,7 @@ protected Set> toSet(String sValue) {
if (tokens.length == 1 && isReference(tokens[0])) {
Object reference = resolveReference(tokens[0]);
if (reference instanceof Set) {
- return (Set)reference;
+ return (Set) reference;
}
}
@@ -511,7 +518,7 @@ protected Set> toSet(String sValue) {
if (tokens.length == 1 && isReference(tokens[0])) {
Object reference = resolveReference(tokens[0]);
if (reference instanceof Map) {
- return (Map)reference;
+ return (Map) reference;
}
}
@@ -519,9 +526,9 @@ protected Set> toSet(String sValue) {
for (String token : tokens) {
String[] kvPair = StringUtils.split(token, MAP_KEY_VALUE_DELIMITER);
if (kvPair == null || kvPair.length != 2) {
- String msg = "Map property value [" + sValue + "] contained key-value pair token [" +
- token + "] that does not properly split to a single key and pair. This must be the " +
- "case for all map entries.";
+ String msg = "Map property value [" + sValue + "] contained key-value pair token ["
+ + token + "] that does not properly split to a single key and pair. This must be the "
+ + "case for all map entries.";
throw new ConfigurationException(msg);
}
mapTokens.put(kvPair[0], kvPair[1]);
@@ -549,7 +556,7 @@ protected Collection> toCollection(String sValue) {
if (tokens.length == 1 && isReference(tokens[0])) {
Object reference = resolveReference(tokens[0]);
if (reference instanceof Collection) {
- return (Collection)reference;
+ return (Collection) reference;
}
}
@@ -572,7 +579,7 @@ protected List> toList(String sValue) {
if (tokens.length == 1 && isReference(tokens[0])) {
Object reference = resolveReference(tokens[0]);
if (reference instanceof List) {
- return (List)reference;
+ return (List) reference;
}
}
@@ -615,11 +622,10 @@ protected String checkForNullOrEmptyLiteral(String stringValue) {
return null;
}
//check if the value is the actual literal string 'null' (expected to be wrapped in quotes):
- if (stringValue.equals("\"null\"")) {
+ if ("\"null\"".equals(stringValue)) {
return NULL_VALUE_TOKEN;
- }
- //or the actual literal string of two quotes '""' (expected to be wrapped in quotes):
- else if (stringValue.equals("\"\"\"\"")) {
+ //or the actual literal string of two quotes '""' (expected to be wrapped in quotes):
+ } else if ("\"\"\"\"".equals(stringValue)) {
return EMPTY_STRING_VALUE_TOKEN;
} else {
return stringValue;
@@ -641,11 +647,11 @@ protected void applyProperty(Object object, String propertyPath, Object value) {
//find the end of the map reference:
mapEnd = propertyPath.indexOf(MAP_PROPERTY_END_TOKEN, mapBegin);
//find the token in between the [ and the ] (the map/array key or index):
- keyString = propertyPath.substring(mapBegin+1, mapEnd);
+ keyString = propertyPath.substring(mapBegin + 1, mapEnd);
//find out if there is more path reference to follow. If not, we're at a terminal of the OGNL expression
- if (propertyPath.length() > (mapEnd+1)) {
- remaining = propertyPath.substring(mapEnd+1);
+ if (propertyPath.length() > (mapEnd + 1)) {
+ remaining = propertyPath.substring(mapEnd + 1);
if (remaining.startsWith(".")) {
remaining = StringUtils.clean(remaining.substring(1));
}
@@ -660,7 +666,7 @@ protected void applyProperty(Object object, String propertyPath, Object value) {
} else {
//we're assigning a map or array entry. Check to see which we should call:
if (isTypedProperty(object, mapPropertyPath, Map.class)) {
- Map map = (Map)getProperty(object, mapPropertyPath);
+ Map map = (Map) getProperty(object, mapPropertyPath);
Object mapKey = resolveValue(keyString);
//noinspection unchecked
map.put(mapKey, value);
@@ -675,7 +681,7 @@ protected void applyProperty(Object object, String propertyPath, Object value) {
//recursively call this method with the remaining property path
Object referencedValue = null;
if (isTypedProperty(object, mapPropertyPath, Map.class)) {
- Map map = (Map)getProperty(object, mapPropertyPath);
+ Map map = (Map) getProperty(object, mapPropertyPath);
Object mapKey = resolveValue(keyString);
referencedValue = map.get(mapKey);
} else {
@@ -685,8 +691,8 @@ protected void applyProperty(Object object, String propertyPath, Object value) {
}
if (referencedValue == null) {
- throw new ConfigurationException("Referenced map/array value '" + mapPropertyPath + "[" +
- keyString + "]' does not exist.");
+ throw new ConfigurationException("Referenced map/array value '" + mapPropertyPath + "["
+ + keyString + "]' does not exist.");
}
applyProperty(referencedValue, remaining, value);
@@ -695,18 +701,18 @@ protected void applyProperty(Object object, String propertyPath, Object value) {
private void setProperty(Object object, String propertyPath, Object value) {
try {
- if (log.isTraceEnabled()) {
- log.trace("Applying property [{}] value [{}] on object of type [{}]",
- new Object[]{propertyPath, value, object.getClass().getName()});
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("Applying property [{}] value [{}] on object of type [{}]",
+ new Object[] {propertyPath, value, object.getClass().getName()});
}
beanUtilsBean.setProperty(object, propertyPath, value);
} catch (Exception e) {
- String msg = "Unable to set property '" + propertyPath + "' with value [" + value + "] on object " +
- "of type " + (object != null ? object.getClass().getName() : null) + ". If " +
- "'" + value + "' is a reference to another (previously defined) object, prefix it with " +
- "'" + OBJECT_REFERENCE_BEGIN_TOKEN + "' to indicate that the referenced " +
- "object should be used as the actual value. " +
- "For example, " + OBJECT_REFERENCE_BEGIN_TOKEN + value;
+ String msg = "Unable to set property '" + propertyPath + "' with value [" + value + "] on object "
+ + "of type " + (object != null ? object.getClass().getName() : null) + ". If "
+ + "'" + value + "' is a reference to another (previously defined) object, prefix it with "
+ + "'" + OBJECT_REFERENCE_BEGIN_TOKEN + "' to indicate that the referenced "
+ + "object should be used as the actual value. "
+ + "For example, " + OBJECT_REFERENCE_BEGIN_TOKEN + value;
throw new ConfigurationException(msg, e);
}
}
@@ -782,31 +788,32 @@ private Interpolator createInterpolator() {
/**
* Sets the {@link Interpolator} used when evaluating the right side of the expressions.
+ *
* @since 1.4
*/
public void setInterpolator(Interpolator interpolator) {
this.interpolator = interpolator;
}
- private class BeanConfigurationProcessor {
+ private final class BeanConfigurationProcessor {
private final List statements = new ArrayList();
private final List beanConfigurations = new ArrayList();
public void add(Statement statement) {
-
- statements.add(statement); //we execute bean configuration statements in the order they are declared.
+ //we execute bean configuration statements in the order they are declared.
+ statements.add(statement);
if (statement instanceof InstantiationStatement) {
- InstantiationStatement is = (InstantiationStatement)statement;
+ InstantiationStatement is = (InstantiationStatement) statement;
beanConfigurations.add(new BeanConfiguration(is));
} else {
- AssignmentStatement as = (AssignmentStatement)statement;
+ AssignmentStatement as = (AssignmentStatement) statement;
//statements always apply to the most recently defined bean configuration with the same name, so we
//have to traverse the configuration list starting at the end (most recent elements are appended):
boolean addedToConfig = false;
String beanName = as.getRootBeanName();
- for( int i = beanConfigurations.size()-1; i >= 0; i--) {
+ for (int i = beanConfigurations.size() - 1; i >= 0; i--) {
BeanConfiguration mostRecent = beanConfigurations.get(i);
String mostRecentBeanName = mostRecent.getBeanName();
if (beanName.equals(mostRecentBeanName)) {
@@ -828,17 +835,18 @@ public void add(Statement statement) {
public void execute() {
- for( Statement statement : statements) {
+ for (Statement statement : statements) {
statement.execute();
BeanConfiguration bd = statement.getBeanConfiguration();
- if (bd.isExecuted()) { //bean is fully configured, no more statements to execute for it:
+ //bean is fully configured, no more statements to execute for it:
+ if (bd.isExecuted()) {
//bean configured overrides the 'eventBus' bean - replace the existing eventBus with the one configured:
if (bd.getBeanName().equals(EVENT_BUS_NAME)) {
- EventBus eventBus = (EventBus)bd.getBean();
+ EventBus eventBus = (EventBus) bd.getBean();
enableEvents(eventBus);
}
@@ -863,7 +871,7 @@ public void execute() {
}
}
- private class BeanConfiguration {
+ private final class BeanConfiguration {
private final InstantiationStatement instantiationStatement;
private final List assignments = new ArrayList();
@@ -886,7 +894,12 @@ public String getBeanName() {
return this.beanName;
}
- public boolean isGlobalConfig() { //BeanConfiguration instance representing the global 'shiro.' properties
+ /**
+ * BeanConfiguration instance representing the global 'shiro.' properties
+ *
+ * @return boolean
+ */
+ public boolean isGlobalConfig() {
// (we should remove this concept).
return GLOBAL_PROPERTY_PREFIX.equals(getBeanName());
}
@@ -912,6 +925,7 @@ public Object getBean() {
/**
* Returns true if all configuration statements have been executed.
+ *
* @return true if all configuration statements have been executed.
*/
public boolean isExecuted() {
@@ -983,7 +997,7 @@ public boolean isExecuted() {
}
}
- private class InstantiationStatement extends Statement {
+ private final class InstantiationStatement extends Statement {
private InstantiationStatement(String lhs, String rhs) {
super(lhs, rhs);
@@ -1008,7 +1022,7 @@ protected Object doExecute() {
}
}
- private class AssignmentStatement extends Statement {
+ private final class AssignmentStatement extends Statement {
private final String rootBeanName;
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/ConfiguredBeanEvent.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/ConfiguredBeanEvent.java
index 2a196a58e4..619620e6a2 100644
--- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/ConfiguredBeanEvent.java
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/ConfiguredBeanEvent.java
@@ -24,11 +24,11 @@
* Event triggered when a configured bean has been instantiated and fully configured but right before the bean has been
* initialized.
*
- * @since 1.3
* @see InstantiatedBeanEvent
* @see org.apache.shiro.lang.util.Initializable Initializable
* @see InitializedBeanEvent
* @see DestroyedBeanEvent
+ * @since 1.3
*/
public class ConfiguredBeanEvent extends BeanEvent {
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/DestroyedBeanEvent.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/DestroyedBeanEvent.java
index f4924cb68a..090d985bbe 100644
--- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/DestroyedBeanEvent.java
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/DestroyedBeanEvent.java
@@ -23,11 +23,11 @@
/**
* Event triggered when a configured bean has been destroyed.
*
- * @since 1.3
* @see org.apache.shiro.lang.util.Destroyable Destroyable
* @see InstantiatedBeanEvent
* @see ConfiguredBeanEvent
* @see InitializedBeanEvent
+ * @since 1.3
*/
public class DestroyedBeanEvent extends BeanEvent {
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/InitializedBeanEvent.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/InitializedBeanEvent.java
index 44a8dfc930..98d180ba08 100644
--- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/InitializedBeanEvent.java
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/InitializedBeanEvent.java
@@ -23,11 +23,11 @@
/**
* Event triggered when a configured bean has been instantiated, fully configured and initialized.
*
- * @since 1.3
* @see org.apache.shiro.lang.util.Initializable Initializable
* @see InstantiatedBeanEvent
* @see ConfiguredBeanEvent
* @see DestroyedBeanEvent
+ * @since 1.3
*/
public class InitializedBeanEvent extends BeanEvent {
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/InstantiatedBeanEvent.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/InstantiatedBeanEvent.java
index b6eec57088..372bf6162d 100644
--- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/InstantiatedBeanEvent.java
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/InstantiatedBeanEvent.java
@@ -23,11 +23,11 @@
/**
* Event triggered when a configured bean has been instantiated but before it is configured or initialized.
*
- * @since 1.3
* @see ConfiguredBeanEvent
* @see InitializedBeanEvent
* @see DestroyedBeanEvent
* @see org.apache.shiro.lang.util.Initializable Initializable
+ * @since 1.3
*/
public class InstantiatedBeanEvent extends BeanEvent {
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/LoggingBeanEventListener.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/LoggingBeanEventListener.java
index 24c709954d..3b9ada4546 100644
--- a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/LoggingBeanEventListener.java
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/LoggingBeanEventListener.java
@@ -29,7 +29,7 @@
*/
public class LoggingBeanEventListener {
- private static final Logger logger = LoggerFactory.getLogger(LoggingBeanEventListener.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(LoggingBeanEventListener.class);
private static final String SUFFIX = BeanEvent.class.getSimpleName();
@Subscribe
@@ -37,6 +37,6 @@ public void onEvent(BeanEvent e) {
String className = e.getClass().getSimpleName();
int i = className.lastIndexOf(SUFFIX);
String subclassPrefix = i > 0 ? className.substring(0, i) : className;
- logger.trace("{} bean '{}' [{}]", new Object[]{subclassPrefix, e.getBeanName(), e.getBean()});
+ LOGGER.trace("{} bean '{}' [{}]", subclassPrefix, e.getBeanName(), e.getBean());
}
}
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/package-info.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/package-info.java
new file mode 100644
index 0000000000..e7f1312175
--- /dev/null
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/event/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.shiro.config.ogdl.event;
diff --git a/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/package-info.java b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/package-info.java
new file mode 100644
index 0000000000..daf21d2eb5
--- /dev/null
+++ b/config/ogdl/src/main/java/org/apache/shiro/config/ogdl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.shiro.config.ogdl;
diff --git a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/CompositeBean.groovy b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/CompositeBean.groovy
index ff4d5bb171..0ae0632afb 100644
--- a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/CompositeBean.groovy
+++ b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/CompositeBean.groovy
@@ -34,7 +34,7 @@ class CompositeBean {
Map compositeBeanMap;
CompositeBean[] compositeBeanArray;
- public CompositeBean(){}
+ public CompositeBean() {}
public CompositeBean(String name) {
this.name = name
diff --git a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/InitializableBean.groovy b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/InitializableBean.groovy
index 05b35f0899..cc5d8f3d3d 100644
--- a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/InitializableBean.groovy
+++ b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/InitializableBean.groovy
@@ -28,7 +28,7 @@ class InitializableBean implements Initializable {
private volatile boolean initialized = false;
- public InitializableBean(){}
+ public InitializableBean() {}
public void init() throws ShiroException {
initialized = true;
diff --git a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/RecordingBeanListener.groovy b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/RecordingBeanListener.groovy
index afb4aa6d5e..b2e8281024 100644
--- a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/RecordingBeanListener.groovy
+++ b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/RecordingBeanListener.groovy
@@ -32,31 +32,36 @@ public class RecordingBeanListener {
private List destroyedEvents = new ArrayList();
private List unhandledEvents = new ArrayList();
- @SuppressWarnings("UnusedDeclaration") //used via reflection
+ @SuppressWarnings("UnusedDeclaration")
+ //used via reflection
@Subscribe
public void onUnhandledBeanEvent(BeanEvent beanEvent) {
this.unhandledEvents.add(beanEvent);
}
- @SuppressWarnings("UnusedDeclaration") //used via reflection
+ @SuppressWarnings("UnusedDeclaration")
+ //used via reflection
@Subscribe
public void onInstantiatedBeanEvent(InstantiatedBeanEvent beanEvent) {
this.instantiateEvents.add(beanEvent);
}
- @SuppressWarnings("UnusedDeclaration") //used via reflection
+ @SuppressWarnings("UnusedDeclaration")
+ //used via reflection
@Subscribe
public void onConfiguredBeanEvent(ConfiguredBeanEvent beanEvent) {
this.configuredEvents.add(beanEvent);
}
- @SuppressWarnings("UnusedDeclaration") //used via reflection
+ @SuppressWarnings("UnusedDeclaration")
+ //used via reflection
@Subscribe
public void onInitializedBeanEvent(InitializedBeanEvent beanEvent) {
this.initializedEvents.add(beanEvent);
}
- @SuppressWarnings("UnusedDeclaration") //used via reflection
+ @SuppressWarnings("UnusedDeclaration")
+ //used via reflection
@Subscribe
public void onDestroyedBeanEvent(DestroyedBeanEvent beanEvent) {
this.destroyedEvents.add(beanEvent);
diff --git a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/ReflectionBuilderTest.groovy b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/ReflectionBuilderTest.groovy
index 2e8e0ec376..86af2eea35 100644
--- a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/ReflectionBuilderTest.groovy
+++ b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/ReflectionBuilderTest.groovy
@@ -134,7 +134,7 @@ class ReflectionBuilderTest {
@Test
void testWithConfiguredNullValue() {
- Map defaults = new LinkedHashMap();
+ Map defaults = new LinkedHashMap();
CompositeBean cBean = new CompositeBean();
cBean.setSimpleBean(new SimpleBean());
defaults.put("compositeBean", cBean);
@@ -296,7 +296,7 @@ class ReflectionBuilderTest {
def set = [new SimpleBean('foo'), new SimpleBean('bar')] as Set
def defs = [
- compositeBean: 'org.apache.shiro.config.ogdl.CompositeBean',
+ compositeBean : 'org.apache.shiro.config.ogdl.CompositeBean',
'compositeBean.simpleBeanSet': '$set'
]
@@ -337,7 +337,7 @@ class ReflectionBuilderTest {
List list = [new SimpleBean('foo'), new SimpleBean('bar')] as List
def defs = [
- compositeBean: 'org.apache.shiro.config.ogdl.CompositeBean',
+ compositeBean : 'org.apache.shiro.config.ogdl.CompositeBean',
'compositeBean.simpleBeanList': '$list'
]
@@ -378,7 +378,7 @@ class ReflectionBuilderTest {
def c = [new SimpleBean('foo'), new SimpleBean('bar')]
def defs = [
- compositeBean: 'org.apache.shiro.config.ogdl.CompositeBean',
+ compositeBean : 'org.apache.shiro.config.ogdl.CompositeBean',
'compositeBean.simpleBeanCollection': '$collection'
]
@@ -391,7 +391,7 @@ class ReflectionBuilderTest {
assertNotNull(simpleBeans);
assertSame c, simpleBeans
assertEquals(2, simpleBeans.size());
- def i = simpleBeans.iterator()
+ def i = simpleBeans.iterator()
assertEquals 'foo', i.next().name
assertEquals 'bar', i.next().name
}
@@ -463,7 +463,7 @@ class ReflectionBuilderTest {
def map = ['foo': new SimpleBean('foo'), 'bar': new SimpleBean('bar')]
def defs = [
- compositeBean: 'org.apache.shiro.config.ogdl.CompositeBean',
+ compositeBean : 'org.apache.shiro.config.ogdl.CompositeBean',
'compositeBean.simpleBeanMap': '$map'
]
@@ -718,8 +718,8 @@ class ReflectionBuilderTest {
}
void checkType(String instanceName, List extends BeanEvent> events, String name, Class> expectedType) {
- for(BeanEvent event: events) {
- if(event.getBeanName().equals(name)) {
+ for (BeanEvent event : events) {
+ if (event.getBeanName().equals(name)) {
assertTrue(
expectedType.isInstance(event.getBean()),
"Notification for bean " + name + " did not provide an instance of " + expectedType
diff --git a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/SimpleBean.groovy b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/SimpleBean.groovy
index 8fd9b7f346..b15ffb40df 100644
--- a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/SimpleBean.groovy
+++ b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/SimpleBean.groovy
@@ -26,10 +26,11 @@ class SimpleBean {
byte[] byteArrayProp;
List simpleBeans;
List stringList;
- Map mapProp = new LinkedHashMap();
+ Map mapProp = new LinkedHashMap();
SimpleEnum simpleEnum;
- public SimpleBean(){}
+ public SimpleBean() {}
+
public SimpleBean(String name) {
this.name = name
}
diff --git a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/event/BeanEventTest.groovy b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/event/BeanEventTest.groovy
index d784d97dcb..196c86ebf8 100644
--- a/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/event/BeanEventTest.groovy
+++ b/config/ogdl/src/test/groovy/org/apache/shiro/config/ogdl/event/BeanEventTest.groovy
@@ -31,7 +31,7 @@ class BeanEventTest {
@Test
void testDefault() {
- def m = [foo: 'bar'] as Map
+ def m = [foo: 'bar'] as Map
Object o = new Object()
BeanEvent evt = new MyBeanEvent('baz', o, m)
diff --git a/config/pom.xml b/config/pom.xml
index 7b885c4d79..681049c197 100644
--- a/config/pom.xml
+++ b/config/pom.xml
@@ -17,7 +17,8 @@
~ specific language governing permissions and limitations
~ under the License.
-->
-
+4.0.0
diff --git a/core/pom.xml b/core/pom.xml
index a81cbf4712..57c0e5b30d 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -17,7 +17,8 @@
~ specific language governing permissions and limitations
~ under the License.
-->
-
+org.apache.shiro
@@ -36,7 +37,7 @@
-
+ org.apache.maven.pluginsmaven-jar-plugin
diff --git a/core/src/main/java/org/apache/shiro/SecurityUtils.java b/core/src/main/java/org/apache/shiro/SecurityUtils.java
index 058ccf4c5c..71ee87a5db 100644
--- a/core/src/main/java/org/apache/shiro/SecurityUtils.java
+++ b/core/src/main/java/org/apache/shiro/SecurityUtils.java
@@ -107,9 +107,8 @@ public static void setSecurityManager(SecurityManager securityManager) {
* to calling code in an application. If it is not, it is likely due to a Shiro configuration problem.
*
* @return the SecurityManager accessible to the calling code.
- * @throws UnavailableSecurityManagerException
- * if there is no {@code SecurityManager} instance available to the
- * calling code, which typically indicates an invalid application configuration.
+ * @throws UnavailableSecurityManagerException if there is no {@code SecurityManager} instance available to the
+ * calling code, which typically indicates an invalid application configuration.
*/
public static SecurityManager getSecurityManager() throws UnavailableSecurityManagerException {
SecurityManager securityManager = ThreadContext.getSecurityManager();
@@ -117,9 +116,9 @@ public static SecurityManager getSecurityManager() throws UnavailableSecurityMan
securityManager = SecurityUtils.securityManager;
}
if (securityManager == null) {
- String msg = "No SecurityManager accessible to the calling code, either bound to the " +
- ThreadContext.class.getName() + " or as a vm static singleton. This is an invalid application " +
- "configuration.";
+ String msg = "No SecurityManager accessible to the calling code, either bound to the "
+ + ThreadContext.class.getName() + " or as a vm static singleton. This is an invalid application "
+ + "configuration.";
throw new UnavailableSecurityManagerException(msg);
}
return securityManager;
diff --git a/core/src/main/java/org/apache/shiro/aop/AnnotationHandler.java b/core/src/main/java/org/apache/shiro/aop/AnnotationHandler.java
index 706c56e8c3..d1c567674a 100644
--- a/core/src/main/java/org/apache/shiro/aop/AnnotationHandler.java
+++ b/core/src/main/java/org/apache/shiro/aop/AnnotationHandler.java
@@ -49,7 +49,8 @@ public AnnotationHandler(Class extends Annotation> annotationClass) {
/**
* Returns the {@link org.apache.shiro.subject.Subject Subject} associated with the currently-executing code.
*
- * This default implementation merely calls {@link org.apache.shiro.SecurityUtils#getSubject SecurityUtils.getSubject()}.
+ * This default implementation merely calls
+ * {@link org.apache.shiro.SecurityUtils#getSubject SecurityUtils.getSubject()}.
*
* @return the {@link org.apache.shiro.subject.Subject Subject} associated with the currently-executing code.
*/
diff --git a/core/src/main/java/org/apache/shiro/aop/AnnotationMethodInterceptor.java b/core/src/main/java/org/apache/shiro/aop/AnnotationMethodInterceptor.java
index 9179651dcf..fab7d3cdbc 100644
--- a/core/src/main/java/org/apache/shiro/aop/AnnotationMethodInterceptor.java
+++ b/core/src/main/java/org/apache/shiro/aop/AnnotationMethodInterceptor.java
@@ -75,7 +75,7 @@ public AnnotationMethodInterceptor(AnnotationHandler handler, AnnotationResolver
* an annotation discovered at runtime.
*
* @return the {@code AnnotationHandler} used to perform authorization behavior based on
- * an annotation discovered at runtime.
+ * an annotation discovered at runtime.
*/
public AnnotationHandler getHandler() {
return handler;
@@ -98,7 +98,7 @@ public void setHandler(AnnotationHandler handler) {
* perform authorization logic.
*
* @return the {@code AnnotationResolver} to use to acquire annotations from intercepted
- * methods at runtime.
+ * methods at runtime.
* @since 1.1
*/
public AnnotationResolver getResolver() {
@@ -128,7 +128,7 @@ public void setResolver(AnnotationResolver resolver) {
*
* @param mi the MethodInvocation for the method being invoked.
* @return true if this interceptor supports, that is, should inspect, the specified
- * MethodInvocation, false otherwise.
+ * MethodInvocation, false otherwise.
*/
public boolean supports(MethodInvocation mi) {
return getAnnotation(mi) != null;
diff --git a/core/src/main/java/org/apache/shiro/aop/AnnotationResolver.java b/core/src/main/java/org/apache/shiro/aop/AnnotationResolver.java
index 7934884503..2e96dff31e 100644
--- a/core/src/main/java/org/apache/shiro/aop/AnnotationResolver.java
+++ b/core/src/main/java/org/apache/shiro/aop/AnnotationResolver.java
@@ -1,42 +1,42 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.shiro.aop;
-
-import java.lang.annotation.Annotation;
-
-/**
- * Defines an AOP-framework-independent way of determining if an Annotation exists on a Method.
- *
- * @since 1.1
- */
-public interface AnnotationResolver {
-
- /**
- * Returns an {@link Annotation} instance of the specified type based on the given
- * {@link MethodInvocation MethodInvocation} argument, or {@code null} if no annotation
- * of that type could be found. First checks the invoked method itself and if not found,
- * then the class for the existence of the same annotation.
- *
- * @param mi the intercepted method to be invoked.
- * @param clazz the annotation class of the annotation to find.
- * @return the method's annotation of the specified type or {@code null} if no annotation of
- * that type could be found.
- */
- Annotation getAnnotation(MethodInvocation mi, Class extends Annotation> clazz);
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.aop;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Defines an AOP-framework-independent way of determining if an Annotation exists on a Method.
+ *
+ * @since 1.1
+ */
+public interface AnnotationResolver {
+
+ /**
+ * Returns an {@link Annotation} instance of the specified type based on the given
+ * {@link MethodInvocation MethodInvocation} argument, or {@code null} if no annotation
+ * of that type could be found. First checks the invoked method itself and if not found,
+ * then the class for the existence of the same annotation.
+ *
+ * @param mi the intercepted method to be invoked.
+ * @param clazz the annotation class of the annotation to find.
+ * @return the method's annotation of the specified type or {@code null} if no annotation of
+ * that type could be found.
+ */
+ Annotation getAnnotation(MethodInvocation mi, Class extends Annotation> clazz);
+}
diff --git a/core/src/main/java/org/apache/shiro/aop/DefaultAnnotationResolver.java b/core/src/main/java/org/apache/shiro/aop/DefaultAnnotationResolver.java
index d7fd4aec7a..c020588ce1 100644
--- a/core/src/main/java/org/apache/shiro/aop/DefaultAnnotationResolver.java
+++ b/core/src/main/java/org/apache/shiro/aop/DefaultAnnotationResolver.java
@@ -1,69 +1,70 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.shiro.aop;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-
-/**
- * Default {@code AnnotationResolver} implementation that merely inspects the
- * {@link MethodInvocation MethodInvocation}'s {@link MethodInvocation#getMethod() target method},
- * and returns {@code targetMethod}.{@link Method#getAnnotation(Class) getAnnotation(class)}.
- *
- * Unfortunately Java's default reflection API for Annotations is not very robust, and this logic
- * may not be enough - if the incoming method invocation represents a method from an interface,
- * this default logic would not discover the annotation if it existed on the method implementation
- * directly (as opposed to being defined directly in the interface definition).
- *
- * More complex class hierarchy traversal logic is required to exhaust a method's target object's
- * classes, parent classes, interfaces and parent interfaces. That logic will likely be added
- * to this implementation in due time, but for now, this implementation relies on the JDK's default
- * {@link Method#getAnnotation(Class) Method.getAnnotation(class)} logic.
- *
- * @since 1.1
- */
-public class DefaultAnnotationResolver implements AnnotationResolver {
-
- /**
- * Returns {@code methodInvocation.}{@link org.apache.shiro.aop.MethodInvocation#getMethod() getMethod()}.{@link Method#getAnnotation(Class) getAnnotation(clazz)}.
- *
- * @param mi the intercepted method to be invoked.
- * @param clazz the annotation class to use to find an annotation instance on the method.
- * @return the discovered annotation or {@code null} if an annotation instance could not be
- * found.
- */
- public Annotation getAnnotation(MethodInvocation mi, Class extends Annotation> clazz) {
- if (mi == null) {
- throw new IllegalArgumentException("method argument cannot be null");
- }
- Method m = mi.getMethod();
- if (m == null) {
- String msg = MethodInvocation.class.getName() + " parameter incorrectly constructed. getMethod() returned null";
- throw new IllegalArgumentException(msg);
-
- }
- Annotation annotation = m.getAnnotation(clazz);
- if (annotation == null ) {
- Object miThis = mi.getThis();
- //SHIRO-473 - miThis could be null for static methods, just return null
- annotation = miThis != null ? miThis.getClass().getAnnotation(clazz) : null;
- }
- return annotation;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.aop;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * Default {@code AnnotationResolver} implementation that merely inspects the
+ * {@link MethodInvocation MethodInvocation}'s {@link MethodInvocation#getMethod() target method},
+ * and returns {@code targetMethod}.{@link Method#getAnnotation(Class) getAnnotation(class)}.
+ *
+ * Unfortunately Java's default reflection API for Annotations is not very robust, and this logic
+ * may not be enough - if the incoming method invocation represents a method from an interface,
+ * this default logic would not discover the annotation if it existed on the method implementation
+ * directly (as opposed to being defined directly in the interface definition).
+ *
+ * More complex class hierarchy traversal logic is required to exhaust a method's target object's
+ * classes, parent classes, interfaces and parent interfaces. That logic will likely be added
+ * to this implementation in due time, but for now, this implementation relies on the JDK's default
+ * {@link Method#getAnnotation(Class) Method.getAnnotation(class)} logic.
+ *
+ * @since 1.1
+ */
+public class DefaultAnnotationResolver implements AnnotationResolver {
+
+ /**
+ * Returns {@code methodInvocation.}{@link org.apache.shiro.aop.MethodInvocation#getMethod() getMethod()}.
+ * {@link Method#getAnnotation(Class) getAnnotation(clazz)}.
+ *
+ * @param mi the intercepted method to be invoked.
+ * @param clazz the annotation class to use to find an annotation instance on the method.
+ * @return the discovered annotation or {@code null} if an annotation instance could not be
+ * found.
+ */
+ public Annotation getAnnotation(MethodInvocation mi, Class extends Annotation> clazz) {
+ if (mi == null) {
+ throw new IllegalArgumentException("method argument cannot be null");
+ }
+ Method m = mi.getMethod();
+ if (m == null) {
+ String msg = MethodInvocation.class.getName() + " parameter incorrectly constructed. getMethod() returned null";
+ throw new IllegalArgumentException(msg);
+
+ }
+ Annotation annotation = m.getAnnotation(clazz);
+ if (annotation == null) {
+ Object miThis = mi.getThis();
+ //SHIRO-473 - miThis could be null for static methods, just return null
+ annotation = miThis != null ? miThis.getClass().getAnnotation(clazz) : null;
+ }
+ return annotation;
+ }
+}
diff --git a/core/src/main/java/org/apache/shiro/aop/MethodInterceptorSupport.java b/core/src/main/java/org/apache/shiro/aop/MethodInterceptorSupport.java
index e21772ecda..2be6b3f1fb 100644
--- a/core/src/main/java/org/apache/shiro/aop/MethodInterceptorSupport.java
+++ b/core/src/main/java/org/apache/shiro/aop/MethodInterceptorSupport.java
@@ -40,7 +40,8 @@ public MethodInterceptorSupport() {
/**
* Returns the {@link Subject Subject} associated with the currently-executing code.
*
- * This default implementation merely calls {@link org.apache.shiro.SecurityUtils#getSubject SecurityUtils.getSubject()}.
+ * This default implementation merely calls
+ * {@link org.apache.shiro.SecurityUtils#getSubject SecurityUtils.getSubject()}.
*
* @return the {@link org.apache.shiro.subject.Subject Subject} associated with the currently-executing code.
*/
diff --git a/core/src/main/java/org/apache/shiro/aop/package-info.java b/core/src/main/java/org/apache/shiro/aop/package-info.java
index 0daa7749a0..3e9806cc24 100644
--- a/core/src/main/java/org/apache/shiro/aop/package-info.java
+++ b/core/src/main/java/org/apache/shiro/aop/package-info.java
@@ -23,4 +23,4 @@
* useful for any AOP environment and/or function. Feature-dependent AOP classes (e.g. authorization,
* authentication, etc.) will use these classes as their base in their respective packages.
*/
-package org.apache.shiro.aop;
\ No newline at end of file
+package org.apache.shiro.aop;
diff --git a/core/src/main/java/org/apache/shiro/authc/AbstractAuthenticator.java b/core/src/main/java/org/apache/shiro/authc/AbstractAuthenticator.java
index 125929bf72..278dae9010 100644
--- a/core/src/main/java/org/apache/shiro/authc/AbstractAuthenticator.java
+++ b/core/src/main/java/org/apache/shiro/authc/AbstractAuthenticator.java
@@ -48,7 +48,7 @@ public abstract class AbstractAuthenticator implements Authenticator, LogoutAwar
/**
* Private class log instance.
*/
- private static final Logger log = LoggerFactory.getLogger(AbstractAuthenticator.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAuthenticator.class);
/*-------------------------------------------
| I N S T A N C E V A R I A B L E S |
@@ -95,7 +95,7 @@ public void setAuthenticationListeners(Collection listen
* attempts.
*
* @return the {@link AuthenticationListener AuthenticationListener}s that should be notified during authentication
- * attempts.
+ * attempts.
*/
@SuppressWarnings({"UnusedDeclaration"})
public Collection getAuthenticationListeners() {
@@ -191,14 +191,14 @@ public final AuthenticationInfo authenticate(AuthenticationToken token) throws A
throw new IllegalArgumentException("Method argument (authentication token) cannot be null.");
}
- log.trace("Authentication attempt received for token [{}]", token);
+ LOGGER.trace("Authentication attempt received for token [{}]", token);
AuthenticationInfo info;
try {
info = doAuthenticate(token);
if (info == null) {
- String msg = "No account information found for authentication token [" + token + "] by this " +
- "Authenticator instance. Please check that it is configured correctly.";
+ String msg = "No account information found for authentication token [" + token + "] by this "
+ + "Authenticator instance. Please check that it is configured correctly.";
throw new AuthenticationException(msg);
}
} catch (Throwable t) {
@@ -209,20 +209,21 @@ public final AuthenticationInfo authenticate(AuthenticationToken token) throws A
if (ae == null) {
//Exception thrown was not an expected AuthenticationException. Therefore it is probably a little more
//severe or unexpected. So, wrap in an AuthenticationException, log to warn, and propagate:
- String msg = "Authentication failed for token submission [" + token + "]. Possible unexpected " +
- "error? (Typical or expected login exceptions should extend from AuthenticationException).";
+ String msg = "Authentication failed for token submission [" + token + "]. Possible unexpected "
+ + "error? (Typical or expected login exceptions should extend from AuthenticationException).";
ae = new AuthenticationException(msg, t);
- if (log.isWarnEnabled())
- log.warn(msg, t);
+ if (LOGGER.isWarnEnabled()) {
+ LOGGER.warn(msg, t);
+ }
}
try {
notifyFailure(token, ae);
} catch (Throwable t2) {
- if (log.isWarnEnabled()) {
- String msg = "Unable to send notification for failed authentication attempt - listener error?. " +
- "Please check your AuthenticationListener implementation(s). Logging sending exception " +
- "and propagating original AuthenticationException instead...";
- log.warn(msg, t2);
+ if (LOGGER.isWarnEnabled()) {
+ String msg = "Unable to send notification for failed authentication attempt - listener error?. "
+ + "Please check your AuthenticationListener implementation(s). Logging sending exception "
+ + "and propagating original AuthenticationException instead...";
+ LOGGER.warn(msg, t2);
}
}
@@ -230,7 +231,7 @@ public final AuthenticationInfo authenticate(AuthenticationToken token) throws A
throw ae;
}
- log.debug("Authentication successful for token [{}]. Returned account [{}]", token, info);
+ LOGGER.debug("Authentication successful for token [{}]. Returned account [{}]", token, info);
notifySuccess(token, info);
@@ -251,7 +252,7 @@ public final AuthenticationInfo authenticate(AuthenticationToken token) throws A
*
* @param token the authentication token encapsulating the user's login information.
* @return an {@code AuthenticationInfo} object encapsulating the user's account information
- * important to Shiro.
+ * important to Shiro.
* @throws AuthenticationException if there is a problem logging in the user.
*/
protected abstract AuthenticationInfo doAuthenticate(AuthenticationToken token)
diff --git a/core/src/main/java/org/apache/shiro/authc/AuthenticationException.java b/core/src/main/java/org/apache/shiro/authc/AuthenticationException.java
index 18ee77062c..6f4f497fee 100644
--- a/core/src/main/java/org/apache/shiro/authc/AuthenticationException.java
+++ b/core/src/main/java/org/apache/shiro/authc/AuthenticationException.java
@@ -26,8 +26,7 @@
*
* @since 0.1
*/
-public class AuthenticationException extends ShiroException
-{
+public class AuthenticationException extends ShiroException {
/**
* Creates a new AuthenticationException.
diff --git a/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java b/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java
index 3c20f0a0f7..5184c1a5f7 100644
--- a/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java
+++ b/core/src/main/java/org/apache/shiro/authc/AuthenticationInfo.java
@@ -46,8 +46,9 @@
* preferences.
*
*
Please note: Since Shiro sometimes logs authentication operations, please ensure your AuthenticationInfo's
- * toString() implementation does not print out account credentials (password, etc.), as these might be viewable to
- * someone reading your logs. This is good practice anyway, and account credentials should rarely (if ever) be printed
+ * toString() implementation does not print out account credentials (password, etc.),
+ * as these might be viewable to someone reading your logs.
+ * This is good practice anyway, and account credentials should rarely (if ever) be printed
* out for any reason. If you're using Shiro's default implementations of this interface, they only ever print the
* account {@link #getPrincipals() principals}, so you do not need to do anything additional.
*
diff --git a/core/src/main/java/org/apache/shiro/authc/Authenticator.java b/core/src/main/java/org/apache/shiro/authc/Authenticator.java
index ca4df4236d..0bcd93bf71 100644
--- a/core/src/main/java/org/apache/shiro/authc/Authenticator.java
+++ b/core/src/main/java/org/apache/shiro/authc/Authenticator.java
@@ -62,6 +62,6 @@ public interface Authenticator {
* @see ConcurrentAccessException
* @see UnknownAccountException
*/
- public AuthenticationInfo authenticate(AuthenticationToken authenticationToken)
+ AuthenticationInfo authenticate(AuthenticationToken authenticationToken)
throws AuthenticationException;
}
diff --git a/core/src/main/java/org/apache/shiro/authc/BearerToken.java b/core/src/main/java/org/apache/shiro/authc/BearerToken.java
index 51fe909003..2a193e010e 100644
--- a/core/src/main/java/org/apache/shiro/authc/BearerToken.java
+++ b/core/src/main/java/org/apache/shiro/authc/BearerToken.java
@@ -20,13 +20,13 @@
/**
- * A {@link AuthenticationToken} that contains an a Bearer token or API key, typically received via an HTTP {@code Authorization} header. This
- * class also implements the {@link org.apache.shiro.authc.HostAuthenticationToken HostAuthenticationToken} interface to retain the host name
- * or IP address location from where the authentication attempt is occurring.
+ * A {@link AuthenticationToken} that contains a Bearer token or API key, typically received via an HTTP
+ * {@code Authorization} header. This class also implements the
+ * {@link org.apache.shiro.authc.HostAuthenticationToken HostAuthenticationToken} interface to
+ * retain the host name or IP address location from where the authentication attempt is occurring.
*
* @see RFC 2617
* @see OAuth2 Authorization Request Header Field
- *
* @since 1.5
*/
public class BearerToken implements HostAuthenticationToken {
diff --git a/core/src/main/java/org/apache/shiro/authc/HostAuthenticationToken.java b/core/src/main/java/org/apache/shiro/authc/HostAuthenticationToken.java
index 475b9f70f5..599b318b41 100644
--- a/core/src/main/java/org/apache/shiro/authc/HostAuthenticationToken.java
+++ b/core/src/main/java/org/apache/shiro/authc/HostAuthenticationToken.java
@@ -36,9 +36,9 @@ public interface HostAuthenticationToken extends AuthenticationToken {
* {@code ServletRequest.getRemoteHost()} value.
*
* @return the fully qualified name of the client from where the
- * authentication attempt originates or the String representation
- * of the client's IP address is hostname resolution is not
- * available or disabled.
+ * authentication attempt originates or the String representation
+ * of the client's IP address is hostname resolution is not
+ * available or disabled.
*/
String getHost();
}
diff --git a/core/src/main/java/org/apache/shiro/authc/LogoutAware.java b/core/src/main/java/org/apache/shiro/authc/LogoutAware.java
index d686bfcd3d..30196fa70f 100644
--- a/core/src/main/java/org/apache/shiro/authc/LogoutAware.java
+++ b/core/src/main/java/org/apache/shiro/authc/LogoutAware.java
@@ -37,5 +37,5 @@ public interface LogoutAware {
*
* @param principals the identifying principals of the Subject logging out.
*/
- public void onLogout(PrincipalCollection principals);
+ void onLogout(PrincipalCollection principals);
}
diff --git a/core/src/main/java/org/apache/shiro/authc/RememberMeAuthenticationToken.java b/core/src/main/java/org/apache/shiro/authc/RememberMeAuthenticationToken.java
index 88da10dd57..28aaff1cdd 100644
--- a/core/src/main/java/org/apache/shiro/authc/RememberMeAuthenticationToken.java
+++ b/core/src/main/java/org/apache/shiro/authc/RememberMeAuthenticationToken.java
@@ -36,7 +36,7 @@ public interface RememberMeAuthenticationToken extends AuthenticationToken {
* across sessions, {@code false} otherwise.
*
* @return {@code true} if the submitting user wishes their identity (principal(s)) to be remembered
- * across sessions, {@code false} otherwise.
+ * across sessions, {@code false} otherwise.
*/
boolean isRememberMe();
diff --git a/core/src/main/java/org/apache/shiro/authc/SaltedAuthenticationInfo.java b/core/src/main/java/org/apache/shiro/authc/SaltedAuthenticationInfo.java
index f490385c05..003f022645 100644
--- a/core/src/main/java/org/apache/shiro/authc/SaltedAuthenticationInfo.java
+++ b/core/src/main/java/org/apache/shiro/authc/SaltedAuthenticationInfo.java
@@ -1,48 +1,47 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.shiro.authc;
-
-import org.apache.shiro.lang.util.ByteSource;
-
-/**
- * Interface representing account information that may use a salt when hashing credentials. This interface
- * exists primarily to support environments that hash user credentials (e.g. passwords).
- *
- * Salts should typically be generated from a secure pseudo-random number generator so they are effectively
- * impossible to guess. The salt value should be safely stored along side the account information to ensure
- * it is maintained along with the account's credentials.
- *
- * This interface exists as a way for Shiro to acquire that salt so it can correctly perform
- * {@link org.apache.shiro.authc.credential.CredentialsMatcher credentials matching} during login attempts.
- * See the {@link org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher} JavaDoc for
- * more information on hashing credentials with salts.
- *
- * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher
- *
- * @since 1.1
- */
-public interface SaltedAuthenticationInfo extends AuthenticationInfo {
-
- /**
- * Returns the salt used to salt the account's credentials or {@code null} if no salt was used.
- *
- * @return the salt used to salt the account's credentials or {@code null} if no salt was used.
- */
- ByteSource getCredentialsSalt();
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.authc;
+
+import org.apache.shiro.lang.util.ByteSource;
+
+/**
+ * Interface representing account information that may use a salt when hashing credentials. This interface
+ * exists primarily to support environments that hash user credentials (e.g. passwords).
+ *
+ * Salts should typically be generated from a secure pseudo-random number generator so they are effectively
+ * impossible to guess. The salt value should be safely stored along side the account information to ensure
+ * it is maintained along with the account's credentials.
+ *
+ * This interface exists as a way for Shiro to acquire that salt so it can correctly perform
+ * {@link org.apache.shiro.authc.credential.CredentialsMatcher credentials matching} during login attempts.
+ * See the {@link org.apache.shiro.authc.credential.HashedCredentialsMatcher HashedCredentialsMatcher} JavaDoc for
+ * more information on hashing credentials with salts.
+ *
+ * @see org.apache.shiro.authc.credential.HashedCredentialsMatcher
+ * @since 1.1
+ */
+public interface SaltedAuthenticationInfo extends AuthenticationInfo {
+
+ /**
+ * Returns the salt used to salt the account's credentials or {@code null} if no salt was used.
+ *
+ * @return the salt used to salt the account's credentials or {@code null} if no salt was used.
+ */
+ ByteSource getCredentialsSalt();
+}
diff --git a/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java b/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java
index e65e07c87f..d173ebd73b 100644
--- a/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java
+++ b/core/src/main/java/org/apache/shiro/authc/SimpleAccount.java
@@ -81,7 +81,8 @@ public SimpleAccount() {
* @param realmName the name of the realm that accesses this account data
*/
public SimpleAccount(Object principal, Object credentials, String realmName) {
- this(principal instanceof PrincipalCollection ? (PrincipalCollection) principal : new SimplePrincipalCollection(principal, realmName), credentials);
+ this(principal instanceof PrincipalCollection
+ ? (PrincipalCollection) principal : new SimplePrincipalCollection(principal, realmName), credentials);
}
/**
@@ -96,7 +97,8 @@ public SimpleAccount(Object principal, Object credentials, String realmName) {
* @since 1.1
*/
public SimpleAccount(Object principal, Object hashedCredentials, ByteSource credentialsSalt, String realmName) {
- this(principal instanceof PrincipalCollection ? (PrincipalCollection) principal : new SimplePrincipalCollection(principal, realmName),
+ this(principal instanceof PrincipalCollection ? (PrincipalCollection) principal
+ : new SimplePrincipalCollection(principal, realmName),
hashedCredentials, credentialsSalt);
}
@@ -162,7 +164,8 @@ public SimpleAccount(PrincipalCollection principals, Object credentials, Set roleNames, Set permissions) {
+ public SimpleAccount(Object principal, Object credentials, String realmName,
+ Set roleNames, Set permissions) {
this.authcInfo = new SimpleAuthenticationInfo(new SimplePrincipalCollection(principal, realmName), credentials);
this.authzInfo = new SimpleAuthorizationInfo(roleNames);
this.authzInfo.setObjectPermissions(permissions);
@@ -179,7 +182,9 @@ public SimpleAccount(Object principal, Object credentials, String realmName, Set
* @param roleNames the names of the roles assigned to this account.
* @param permissions the permissions assigned to this account directly (not those assigned to any of the realms).
*/
- public SimpleAccount(Collection principals, Object credentials, String realmName, Set roleNames, Set permissions) {
+
+ public SimpleAccount(Collection principals, Object credentials, String realmName,
+ Set roleNames, Set permissions) {
this.authcInfo = new SimpleAuthenticationInfo(new SimplePrincipalCollection(principals, realmName), credentials);
this.authzInfo = new SimpleAuthorizationInfo(roleNames);
this.authzInfo.setObjectPermissions(permissions);
@@ -253,7 +258,7 @@ public void setCredentials(Object credentials) {
* was used or credentials were not hashed at all.
*
* @return the salt used to hash this Account's credentials (e.g. for password hashing), or {@code null} if no salt
- * was used or credentials were not hashed at all.
+ * was used or credentials were not hashed at all.
* @since 1.1
*/
public ByteSource getCredentialsSalt() {
@@ -467,7 +472,7 @@ public int hashCode() {
*
* @param o the object to test for equality.
* @return true if the specified object is also a {@link SimpleAccount SimpleAccount} and its
- * {@link #getPrincipals() principals} are equal to this object's principals, false otherwise.
+ * {@link #getPrincipals() principals} are equal to this object's principals, false otherwise.
*/
public boolean equals(Object o) {
if (o == this) {
@@ -491,4 +496,4 @@ public String toString() {
return getPrincipals() != null ? getPrincipals().toString() : "empty";
}
-}
\ No newline at end of file
+}
diff --git a/core/src/main/java/org/apache/shiro/authc/SimpleAuthenticationInfo.java b/core/src/main/java/org/apache/shiro/authc/SimpleAuthenticationInfo.java
index 8ab6ae9b3e..8cae62fbe2 100644
--- a/core/src/main/java/org/apache/shiro/authc/SimpleAuthenticationInfo.java
+++ b/core/src/main/java/org/apache/shiro/authc/SimpleAuthenticationInfo.java
@@ -165,7 +165,7 @@ public void setCredentials(Object credentials) {
* use for salts. Therefore it doesn't make sense to 'merge' salts in a multi-realm scenario.
*
* @return the salt used to hash the credentials, or {@code null} if no salt was used or credentials were not
- * hashed at all.
+ * hashed at all.
* @since 1.1
*/
@Override
@@ -196,7 +196,7 @@ public void setCredentialsSalt(ByteSource salt) {
* @param info the AuthenticationInfo to add into this instance.
*/
@Override
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({"unchecked", "checkstyle:NPathComplexity"})
public void merge(AuthenticationInfo info) {
if (info == null || info.getPrincipals() == null || info.getPrincipals().isEmpty()) {
return;
@@ -254,7 +254,7 @@ public void merge(AuthenticationInfo info) {
*
* @param o the object to compare for equality.
* @return true if the Object argument is an instanceof SimpleAuthenticationInfo and
- * its {@link #getPrincipals() principals} are equal to this instance's principals, false otherwise.
+ * its {@link #getPrincipals() principals} are equal to this instance's principals, false otherwise.
*/
@Override
public boolean equals(Object o) {
diff --git a/core/src/main/java/org/apache/shiro/authc/UsernamePasswordToken.java b/core/src/main/java/org/apache/shiro/authc/UsernamePasswordToken.java
index 23768f2166..21d76c56ec 100644
--- a/core/src/main/java/org/apache/shiro/authc/UsernamePasswordToken.java
+++ b/core/src/main/java/org/apache/shiro/authc/UsernamePasswordToken.java
@@ -65,7 +65,7 @@ public class UsernamePasswordToken implements HostAuthenticationToken, RememberM
* Whether or not 'rememberMe' should be enabled for the corresponding login attempt;
* default is false
*/
- private boolean rememberMe = false;
+ private boolean rememberMe;
/**
* The location from where the login attempt occurs, or null if not known or explicitly
@@ -279,7 +279,7 @@ public Object getCredentials() {
*
(Shiro's default Authenticator allows null hosts to support localhost and proxy server environments).
*
* @return the host from where the authentication attempt occurs, or null if it is unknown or
- * explicitly omitted.
+ * explicitly omitted.
* @since 1.0
*/
public String getHost() {
@@ -305,7 +305,7 @@ public void setHost(String host) {
* across sessions, false otherwise. Unless overridden, this value is false by default.
*
* @return true if the submitting user wishes their identity (principal(s)) to be remembered
- * across sessions, false otherwise (false by default).
+ * across sessions, false otherwise (false by default).
* @since 0.9
*/
public boolean isRememberMe() {
@@ -352,7 +352,7 @@ public void clear() {
* that might be widely viewable).
*
* @return the String representation of the UsernamePasswordToken, omitting
- * the password.
+ * the password.
*/
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/core/src/main/java/org/apache/shiro/authc/credential/AllowAllCredentialsMatcher.java b/core/src/main/java/org/apache/shiro/authc/credential/AllowAllCredentialsMatcher.java
index f16638fb2b..9984068570 100644
--- a/core/src/main/java/org/apache/shiro/authc/credential/AllowAllCredentialsMatcher.java
+++ b/core/src/main/java/org/apache/shiro/authc/credential/AllowAllCredentialsMatcher.java
@@ -33,8 +33,8 @@ public class AllowAllCredentialsMatcher implements CredentialsMatcher {
/**
* Returns truealways no matter what the method arguments are.
*
- * @param token the token submitted for authentication.
- * @param info the account being verified for access
+ * @param token the token submitted for authentication.
+ * @param info the account being verified for access
* @return truealways.
*/
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
diff --git a/core/src/main/java/org/apache/shiro/authc/credential/CredentialsMatcher.java b/core/src/main/java/org/apache/shiro/authc/credential/CredentialsMatcher.java
index 58b7514b83..89c9dd93c7 100644
--- a/core/src/main/java/org/apache/shiro/authc/credential/CredentialsMatcher.java
+++ b/core/src/main/java/org/apache/shiro/authc/credential/CredentialsMatcher.java
@@ -21,7 +21,6 @@
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
-
/**
* Interface implemented by classes that can determine if an AuthenticationToken's provided
* credentials matches a corresponding account's credentials stored in the system.
@@ -44,11 +43,11 @@ public interface CredentialsMatcher {
* Returns {@code true} if the provided token credentials match the stored account credentials,
* {@code false} otherwise.
*
- * @param token the {@code AuthenticationToken} submitted during the authentication attempt
- * @param info the {@code AuthenticationInfo} stored in the system.
+ * @param token the {@code AuthenticationToken} submitted during the authentication attempt
+ * @param info the {@code AuthenticationInfo} stored in the system.
* @return {@code true} if the provided token credentials match the stored account credentials,
- * {@code false} otherwise.
+ * {@code false} otherwise.
*/
boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info);
-}
\ No newline at end of file
+}
diff --git a/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java b/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java
index 25c0898a59..73fd341362 100644
--- a/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java
+++ b/core/src/main/java/org/apache/shiro/authc/credential/DefaultPasswordService.java
@@ -47,15 +47,21 @@
*/
public class DefaultPasswordService implements HashingPasswordService {
+ /**
+ * default hash algorithm.
+ */
public static final String DEFAULT_HASH_ALGORITHM = "argon2id";
- private static final Logger log = LoggerFactory.getLogger(DefaultPasswordService.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPasswordService.class);
private HashService hashService;
private HashFormat hashFormat;
private HashFormatFactory hashFormatFactory;
- private volatile boolean hashFormatWarned; //used to avoid excessive log noise
+ /**
+ * used to avoid excessive log noise
+ */
+ private volatile boolean hashFormatWarned;
/**
* Constructs a new PasswordService with a default hash service and the default
@@ -122,13 +128,13 @@ protected void checkHashFormatDurability() {
HashFormat format = this.hashFormat;
- if (!(format instanceof ParsableHashFormat) && log.isWarnEnabled()) {
- String msg = "The configured hashFormat instance [" + format.getClass().getName() + "] is not a " +
- ParsableHashFormat.class.getName() + " implementation. This is " +
- "required if you wish to support backwards compatibility for saved password checking (almost " +
- "always desirable). Without a " + ParsableHashFormat.class.getSimpleName() + " instance, " +
- "any hashService configuration changes will break previously hashed/saved passwords.";
- log.warn(msg);
+ if (!(format instanceof ParsableHashFormat) && LOGGER.isWarnEnabled()) {
+ String msg = "The configured hashFormat instance [" + format.getClass().getName() + "] is not a "
+ + ParsableHashFormat.class.getName() + " implementation. This is "
+ + "required if you wish to support backwards compatibility for saved password checking (almost "
+ + "always desirable). Without a " + ParsableHashFormat.class.getSimpleName() + " instance, "
+ + "any hashService configuration changes will break previously hashed/saved passwords.";
+ LOGGER.warn(msg);
this.hashFormatWarned = true;
}
}
diff --git a/core/src/main/java/org/apache/shiro/authc/credential/HashedCredentialsMatcher.java b/core/src/main/java/org/apache/shiro/authc/credential/HashedCredentialsMatcher.java
index 4e73810602..87c663079c 100644
--- a/core/src/main/java/org/apache/shiro/authc/credential/HashedCredentialsMatcher.java
+++ b/core/src/main/java/org/apache/shiro/authc/credential/HashedCredentialsMatcher.java
@@ -7,7 +7,7 @@
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
@@ -36,7 +36,7 @@
* before being compared to those in the {@code AuthenticationInfo} from the data store.
*
* Credential hashing is one of the most common security techniques when safeguarding a user's private credentials
- * (passwords, keys, etc). Most developers never want to store their users' credentials in plain form, viewable by
+ * (passwords, keys, etc.). Most developers never want to store their users' credentials in plain form, viewable by
* anyone, so they often hash the users' credentials before they are saved in the data store.
*
* This class (and its subclasses) function as follows:
@@ -55,7 +55,7 @@
* "Why add salt?" and 6 "Hardening against the attacker's attack").
Note: Will only get applied if no other scheme (e.g. "java:") is given.
@@ -101,7 +101,7 @@ public void setResourceRef(boolean resourceRef) {
}
/**
- * Return whether the lookup occurs in a J2EE container.
+ * Return whether the lookup occurs in a Jakarta EE container.
*/
public boolean isResourceRef() {
return this.resourceRef;
@@ -141,20 +141,19 @@ protected Object lookup(String jndiName, Class requiredType) throws NamingExcept
Object jndiObject;
try {
jndiObject = getJndiTemplate().lookup(convertedName, requiredType);
- }
- catch (NamingException ex) {
+ } catch (NamingException ex) {
if (!convertedName.equals(jndiName)) {
// Try fallback to originally specified name...
- if (log.isDebugEnabled()) {
- log.debug("Converted JNDI name [" + convertedName +
- "] not found - trying original name [" + jndiName + "]. " + ex);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Converted JNDI name [" + convertedName
+ + "] not found - trying original name [" + jndiName + "]. " + ex);
}
jndiObject = getJndiTemplate().lookup(jndiName, requiredType);
} else {
throw ex;
}
}
- log.debug("Located object with JNDI name '{}'", convertedName);
+ LOGGER.debug("Located object with JNDI name '{}'", convertedName);
return jndiObject;
}
diff --git a/core/src/main/java/org/apache/shiro/jndi/JndiObjectFactory.java b/core/src/main/java/org/apache/shiro/jndi/JndiObjectFactory.java
index a67bf30393..2fa72bb442 100644
--- a/core/src/main/java/org/apache/shiro/jndi/JndiObjectFactory.java
+++ b/core/src/main/java/org/apache/shiro/jndi/JndiObjectFactory.java
@@ -24,6 +24,7 @@
/**
* A factory implementation intended to be used to look up objects in jndi.
+ *
* @param
* @since 1.2
*/
@@ -34,7 +35,7 @@ public class JndiObjectFactory extends JndiLocator implements Factory {
public T getInstance() {
try {
- if(requiredType != null) {
+ if (requiredType != null) {
return requiredType.cast(this.lookup(resourceName, requiredType));
} else {
return (T) this.lookup(resourceName);
diff --git a/core/src/main/java/org/apache/shiro/jndi/JndiTemplate.java b/core/src/main/java/org/apache/shiro/jndi/JndiTemplate.java
index a9870518b1..4600a802f6 100644
--- a/core/src/main/java/org/apache/shiro/jndi/JndiTemplate.java
+++ b/core/src/main/java/org/apache/shiro/jndi/JndiTemplate.java
@@ -44,11 +44,13 @@
*/
public class JndiTemplate {
- private static final Logger log = LoggerFactory.getLogger(JndiTemplate.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(JndiTemplate.class);
private Properties environment;
- /** Create a new JndiTemplate instance. */
+ /**
+ * Create a new JndiTemplate instance.
+ */
public JndiTemplate() {
}
@@ -91,12 +93,11 @@ public Object execute(JndiCallback contextCallback) throws NamingException {
Context ctx = createInitialContext();
try {
return contextCallback.doInContext(ctx);
- }
- finally {
+ } finally {
try {
ctx.close();
} catch (NamingException ex) {
- log.debug("Could not close JNDI InitialContext", ex);
+ LOGGER.debug("Could not close JNDI InitialContext", ex);
}
}
}
@@ -115,7 +116,7 @@ protected Context createInitialContext() throws NamingException {
Hashtable icEnv = null;
if (env != null) {
icEnv = new Hashtable(env.size());
- for (Enumeration en = env.propertyNames(); en.hasMoreElements();) {
+ for (Enumeration en = env.propertyNames(); en.hasMoreElements(); ) {
String key = (String) en.nextElement();
icEnv.put(key, env.getProperty(key));
}
@@ -128,12 +129,12 @@ protected Context createInitialContext() throws NamingException {
*
* @param name the JNDI name of the object
* @return object found (cannot be null; if a not so well-behaved
- * JNDI implementations returns null, a NamingException gets thrown)
+ * JNDI implementations returns null, a NamingException gets thrown)
* @throws NamingException if there is no object with the given
* name bound to JNDI
*/
public Object lookup(final String name) throws NamingException {
- log.debug("Looking up JNDI object with name '{}'", name);
+ LOGGER.debug("Looking up JNDI object with name '{}'", name);
return execute(new JndiCallback() {
public Object doInContext(Context ctx) throws NamingException {
Object located = ctx.lookup(name);
@@ -155,16 +156,16 @@ public Object doInContext(Context ctx) throws NamingException {
* if the value is Object.class, this method will succeed whatever
* the class of the returned instance.
* @return object found (cannot be null; if a not so well-behaved
- * JNDI implementations returns null, a NamingException gets thrown)
+ * JNDI implementations returns null, a NamingException gets thrown)
* @throws NamingException if there is no object with the given
* name bound to JNDI
*/
public Object lookup(String name, Class requiredType) throws NamingException {
Object jndiObject = lookup(name);
if (requiredType != null && !requiredType.isInstance(jndiObject)) {
- String msg = "Jndi object acquired under name '" + name + "' is of type [" +
- jndiObject.getClass().getName() + "] and not assignable to the required type [" +
- requiredType.getName() + "].";
+ String msg = "Jndi object acquired under name '" + name + "' is of type ["
+ + jndiObject.getClass().getName() + "] and not assignable to the required type ["
+ + requiredType.getName() + "].";
throw new NamingException(msg);
}
return jndiObject;
@@ -178,7 +179,7 @@ public Object lookup(String name, Class requiredType) throws NamingException {
* @throws NamingException thrown by JNDI, mostly name already bound
*/
public void bind(final String name, final Object object) throws NamingException {
- log.debug("Binding JNDI object with name '{}'", name);
+ LOGGER.debug("Binding JNDI object with name '{}'", name);
execute(new JndiCallback() {
public Object doInContext(Context ctx) throws NamingException {
ctx.bind(name, object);
@@ -196,7 +197,7 @@ public Object doInContext(Context ctx) throws NamingException {
* @throws NamingException thrown by JNDI
*/
public void rebind(final String name, final Object object) throws NamingException {
- log.debug("Rebinding JNDI object with name '{}'", name);
+ LOGGER.debug("Rebinding JNDI object with name '{}'", name);
execute(new JndiCallback() {
public Object doInContext(Context ctx) throws NamingException {
ctx.rebind(name, object);
@@ -212,7 +213,7 @@ public Object doInContext(Context ctx) throws NamingException {
* @throws NamingException thrown by JNDI, mostly name not found
*/
public void unbind(final String name) throws NamingException {
- log.debug("Unbinding JNDI object with name '{}'", name);
+ LOGGER.debug("Unbinding JNDI object with name '{}'", name);
execute(new JndiCallback() {
public Object doInContext(Context ctx) throws NamingException {
ctx.unbind(name);
diff --git a/core/src/main/java/org/apache/shiro/ldap/package-info.java b/core/src/main/java/org/apache/shiro/ldap/package-info.java
index 48ccc3b6c5..bef3f3780d 100644
--- a/core/src/main/java/org/apache/shiro/ldap/package-info.java
+++ b/core/src/main/java/org/apache/shiro/ldap/package-info.java
@@ -17,10 +17,9 @@
* under the License.
*/
-package org.apache.shiro.ldap;
-
/**
* Support for accessing LDAP data sources.
*
* @since 1.2
- */
\ No newline at end of file
+ */
+package org.apache.shiro.ldap;
diff --git a/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java b/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java
index 0d1b13d58d..c67ee8bbc1 100644
--- a/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java
+++ b/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java
@@ -18,13 +18,12 @@
*/
package org.apache.shiro.mgt;
-import java.util.function.Supplier;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.RememberMeAuthenticationToken;
-import org.apache.shiro.crypto.cipher.ByteSourceBroker;
import org.apache.shiro.crypto.cipher.AesCipherService;
+import org.apache.shiro.crypto.cipher.ByteSourceBroker;
import org.apache.shiro.crypto.cipher.CipherService;
import org.apache.shiro.lang.io.DefaultSerializer;
import org.apache.shiro.lang.io.Serializer;
@@ -36,6 +35,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.function.Supplier;
+
/**
* Abstract implementation of the {@code RememberMeManager} interface that handles
* {@link #setSerializer(Serializer) serialization} and
@@ -68,7 +69,7 @@ public abstract class AbstractRememberMeManager implements RememberMeManager {
/**
* private inner log instance.
*/
- private static final Logger log = LoggerFactory.getLogger(AbstractRememberMeManager.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRememberMeManager.class);
/**
* Serializer to use for converting PrincipalCollection instances to/from byte arrays
@@ -78,7 +79,8 @@ public abstract class AbstractRememberMeManager implements RememberMeManager {
/**
* Cipher to use for encrypting/decrypting serialized byte arrays for added security
*/
- private CipherService cipherService = new AesCipherService();;
+ private CipherService cipherService = new AesCipherService();
+ ;
/**
* Cipher encryption key to use with the Cipher when encrypting data
@@ -117,7 +119,7 @@ public AbstractRememberMeManager(Supplier keySupplier) {
* {@link org.apache.shiro.lang.io.DefaultSerializer}.
*
* @return the {@code Serializer} used to serialize and deserialize {@link PrincipalCollection} instances for
- * persistent remember me storage.
+ * persistent remember me storage.
*/
public Serializer getSerializer() {
return serializer;
@@ -143,7 +145,7 @@ public void setSerializer(Serializer serializer) {
* Unless overridden by the {@link #setCipherService} method, the default instance is an {@link AesCipherService}.
*
* @return the {@code Cipher} to use for encrypting and decrypting serialized identity data to prevent easy
- * inspection of Subject identity data
+ * inspection of Subject identity data
*/
public CipherService getCipherService() {
return cipherService;
@@ -273,15 +275,15 @@ public void setCipherKey(byte[] cipherKey) {
* @return true if remember me services should be performed as a result of the successful authentication attempt.
*/
protected boolean isRememberMe(AuthenticationToken token) {
- return token != null && (token instanceof RememberMeAuthenticationToken) &&
- ((RememberMeAuthenticationToken) token).isRememberMe();
+ return token instanceof RememberMeAuthenticationToken && ((RememberMeAuthenticationToken) token).isRememberMe();
}
/**
* Reacts to the successful login attempt by first always {@link #forgetIdentity(Subject) forgetting} any previously
* stored identity. Then if the {@code token}
* {@link #isRememberMe(org.apache.shiro.authc.AuthenticationToken) is a RememberMe} token, the associated identity
- * will be {@link #rememberIdentity(org.apache.shiro.subject.Subject, org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.authc.AuthenticationInfo) remembered}
+ * will be {@link #rememberIdentity(org.apache.shiro.subject.Subject, org.apache.shiro.authc.AuthenticationToken,
+ * org.apache.shiro.authc.AuthenticationInfo) remembered}
* for later retrieval during a new user session.
*
* @param subject the subject for which the principals are being remembered.
@@ -296,9 +298,9 @@ public void onSuccessfulLogin(Subject subject, AuthenticationToken token, Authen
if (isRememberMe(token)) {
rememberIdentity(subject, token, info);
} else {
- if (log.isDebugEnabled()) {
- log.debug("AuthenticationToken did not indicate RememberMe is requested. " +
- "RememberMe functionality will not be executed for corresponding account.");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("AuthenticationToken did not indicate RememberMe is requested. "
+ + "RememberMe functionality will not be executed for corresponding account.");
}
}
}
@@ -414,7 +416,7 @@ public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext
* is being used to construct a {@link Subject} instance. To be used to assist with data
* lookup.
* @return the previously persisted serialized identity, or {@code null} if there is no available data for the
- * Subject.
+ * Subject.
*/
protected abstract byte[] getRememberedSerializedIdentity(SubjectContext subjectContext);
@@ -453,13 +455,14 @@ protected PrincipalCollection convertBytesToPrincipals(byte[] bytes, SubjectCont
*/
protected PrincipalCollection onRememberedPrincipalFailure(RuntimeException e, SubjectContext context) {
- if (log.isWarnEnabled()) {
- String message = "There was a failure while trying to retrieve remembered principals. This could be due to a " +
- "configuration problem or corrupted principals. This could also be due to a recently " +
- "changed encryption key, if you are using a shiro.ini file, this property would be " +
- "'securityManager.rememberMeManager.cipherKey' see: http://shiro.apache.org/web.html#Web-RememberMeServices. " +
- "The remembered identity will be forgotten and not used for this request.";
- log.warn(message);
+ if (LOGGER.isWarnEnabled()) {
+ String message = "There was a failure while trying to retrieve remembered principals. This could be due to a "
+ + "configuration problem or corrupted principals. This could also be due to a recently "
+ + "changed encryption key, if you are using a shiro.ini file, this property would be "
+ + "'securityManager.rememberMeManager.cipherKey'"
+ + "see: http://shiro.apache.org/web.html#Web-RememberMeServices. "
+ + "The remembered identity will be forgotten and not used for this request.";
+ LOGGER.warn(message);
}
forgetIdentity(context);
//propagate - security manager implementation will handle and warn appropriately
diff --git a/core/src/main/java/org/apache/shiro/mgt/AuthenticatingSecurityManager.java b/core/src/main/java/org/apache/shiro/mgt/AuthenticatingSecurityManager.java
index c1a7cdb535..a455e0898d 100644
--- a/core/src/main/java/org/apache/shiro/mgt/AuthenticatingSecurityManager.java
+++ b/core/src/main/java/org/apache/shiro/mgt/AuthenticatingSecurityManager.java
@@ -65,7 +65,7 @@ public AuthenticatingSecurityManager() {
* {@link org.apache.shiro.authc.pam.ModularRealmAuthenticator ModularRealmAuthenticator}.
*
* @return the delegate Authenticator instance that this SecurityManager uses to perform all
- * authentication operations.
+ * authentication operations.
*/
public Authenticator getAuthenticator() {
return authenticator;
diff --git a/core/src/main/java/org/apache/shiro/mgt/AuthorizingSecurityManager.java b/core/src/main/java/org/apache/shiro/mgt/AuthorizingSecurityManager.java
index e2555d8bf9..0cbea9dc02 100644
--- a/core/src/main/java/org/apache/shiro/mgt/AuthorizingSecurityManager.java
+++ b/core/src/main/java/org/apache/shiro/mgt/AuthorizingSecurityManager.java
@@ -145,7 +145,8 @@ public void checkPermissions(PrincipalCollection principals, String... permissio
this.authorizer.checkPermissions(principals, permissions);
}
- public void checkPermissions(PrincipalCollection principals, Collection permissions) throws AuthorizationException {
+ public void checkPermissions(PrincipalCollection principals, Collection permissions)
+ throws AuthorizationException {
this.authorizer.checkPermissions(principals, permissions);
}
@@ -168,8 +169,9 @@ public void checkRole(PrincipalCollection principals, String role) throws Author
public void checkRoles(PrincipalCollection principals, Collection roles) throws AuthorizationException {
this.authorizer.checkRoles(principals, roles);
}
-
+
public void checkRoles(PrincipalCollection principals, String... roles) throws AuthorizationException {
this.authorizer.checkRoles(principals, roles);
- }
+ }
+
}
diff --git a/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java b/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java
index 80219d4c68..d83f971fc8 100644
--- a/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java
+++ b/core/src/main/java/org/apache/shiro/mgt/CachingSecurityManager.java
@@ -46,6 +46,7 @@ public abstract class CachingSecurityManager implements SecurityManager, Destroy
/**
* The EventBus to use to use to publish and receive events of interest during Shiro's lifecycle.
+ *
* @since 1.3
*/
private EventBus eventBus;
@@ -111,7 +112,7 @@ public EventBus getEventBus() {
* eventBus is available.
*
* @param eventBus the EventBus used by this {@code SecurityManager} and potentially any of its
- * children components.
+ * children components.
* @since 1.3
*/
public void setEventBus(EventBus eventBus) {
@@ -124,7 +125,7 @@ public void setEventBus(EventBus eventBus) {
*/
protected void applyEventBusToCacheManager() {
if (this.eventBus != null && this.cacheManager != null && this.cacheManager instanceof EventBusAware) {
- ((EventBusAware)this.cacheManager).setEventBus(this.eventBus);
+ ((EventBusAware) this.cacheManager).setEventBus(this.eventBus);
}
}
diff --git a/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java b/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
index 9c59218fd7..9912f6ab14 100644
--- a/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
+++ b/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
@@ -72,9 +72,10 @@
*
* @since 0.2
*/
+@SuppressWarnings("checkstyle:MethodCount")
public class DefaultSecurityManager extends SessionsSecurityManager {
- private static final Logger log = LoggerFactory.getLogger(DefaultSecurityManager.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSecurityManager.class);
protected RememberMeManager rememberMeManager;
protected SubjectDAO subjectDAO;
@@ -121,7 +122,8 @@ public SubjectFactory getSubjectFactory() {
/**
* Sets the {@code SubjectFactory} responsible for creating {@link Subject} instances exposed to the application.
*
- * @param subjectFactory the {@code SubjectFactory} responsible for creating {@link Subject} instances exposed to the application.
+ * @param subjectFactory the {@code SubjectFactory} responsible for creating
+ * {@link Subject} instances exposed to the application.
*/
public void setSubjectFactory(SubjectFactory subjectFactory) {
this.subjectFactory = subjectFactory;
@@ -133,7 +135,7 @@ public void setSubjectFactory(SubjectFactory subjectFactory) {
* implementation is a {@link DefaultSubjectDAO}.
*
* @return the {@code SubjectDAO} responsible for persisting Subject state, typically used after login or when an
- * Subject identity is discovered (e.g. after RememberMe services).
+ * Subject identity is discovered (e.g. after RememberMe services).
* @see DefaultSubjectDAO
* @since 1.2
*/
@@ -174,7 +176,7 @@ protected SubjectContext createSubjectContext() {
* @param info the {@code AuthenticationInfo} of a newly authenticated user.
* @param existing the existing {@code Subject} instance that initiated the authentication attempt
* @return the {@code Subject} instance that represents the context and session data for the newly
- * authenticated subject.
+ * authenticated subject.
*/
protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing) {
SubjectContext context = createSubjectContext();
@@ -210,18 +212,18 @@ protected void rememberMeSuccessfulLogin(AuthenticationToken token, Authenticati
try {
rmm.onSuccessfulLogin(subject, token, info);
} catch (Exception e) {
- if (log.isWarnEnabled()) {
- String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +
- "] threw an exception during onSuccessfulLogin. RememberMe services will not be " +
- "performed for account [" + info + "].";
- log.warn(msg, e);
+ if (LOGGER.isWarnEnabled()) {
+ String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName()
+ + "] threw an exception during onSuccessfulLogin. RememberMe services will not be "
+ + "performed for account [" + info + "].";
+ LOGGER.warn(msg, e);
}
}
} else {
- if (log.isTraceEnabled()) {
- log.trace("This " + getClass().getName() + " instance does not have a " +
- "[" + RememberMeManager.class.getName() + "] instance configured. RememberMe services " +
- "will not be performed for account [" + info + "].");
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("This " + getClass().getName() + " instance does not have a "
+ + "[" + RememberMeManager.class.getName() + "] instance configured. RememberMe services "
+ + "will not be performed for account [" + info + "].");
}
}
}
@@ -232,11 +234,11 @@ protected void rememberMeFailedLogin(AuthenticationToken token, AuthenticationEx
try {
rmm.onFailedLogin(subject, token, ex);
} catch (Exception e) {
- if (log.isWarnEnabled()) {
- String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +
- "] threw an exception during onFailedLogin for AuthenticationToken [" +
- token + "].";
- log.warn(msg, e);
+ if (LOGGER.isWarnEnabled()) {
+ String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName()
+ + "] threw an exception during onFailedLogin for AuthenticationToken ["
+ + token + "].";
+ LOGGER.warn(msg, e);
}
}
}
@@ -248,11 +250,11 @@ protected void rememberMeLogout(Subject subject) {
try {
rmm.onLogout(subject);
} catch (Exception e) {
- if (log.isWarnEnabled()) {
- String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +
- "] threw an exception during onLogout for subject with principals [" +
- (subject != null ? subject.getPrincipals() : null) + "]";
- log.warn(msg, e);
+ if (LOGGER.isWarnEnabled()) {
+ String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName()
+ + "] threw an exception during onLogout for subject with principals ["
+ + (subject != null ? subject.getPrincipals() : null) + "]";
+ LOGGER.warn(msg, e);
}
}
}
@@ -277,12 +279,13 @@ public Subject login(Subject subject, AuthenticationToken token) throws Authenti
try {
onFailedLogin(token, ae, subject);
} catch (Exception e) {
- if (log.isInfoEnabled()) {
- log.info("onFailedLogin method threw an " +
- "exception. Logging and propagating original AuthenticationException.", e);
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("onFailedLogin method threw an "
+ + "exception. Logging and propagating original AuthenticationException.", e);
}
}
- throw ae; //propagate
+ //propagate
+ throw ae;
}
Subject loggedIn = createSubject(token, info, subject);
@@ -414,10 +417,10 @@ protected void delete(Subject subject) {
@SuppressWarnings({"unchecked"})
protected SubjectContext ensureSecurityManager(SubjectContext context) {
if (context.resolveSecurityManager() != null) {
- log.trace("Context already contains a SecurityManager instance. Returning.");
+ LOGGER.trace("Context already contains a SecurityManager instance. Returning.");
return context;
}
- log.trace("No SecurityManager found in context. Adding self reference.");
+ LOGGER.trace("No SecurityManager found in context. Adding self reference.");
context.setSecurityManager(this);
return context;
}
@@ -438,19 +441,19 @@ protected SubjectContext ensureSecurityManager(SubjectContext context) {
@SuppressWarnings({"unchecked"})
protected SubjectContext resolveSession(SubjectContext context) {
if (context.resolveSession() != null) {
- log.debug("Context already contains a session. Returning.");
+ LOGGER.debug("Context already contains a session. Returning.");
return context;
}
try {
- //Context couldn't resolve it directly, let's see if we can since we have direct access to
+ //Context couldn't resolve it directly, let's see if we can since we have direct access to
//the session manager:
Session session = resolveContextSession(context);
if (session != null) {
context.setSession(session);
}
} catch (InvalidSessionException e) {
- log.debug("Resolved SubjectContext context session is invalid. Ignoring and creating an anonymous " +
- "(session-less) Subject instance.", e);
+ LOGGER.debug("Resolved SubjectContext context session is invalid. Ignoring and creating an anonymous "
+ + "(session-less) Subject instance.", e);
}
return context;
}
@@ -496,13 +499,13 @@ protected SubjectContext resolvePrincipals(SubjectContext context) {
PrincipalCollection principals = context.resolvePrincipals();
if (isEmpty(principals)) {
- log.trace("No identity (PrincipalCollection) found in the context. Looking for a remembered identity.");
+ LOGGER.trace("No identity (PrincipalCollection) found in the context. Looking for a remembered identity.");
principals = getRememberedIdentity(context);
if (!isEmpty(principals)) {
- log.debug("Found remembered PrincipalCollection. Adding to the context to be used " +
- "for subject construction by the SubjectFactory.");
+ LOGGER.debug("Found remembered PrincipalCollection. Adding to the context to be used "
+ + "for subject construction by the SubjectFactory.");
context.setPrincipals(principals);
@@ -522,7 +525,7 @@ protected SubjectContext resolvePrincipals(SubjectContext context) {
// bindPrincipalsToSession(principals, context);
} else {
- log.trace("No remembered identity found. Returning original context.");
+ LOGGER.trace("No remembered identity found. Returning original context.");
}
}
@@ -555,8 +558,8 @@ public void logout(Subject subject) {
PrincipalCollection principals = subject.getPrincipals();
if (principals != null && !principals.isEmpty()) {
- if (log.isDebugEnabled()) {
- log.debug("Logging out subject with primary principal {}", principals.getPrimaryPrincipal());
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Logging out subject with primary principal {}", principals.getPrimaryPrincipal());
}
Authenticator authc = getAuthenticator();
if (authc instanceof LogoutAware) {
@@ -567,18 +570,18 @@ public void logout(Subject subject) {
try {
delete(subject);
} catch (Exception e) {
- if (log.isDebugEnabled()) {
+ if (LOGGER.isDebugEnabled()) {
String msg = "Unable to cleanly unbind Subject. Ignoring (logging out).";
- log.debug(msg, e);
+ LOGGER.debug(msg, e);
}
} finally {
try {
stopSession(subject);
} catch (Exception e) {
- if (log.isDebugEnabled()) {
- String msg = "Unable to cleanly stop Session for Subject [" + subject.getPrincipal() + "] " +
- "Ignoring (logging out).";
- log.debug(msg, e);
+ if (LOGGER.isDebugEnabled()) {
+ String msg = "Unable to cleanly stop Session for Subject [" + subject.getPrincipal() + "] "
+ + "Ignoring (logging out).";
+ LOGGER.debug(msg, e);
}
}
}
@@ -612,10 +615,10 @@ protected PrincipalCollection getRememberedIdentity(SubjectContext subjectContex
try {
return rmm.getRememberedPrincipals(subjectContext);
} catch (Exception e) {
- if (log.isWarnEnabled()) {
- String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName() +
- "] threw an exception during getRememberedPrincipals().";
- log.warn(msg, e);
+ if (LOGGER.isWarnEnabled()) {
+ String msg = "Delegate RememberMeManager instance of type [" + rmm.getClass().getName()
+ + "] threw an exception during getRememberedPrincipals().";
+ LOGGER.warn(msg, e);
}
}
}
diff --git a/core/src/main/java/org/apache/shiro/mgt/DefaultSessionStorageEvaluator.java b/core/src/main/java/org/apache/shiro/mgt/DefaultSessionStorageEvaluator.java
index b720ac6cdf..b36080e96b 100644
--- a/core/src/main/java/org/apache/shiro/mgt/DefaultSessionStorageEvaluator.java
+++ b/core/src/main/java/org/apache/shiro/mgt/DefaultSessionStorageEvaluator.java
@@ -73,7 +73,7 @@ public boolean isSessionStorageEnabled(Subject subject) {
* authenticate on every request).
*
* @return {@code true} if any Subject's {@code Session} may be used to persist that {@code Subject}'s state,
- * {@code false} otherwise.
+ * {@code false} otherwise.
*/
public boolean isSessionStorageEnabled() {
return sessionStorageEnabled;
diff --git a/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectDAO.java b/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectDAO.java
index 06b4e463ab..354517369b 100644
--- a/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectDAO.java
+++ b/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectDAO.java
@@ -80,7 +80,7 @@
*/
public class DefaultSubjectDAO implements SubjectDAO {
- private static final Logger log = LoggerFactory.getLogger(DefaultSubjectDAO.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSubjectDAO.class);
/**
* Evaluator that determines if a Subject's session may be used to store the Subject's own state.
@@ -112,7 +112,7 @@ protected boolean isSessionStorageEnabled(Subject subject) {
* the Subject's session. The default instance is a {@link DefaultSessionStorageEvaluator}.
*
* @return the {@code SessionStorageEvaluator} that will determine if a {@code Subject}'s state may be persisted in
- * the Subject's session.
+ * the Subject's session.
* @see DefaultSessionStorageEvaluator
*/
public SessionStorageEvaluator getSessionStorageEvaluator() {
@@ -145,8 +145,8 @@ public Subject save(Subject subject) {
if (isSessionStorageEnabled(subject)) {
saveToSession(subject);
} else {
- log.trace("Session storage of subject state for Subject [{}] has been disabled: identity and " +
- "authentication state are expected to be initialized on every request or invocation.", subject);
+ LOGGER.trace("Session storage of subject state for Subject [{}] has been disabled: identity and "
+ + "authentication state are expected to be initialized on every request or invocation.", subject);
}
return subject;
@@ -191,7 +191,7 @@ protected void mergePrincipals(Subject subject) {
try {
Field field = DelegatingSubject.class.getDeclaredField("principals");
field.setAccessible(true);
- currentPrincipals = (PrincipalCollection)field.get(subject);
+ currentPrincipals = (PrincipalCollection) field.get(subject);
} catch (Exception e) {
throw new IllegalStateException("Unable to access DelegatingSubject principals property.", e);
}
diff --git a/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java b/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java
index 7e41abbcdf..618a44146b 100644
--- a/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java
+++ b/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java
@@ -26,7 +26,8 @@
/**
- * Default {@link SubjectFactory SubjectFactory} implementation that creates {@link org.apache.shiro.subject.support.DelegatingSubject DelegatingSubject}
+ * Default {@link SubjectFactory SubjectFactory} implementation that creates
+ * {@link org.apache.shiro.subject.support.DelegatingSubject DelegatingSubject}
* instances.
*
* @since 1.0
@@ -49,7 +50,7 @@ public Subject createSubject(SubjectContext context) {
/**
* @deprecated since 1.2 - override {@link #createSubject(org.apache.shiro.subject.SubjectContext)} directly if you
- * need to instantiate a custom {@link Subject} class.
+ * need to instantiate a custom {@link Subject} class.
*/
@Deprecated
protected Subject newSubjectInstance(PrincipalCollection principals, boolean authenticated, String host,
diff --git a/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java b/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java
index aaca9d8b22..748ddd169a 100644
--- a/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java
+++ b/core/src/main/java/org/apache/shiro/mgt/RealmSecurityManager.java
@@ -139,9 +139,9 @@ protected void applyEventBusToRealms() {
EventBus eventBus = getEventBus();
Collection realms = getRealms();
if (eventBus != null && realms != null && !realms.isEmpty()) {
- for(Realm realm : realms) {
+ for (Realm realm : realms) {
if (realm instanceof EventBusAware) {
- ((EventBusAware)realm).setEventBus(eventBus);
+ ((EventBusAware) realm).setEventBus(eventBus);
}
}
}
@@ -149,8 +149,8 @@ protected void applyEventBusToRealms() {
/**
* Simply calls {@link #applyCacheManagerToRealms() applyCacheManagerToRealms()} to allow the
- * newly set {@link org.apache.shiro.cache.CacheManager CacheManager} to be propagated to the internal collection of Realm
- * that would need to use it.
+ * newly set {@link org.apache.shiro.cache.CacheManager CacheManager} to be propagated to the
+ * internal collection of Realm that would need to use it.
*/
protected void afterCacheManagerSet() {
super.afterCacheManagerSet();
diff --git a/core/src/main/java/org/apache/shiro/mgt/SessionStorageEvaluator.java b/core/src/main/java/org/apache/shiro/mgt/SessionStorageEvaluator.java
index ebdd9dfed6..8a062b213f 100644
--- a/core/src/main/java/org/apache/shiro/mgt/SessionStorageEvaluator.java
+++ b/core/src/main/java/org/apache/shiro/mgt/SessionStorageEvaluator.java
@@ -54,8 +54,8 @@ public interface SessionStorageEvaluator {
*
* @param subject the {@code Subject} for which session state persistence may be enabled
* @return {@code true} if the specified {@code Subject}'s
- * {@link org.apache.shiro.subject.Subject#getSession() session} may be used to persist that Subject's
- * state, {@code false} otherwise.
+ * {@link org.apache.shiro.subject.Subject#getSession() session} may be used to persist that Subject's
+ * state, {@code false} otherwise.
* @see Subject#getSession()
* @see Subject#getSession(boolean)
*/
diff --git a/core/src/main/java/org/apache/shiro/mgt/SessionsSecurityManager.java b/core/src/main/java/org/apache/shiro/mgt/SessionsSecurityManager.java
index abe60ece28..e2180888e8 100644
--- a/core/src/main/java/org/apache/shiro/mgt/SessionsSecurityManager.java
+++ b/core/src/main/java/org/apache/shiro/mgt/SessionsSecurityManager.java
@@ -98,9 +98,9 @@ public SessionManager getSessionManager() {
}
/**
- * Calls {@link org.apache.shiro.mgt.AuthorizingSecurityManager#afterCacheManagerSet() super.afterCacheManagerSet()} and then immediately calls
- * {@link #applyCacheManagerToSessionManager() applyCacheManagerToSessionManager()} to ensure the
- * CacheManager is applied to the SessionManager as necessary.
+ * Calls {@link org.apache.shiro.mgt.AuthorizingSecurityManager#afterCacheManagerSet() super.afterCacheManagerSet()}
+ * and then immediately calls {@link #applyCacheManagerToSessionManager() applyCacheManagerToSessionManager()}
+ * to ensure the CacheManager is applied to the SessionManager as necessary.
*/
@Override
protected void afterCacheManagerSet() {
@@ -144,7 +144,7 @@ protected void applyCacheManagerToSessionManager() {
protected void applyEventBusToSessionManager() {
EventBus eventBus = getEventBus();
if (eventBus != null && this.sessionManager instanceof EventBusAware) {
- ((EventBusAware)this.sessionManager).setEventBus(eventBus);
+ ((EventBusAware) this.sessionManager).setEventBus(eventBus);
}
}
diff --git a/core/src/main/java/org/apache/shiro/realm/AuthenticatingRealm.java b/core/src/main/java/org/apache/shiro/realm/AuthenticatingRealm.java
index 54d3963a1d..58ea1e9652 100644
--- a/core/src/main/java/org/apache/shiro/realm/AuthenticatingRealm.java
+++ b/core/src/main/java/org/apache/shiro/realm/AuthenticatingRealm.java
@@ -112,9 +112,7 @@
*/
public abstract class AuthenticatingRealm extends CachingRealm implements Initializable {
- //TODO - complete JavaDoc
-
- private static final Logger log = LoggerFactory.getLogger(AuthenticatingRealm.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticatingRealm.class);
private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
@@ -191,7 +189,7 @@ public AuthenticatingRealm(CacheManager cacheManager, CredentialsMatcher matcher
* value is a {@link org.apache.shiro.authc.credential.SimpleCredentialsMatcher SimpleCredentialsMatcher} instance.
*
* @return the CredentialsMatcher used during an authentication attempt to verify submitted
- * credentials with those stored in the system.
+ * credentials with those stored in the system.
*/
public CredentialsMatcher getCredentialsMatcher() {
return credentialsMatcher;
@@ -264,7 +262,7 @@ public void setAuthenticationCache(Cache
*
* Permissions are only retrieved if you set {@link #permissionsLookupEnabled} to true. Otherwise,
* this query is ignored.
@@ -191,10 +190,10 @@ public void setPermissionsQuery(String permissionsQuery) {
public void setPermissionsLookupEnabled(boolean permissionsLookupEnabled) {
this.permissionsLookupEnabled = permissionsLookupEnabled;
}
-
+
/**
* Sets the salt style. See {@link #saltStyle}.
- *
+ *
* @param saltStyle new SaltStyle to set.
*/
public void setSaltStyle(SaltStyle saltStyle) {
@@ -237,21 +236,23 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
String password = null;
String salt = null;
switch (saltStyle) {
- case NO_SALT:
- password = getPasswordForUser(conn, username)[0];
- break;
- case CRYPT:
- // TODO: separate password and hash from getPasswordForUser[0]
- throw new ConfigurationException("Not implemented yet");
- //break;
- case COLUMN:
- String[] queryResults = getPasswordForUser(conn, username);
- password = queryResults[0];
- salt = queryResults[1];
- break;
- case EXTERNAL:
- password = getPasswordForUser(conn, username)[0];
- salt = getSaltForUser(username);
+ case NO_SALT:
+ password = getPasswordForUser(conn, username)[0];
+ break;
+ case CRYPT:
+ // TODO: separate password and hash from getPasswordForUser[0]
+ throw new ConfigurationException("Not implemented yet");
+ //break;
+ case COLUMN:
+ String[] queryResults = getPasswordForUser(conn, username);
+ password = queryResults[0];
+ salt = queryResults[1];
+ break;
+ case EXTERNAL:
+ password = getPasswordForUser(conn, username)[0];
+ salt = getSaltForUser(username);
+ break;
+ default:
}
if (password == null) {
@@ -259,19 +260,19 @@ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
}
info = new SimpleAuthenticationInfo(username, password.toCharArray(), getName());
-
+
if (salt != null) {
- if (saltStyle == SaltStyle.COLUMN && saltIsBase64Encoded) {
+ if (saltStyle == SaltStyle.COLUMN && saltIsBase64Encoded) {
info.setCredentialsSalt(ByteSource.Util.bytes(Base64.decode(salt)));
- } else {
+ } else {
info.setCredentialsSalt(ByteSource.Util.bytes(salt));
- }
+ }
}
} catch (SQLException e) {
final String message = "There was a SQL error while authenticating user [" + username + "]";
- if (log.isErrorEnabled()) {
- log.error(message, e);
+ if (LOGGER.isErrorEnabled()) {
+ LOGGER.error(message, e);
}
// Rethrow any SQL errors as an authentication exception
@@ -288,16 +289,16 @@ private String[] getPasswordForUser(Connection conn, String username) throws SQL
String[] result;
boolean returningSeparatedSalt = false;
switch (saltStyle) {
- case NO_SALT:
- case CRYPT:
- case EXTERNAL:
- result = new String[1];
- break;
- default:
- result = new String[2];
- returningSeparatedSalt = true;
+ case NO_SALT:
+ case CRYPT:
+ case EXTERNAL:
+ result = new String[1];
+ break;
+ default:
+ result = new String[2];
+ returningSeparatedSalt = true;
}
-
+
PreparedStatement ps = null;
ResultSet rs = null;
try {
@@ -313,7 +314,8 @@ private String[] getPasswordForUser(Connection conn, String username) throws SQL
// Check to ensure only one row is processed
if (foundResult) {
- throw new AuthenticationException("More than one user row found for user [" + username + "]. Usernames must be unique.");
+ throw new AuthenticationException("More than one user row found for user ["
+ + username + "]. Usernames must be unique.");
}
result[0] = rs.getString(1);
@@ -361,8 +363,8 @@ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal
} catch (SQLException e) {
final String message = "There was a SQL error while authorizing user [" + username + "]";
- if (log.isErrorEnabled()) {
- log.error(message, e);
+ if (LOGGER.isErrorEnabled()) {
+ LOGGER.error(message, e);
}
// Rethrow any SQL errors as an authorization exception
@@ -397,8 +399,8 @@ protected Set getRoleNamesForUser(Connection conn, String username) thro
if (roleName != null) {
roleNames.add(roleName);
} else {
- if (log.isWarnEnabled()) {
- log.warn("Null role name found while retrieving role names for user [" + username + "]");
+ if (LOGGER.isWarnEnabled()) {
+ LOGGER.warn("Null role name found while retrieving role names for user [" + username + "]");
}
}
}
@@ -443,7 +445,7 @@ protected Set getPermissions(Connection conn, String username, Collectio
return permissions;
}
-
+
protected String getSaltForUser(String username) {
return username;
}
diff --git a/core/src/main/java/org/apache/shiro/realm/jdbc/package-info.java b/core/src/main/java/org/apache/shiro/realm/jdbc/package-info.java
index af7be66ef1..40c469f043 100644
--- a/core/src/main/java/org/apache/shiro/realm/jdbc/package-info.java
+++ b/core/src/main/java/org/apache/shiro/realm/jdbc/package-info.java
@@ -16,8 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
+
/**
- * Realms that acquire security data from an RDBMS (Relational Database Management System) using the
+ * Realms that acquire security data from an RDBMS (Relational Database Management System) using the
* JDBC API.
*/
package org.apache.shiro.realm.jdbc;
diff --git a/core/src/main/java/org/apache/shiro/realm/jndi/JndiRealmFactory.java b/core/src/main/java/org/apache/shiro/realm/jndi/JndiRealmFactory.java
index 45144d3251..6ca774fb35 100644
--- a/core/src/main/java/org/apache/shiro/realm/jndi/JndiRealmFactory.java
+++ b/core/src/main/java/org/apache/shiro/realm/jndi/JndiRealmFactory.java
@@ -40,7 +40,7 @@
*/
public class JndiRealmFactory extends JndiLocator implements RealmFactory {
- Collection jndiNames = null;
+ Collection jndiNames;
/**
* Returns the JNDI names that will be used to look up Realm(s) from JNDI.
@@ -80,8 +80,8 @@ public void setJndiNames(Collection jndiNames) {
public void setJndiNames(String commaDelimited) throws IllegalStateException {
String arg = StringUtils.clean(commaDelimited);
if (arg == null) {
- String msg = "One or more comma-delimited jndi names must be specified for the " +
- getClass().getName() + " to locate Realms.";
+ String msg = "One or more comma-delimited jndi names must be specified for the "
+ + getClass().getName() + " to locate Realms.";
throw new IllegalStateException(msg);
}
String[] names = StringUtils.tokenizeToStringArray(arg, ",");
@@ -101,8 +101,8 @@ public void setJndiNames(String commaDelimited) throws IllegalStateException {
public Collection getRealms() throws IllegalStateException {
Collection jndiNames = getJndiNames();
if (jndiNames == null || jndiNames.isEmpty()) {
- String msg = "One or more jndi names must be specified for the " +
- getClass().getName() + " to locate Realms.";
+ String msg = "One or more jndi names must be specified for the "
+ + getClass().getName() + " to locate Realms.";
throw new IllegalStateException(msg);
}
List realms = new ArrayList(jndiNames.size());
diff --git a/core/src/main/java/org/apache/shiro/realm/jndi/package-info.java b/core/src/main/java/org/apache/shiro/realm/jndi/package-info.java
index 4aa3f9317f..fcd9cb1dd0 100644
--- a/core/src/main/java/org/apache/shiro/realm/jndi/package-info.java
+++ b/core/src/main/java/org/apache/shiro/realm/jndi/package-info.java
@@ -17,5 +17,6 @@
* under the License.
*/
/**
- * Support for acquiring Realms from JNDI, particularly useful for configuring Shiro in JEE or EJB environments. */
+ * Support for acquiring Realms from JNDI, particularly useful for configuring Shiro in JEE or EJB environments.
+ */
package org.apache.shiro.realm.jndi;
diff --git a/core/src/main/java/org/apache/shiro/realm/ldap/AbstractLdapRealm.java b/core/src/main/java/org/apache/shiro/realm/ldap/AbstractLdapRealm.java
index 7909e89855..edd6e52832 100644
--- a/core/src/main/java/org/apache/shiro/realm/ldap/AbstractLdapRealm.java
+++ b/core/src/main/java/org/apache/shiro/realm/ldap/AbstractLdapRealm.java
@@ -37,8 +37,8 @@
* list as well.
*
*
Implementations would need to implement the
- * {@link #queryForAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken ,LdapContextFactory)} and
- * {@link #queryForAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection ,LdapContextFactory)} abstract methods.
By default, this implementation will create an instance of {@link JndiLdapContextFactory} to use for
* creating LDAP connections using the principalSuffix, searchBase, url, systemUsername, and systemPassword properties
@@ -46,19 +46,17 @@
* sufficient. If more customized connections are needed, you should inject a custom {@link LdapContextFactory}, which
* will cause these properties specified on the realm to be ignored.
*
- * @see #queryForAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken , LdapContextFactory)
- * @see #queryForAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection , LdapContextFactory)
+ * @see #queryForAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken, LdapContextFactory)
+ * @see #queryForAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection, LdapContextFactory)
* @since 0.1
*/
public abstract class AbstractLdapRealm extends AuthorizingRealm {
- //TODO - complete JavaDoc
-
/*--------------------------------------------
| C O N S T A N T S |
============================================*/
- private static final Logger log = LoggerFactory.getLogger(AbstractLdapRealm.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractLdapRealm.class);
/*--------------------------------------------
| I N S T A N C E V A R I A B L E S |
@@ -69,26 +67,26 @@ public abstract class AbstractLdapRealm extends AuthorizingRealm {
* AD Example:
* User's Principal Name be "John.Doe"
* User's E-Mail Address be "John.Doe@example.com"
- *
* For the example below, set:
- * realm.principalSuffix = @example.com
- *
+ * realm.principalSuffix = @example.com
* Only then, "John.Doe" and also "John.Doe@example.com" can authorize against groups
*/
- protected String principalSuffix = null;
+ protected String principalSuffix;
- protected String searchBase = null;
+ protected String searchBase;
- protected String url = null;
+ protected String url;
- protected String systemUsername = null;
+ protected String systemUsername;
- protected String systemPassword = null;
+ protected String systemPassword;
- //SHIRO-115 - prevent potential code injection:
+ /**
+ * SHIRO-115 - prevent potential code injection.
+ */
protected String searchFilter = "(&(objectClass=*)(userPrincipalName={0}))";
- private LdapContextFactory ldapContextFactory = null;
+ private LdapContextFactory ldapContextFactory;
/*--------------------------------------------
| C O N S T R U C T O R S |
@@ -177,8 +175,8 @@ protected void onInit() {
private LdapContextFactory ensureContextFactory() {
if (this.ldapContextFactory == null) {
- if (log.isDebugEnabled()) {
- log.debug("No LdapContextFactory specified - creating a default instance.");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("No LdapContextFactory specified - creating a default instance.");
}
JndiLdapContextFactory defaultFactory = new JndiLdapContextFactory();
@@ -230,8 +228,8 @@ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal
* @return an {@link AuthenticationInfo} instance containing information retrieved from the LDAP server.
* @throws NamingException if any LDAP errors occur during the search.
*/
- protected abstract AuthenticationInfo queryForAuthenticationInfo(AuthenticationToken token, LdapContextFactory ldapContextFactory) throws NamingException;
-
+ protected abstract AuthenticationInfo queryForAuthenticationInfo(AuthenticationToken token,
+ LdapContextFactory ldapContextFactory) throws NamingException;
/**
*
Abstract method that should be implemented by subclasses to builds an
@@ -243,6 +241,7 @@ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal
* @return an {@link AuthorizationInfo} instance containing information retrieved from the LDAP server.
* @throws NamingException if any LDAP errors occur during the search.
*/
- protected abstract AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principal, LdapContextFactory ldapContextFactory) throws NamingException;
+ protected abstract AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principal,
+ LdapContextFactory ldapContextFactory) throws NamingException;
}
diff --git a/core/src/main/java/org/apache/shiro/realm/ldap/DefaultLdapRealm.java b/core/src/main/java/org/apache/shiro/realm/ldap/DefaultLdapRealm.java
index 75f477e44e..d742f7bf30 100644
--- a/core/src/main/java/org/apache/shiro/realm/ldap/DefaultLdapRealm.java
+++ b/core/src/main/java/org/apache/shiro/realm/ldap/DefaultLdapRealm.java
@@ -1,430 +1,429 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.shiro.realm.ldap;
-
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.AuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.authc.SimpleAuthenticationInfo;
-import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
-import org.apache.shiro.authz.AuthorizationException;
-import org.apache.shiro.authz.AuthorizationInfo;
-import org.apache.shiro.ldap.UnsupportedAuthenticationMechanismException;
-import org.apache.shiro.realm.AuthorizingRealm;
-import org.apache.shiro.subject.PrincipalCollection;
-import org.apache.shiro.lang.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.naming.AuthenticationNotSupportedException;
-import javax.naming.NamingException;
-import javax.naming.ldap.LdapContext;
-
-/**
- * An LDAP {@link org.apache.shiro.realm.Realm Realm} implementation utilizing Sun's/Oracle's
- * JNDI API as an LDAP API. This is
- * Shiro's default implementation for supporting LDAP, as using the JNDI API has been a common approach for Java LDAP
- * support for many years.
- *
- * This realm implementation and its backing {@link JndiLdapContextFactory} should cover 99% of all Shiro-related LDAP
- * authentication and authorization needs. However, if it does not suit your needs, you might want to look into
- * creating your own realm using an alternative, perhaps more robust, LDAP communication API, such as the
- * Apache LDAP API.
- *
Authentication
- * During an authentication attempt, if the submitted {@code AuthenticationToken}'s
- * {@link org.apache.shiro.authc.AuthenticationToken#getPrincipal() principal} is a simple username, but the
- * LDAP directory expects a complete User Distinguished Name (User DN) to establish a connection, the
- * {@link #setUserDnTemplate(String) userDnTemplate} property must be configured. If not configured,
- * the property will pass the simple username directly as the User DN, which is often incorrect in most LDAP
- * environments (maybe Microsoft ActiveDirectory being the exception).
- *
Authorization
- * By default, authorization is effectively disabled due to the default
- * {@link #doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)} implementation returning {@code null}.
- * If you wish to perform authorization based on an LDAP schema, you must subclass this one
- * and override that method to reflect your organization's data model.
- *
Configuration
- * This class primarily provides the {@link #setUserDnTemplate(String) userDnTemplate} property to allow you to specify
- * the your LDAP server's User DN format. Most other configuration is performed via the nested
- * {@link LdapContextFactory contextFactory} property.
- *
- * For example, defining this realm in Shiro .ini:
- *
- * The default {@link #setContextFactory contextFactory} instance is a {@link JndiLdapContextFactory}. See that
- * class's JavaDoc for more information on configuring the LDAP connection as well as specifying JNDI environment
- * properties as necessary.
- *
- * @see JndiLdapContextFactory
- *
- * @since 1.3
- */
-public class DefaultLdapRealm extends AuthorizingRealm {
-
- private static final Logger log = LoggerFactory.getLogger(DefaultLdapRealm.class);
-
- //The zero index currently means nothing, but could be utilized in the future for other substitution techniques.
- private static final String USERDN_SUBSTITUTION_TOKEN = "{0}";
-
- private String userDnPrefix;
- private String userDnSuffix;
-
- /*--------------------------------------------
- | I N S T A N C E V A R I A B L E S |
- ============================================*/
- /**
- * The LdapContextFactory instance used to acquire {@link javax.naming.ldap.LdapContext LdapContext}'s at runtime
- * to acquire connections to the LDAP directory to perform authentication attempts and authorization queries.
- */
- private LdapContextFactory contextFactory;
-
- /*--------------------------------------------
- | C O N S T R U C T O R S |
- ============================================*/
-
- /**
- * Default no-argument constructor that defaults the internal {@link LdapContextFactory} instance to a
- * {@link JndiLdapContextFactory}.
- */
- public DefaultLdapRealm() {
- //Credentials Matching is not necessary - the LDAP directory will do it automatically:
- setCredentialsMatcher(new AllowAllCredentialsMatcher());
- //Any Object principal and Object credentials may be passed to the LDAP provider, so accept any token:
- setAuthenticationTokenClass(AuthenticationToken.class);
- this.contextFactory = new JndiLdapContextFactory();
- }
-
- /*--------------------------------------------
- | A C C E S S O R S / M O D I F I E R S |
- ============================================*/
-
- /**
- * Returns the User DN prefix to use when building a runtime User DN value or {@code null} if no
- * {@link #getUserDnTemplate() userDnTemplate} has been configured. If configured, this value is the text that
- * occurs before the {@link #USERDN_SUBSTITUTION_TOKEN} in the {@link #getUserDnTemplate() userDnTemplate} value.
- *
- * @return the the User DN prefix to use when building a runtime User DN value or {@code null} if no
- * {@link #getUserDnTemplate() userDnTemplate} has been configured.
- */
- protected String getUserDnPrefix() {
- return userDnPrefix;
- }
-
- /**
- * Returns the User DN suffix to use when building a runtime User DN value. or {@code null} if no
- * {@link #getUserDnTemplate() userDnTemplate} has been configured. If configured, this value is the text that
- * occurs after the {@link #USERDN_SUBSTITUTION_TOKEN} in the {@link #getUserDnTemplate() userDnTemplate} value.
- *
- * @return the User DN suffix to use when building a runtime User DN value or {@code null} if no
- * {@link #getUserDnTemplate() userDnTemplate} has been configured.
- */
- protected String getUserDnSuffix() {
- return userDnSuffix;
- }
-
- /*--------------------------------------------
- | M E T H O D S |
- ============================================*/
-
- /**
- * Sets the User Distinguished Name (DN) template to use when creating User DNs at runtime. A User DN is an LDAP
- * fully-qualified unique user identifier which is required to establish a connection with the LDAP
- * directory to authenticate users and query for authorization information.
- *
Usage
- * User DN formats are unique to the LDAP directory's schema, and each environment differs - you will need to
- * specify the format corresponding to your directory. You do this by specifying the full User DN as normal, but
- * but you use a {@code {0}} placeholder token in the string representing the location where the
- * user's submitted principal (usually a username or uid) will be substituted at runtime.
- *
- * For example, if your directory
- * uses an LDAP {@code uid} attribute to represent usernames, the User DN for the {@code jsmith} user may look like
- * this:
- *
- *
uid=jsmith,ou=users,dc=mycompany,dc=com
- *
- * in which case you would set this property with the following template value:
- *
- *
uid={0},ou=users,dc=mycompany,dc=com
- *
- * If no template is configured, the raw {@code AuthenticationToken}
- * {@link AuthenticationToken#getPrincipal() principal} will be used as the LDAP principal. This is likely
- * incorrect as most LDAP directories expect a fully-qualified User DN as opposed to the raw uid or username. So,
- * ensure you set this property to match your environment!
- *
- * @param template the User Distinguished Name template to use for runtime substitution
- * @throws IllegalArgumentException if the template is null, empty, or does not contain the
- * {@code {0}} substitution token.
- * @see LdapContextFactory#getLdapContext(Object,Object)
- */
- public void setUserDnTemplate(String template) throws IllegalArgumentException {
- if (!StringUtils.hasText(template)) {
- String msg = "User DN template cannot be null or empty.";
- throw new IllegalArgumentException(msg);
- }
- int index = template.indexOf(USERDN_SUBSTITUTION_TOKEN);
- if (index < 0) {
- String msg = "User DN template must contain the '" +
- USERDN_SUBSTITUTION_TOKEN + "' replacement token to understand where to " +
- "insert the runtime authentication principal.";
- throw new IllegalArgumentException(msg);
- }
- String prefix = template.substring(0, index);
- String suffix = template.substring(prefix.length() + USERDN_SUBSTITUTION_TOKEN.length());
- if (log.isDebugEnabled()) {
- log.debug("Determined user DN prefix [{}] and suffix [{}]", prefix, suffix);
- }
- this.userDnPrefix = prefix;
- this.userDnSuffix = suffix;
- }
-
- /**
- * Returns the User Distinguished Name (DN) template to use when creating User DNs at runtime - see the
- * {@link #setUserDnTemplate(String) setUserDnTemplate} JavaDoc for a full explanation.
- *
- * @return the User Distinguished Name (DN) template to use when creating User DNs at runtime.
- */
- public String getUserDnTemplate() {
- return getUserDn(USERDN_SUBSTITUTION_TOKEN);
- }
-
- /**
- * Returns the LDAP User Distinguished Name (DN) to use when acquiring an
- * {@link javax.naming.ldap.LdapContext LdapContext} from the {@link LdapContextFactory}.
- *
- * If the the {@link #getUserDnTemplate() userDnTemplate} property has been set, this implementation will construct
- * the User DN by substituting the specified {@code principal} into the configured template. If the
- * {@link #getUserDnTemplate() userDnTemplate} has not been set, the method argument will be returned directly
- * (indicating that the submitted authentication token principal is the User DN).
- *
- * @param principal the principal to substitute into the configured {@link #getUserDnTemplate() userDnTemplate}.
- * @return the constructed User DN to use at runtime when acquiring an {@link javax.naming.ldap.LdapContext}.
- * @throws IllegalArgumentException if the method argument is null or empty
- * @throws IllegalStateException if the {@link #getUserDnTemplate userDnTemplate} has not been set.
- * @see LdapContextFactory#getLdapContext(Object, Object)
- */
- protected String getUserDn(String principal) throws IllegalArgumentException, IllegalStateException {
- if (!StringUtils.hasText(principal)) {
- throw new IllegalArgumentException("User principal cannot be null or empty for User DN construction.");
- }
- String prefix = getUserDnPrefix();
- String suffix = getUserDnSuffix();
- if (prefix == null && suffix == null) {
- log.debug("userDnTemplate property has not been configured, indicating the submitted " +
- "AuthenticationToken's principal is the same as the User DN. Returning the method argument " +
- "as is.");
- return principal;
- }
-
- int prefixLength = prefix != null ? prefix.length() : 0;
- int suffixLength = suffix != null ? suffix.length() : 0;
- StringBuilder sb = new StringBuilder(prefixLength + principal.length() + suffixLength);
- if (prefixLength > 0) {
- sb.append(prefix);
- }
- sb.append(principal);
- if (suffixLength > 0) {
- sb.append(suffix);
- }
- return sb.toString();
- }
-
- /**
- * Sets the LdapContextFactory instance used to acquire connections to the LDAP directory during authentication
- * attempts and authorization queries. Unless specified otherwise, the default is a {@link JndiLdapContextFactory}
- * instance.
- *
- * @param contextFactory the LdapContextFactory instance used to acquire connections to the LDAP directory during
- * authentication attempts and authorization queries
- */
- @SuppressWarnings({"UnusedDeclaration"})
- public void setContextFactory(LdapContextFactory contextFactory) {
- this.contextFactory = contextFactory;
- }
-
- /**
- * Returns the LdapContextFactory instance used to acquire connections to the LDAP directory during authentication
- * attempts and authorization queries. Unless specified otherwise, the default is a {@link JndiLdapContextFactory}
- * instance.
- *
- * @return the LdapContextFactory instance used to acquire connections to the LDAP directory during
- * authentication attempts and authorization queries
- */
- public LdapContextFactory getContextFactory() {
- return this.contextFactory;
- }
-
- /*--------------------------------------------
- | M E T H O D S |
- ============================================*/
-
- /**
- * Delegates to {@link #queryForAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken, LdapContextFactory)},
- * wrapping any {@link NamingException}s in a Shiro {@link AuthenticationException} to satisfy the parent method
- * signature.
- *
- * @param token the authentication token containing the user's principal and credentials.
- * @return the {@link AuthenticationInfo} acquired after a successful authentication attempt
- * @throws AuthenticationException if the authentication attempt fails or if a
- * {@link NamingException} occurs.
- */
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
- AuthenticationInfo info;
- try {
- info = queryForAuthenticationInfo(token, getContextFactory());
- } catch (AuthenticationNotSupportedException e) {
- String msg = "Unsupported configured authentication mechanism";
- throw new UnsupportedAuthenticationMechanismException(msg, e);
- } catch (javax.naming.AuthenticationException e) {
- throw new AuthenticationException("LDAP authentication failed.", e);
- } catch (NamingException e) {
- String msg = "LDAP naming error while attempting to authenticate user.";
- throw new AuthenticationException(msg, e);
- }
-
- return info;
- }
-
-
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- AuthorizationInfo info;
- try {
- info = queryForAuthorizationInfo(principals, getContextFactory());
- } catch (NamingException e) {
- String msg = "LDAP naming error while attempting to retrieve authorization for user [" + principals + "].";
- throw new AuthorizationException(msg, e);
- }
-
- return info;
- }
-
- /**
- * Returns the principal to use when creating the LDAP connection for an authentication attempt.
- *
- * This implementation uses a heuristic: it checks to see if the specified token's
- * {@link AuthenticationToken#getPrincipal() principal} is a {@code String}, and if so,
- * {@link #getUserDn(String) converts it} from what is
- * assumed to be a raw uid or username {@code String} into a User DN {@code String}. Almost all LDAP directories
- * expect the authentication connection to present a User DN and not an unqualified username or uid.
- *
- * If the token's {@code principal} is not a String, it is assumed to already be in the format supported by the
- * underlying {@link LdapContextFactory} implementation and the raw principal is returned directly.
- *
- * @param token the {@link AuthenticationToken} submitted during the authentication process
- * @return the User DN or raw principal to use to acquire the LdapContext.
- * @see LdapContextFactory#getLdapContext(Object, Object)
- */
- protected Object getLdapPrincipal(AuthenticationToken token) {
- Object principal = token.getPrincipal();
- if (principal instanceof String) {
- String sPrincipal = (String) principal;
- return getUserDn(sPrincipal);
- }
- return principal;
- }
-
- /**
- * This implementation opens an LDAP connection using the token's
- * {@link #getLdapPrincipal(org.apache.shiro.authc.AuthenticationToken) discovered principal} and provided
- * {@link AuthenticationToken#getCredentials() credentials}. If the connection opens successfully, the
- * authentication attempt is immediately considered successful and a new
- * {@link AuthenticationInfo} instance is
- * {@link #createAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken, Object, Object, javax.naming.ldap.LdapContext) created}
- * and returned. If the connection cannot be opened, either because LDAP authentication failed or some other
- * JNDI problem, an {@link NamingException} will be thrown.
- *
- * @param token the submitted authentication token that triggered the authentication attempt.
- * @param ldapContextFactory factory used to retrieve LDAP connections.
- * @return an {@link AuthenticationInfo} instance representing the authenticated user's information.
- * @throws NamingException if any LDAP errors occur.
- */
- protected AuthenticationInfo queryForAuthenticationInfo(AuthenticationToken token,
- LdapContextFactory ldapContextFactory)
- throws NamingException {
-
- Object principal = token.getPrincipal();
- Object credentials = token.getCredentials();
-
- log.debug("Authenticating user '{}' through LDAP", principal);
-
- principal = getLdapPrincipal(token);
-
- LdapContext ctx = null;
- try {
- ctx = ldapContextFactory.getLdapContext(principal, credentials);
- //context was opened successfully, which means their credentials were valid. Return the AuthenticationInfo:
- return createAuthenticationInfo(token, principal, credentials, ctx);
- } finally {
- LdapUtils.closeContext(ctx);
- }
- }
-
- /**
- * Returns the {@link AuthenticationInfo} resulting from a Subject's successful LDAP authentication attempt.
- *
- * This implementation ignores the {@code ldapPrincipal}, {@code ldapCredentials}, and the opened
- * {@code ldapContext} arguments and merely returns an {@code AuthenticationInfo} instance mirroring the
- * submitted token's principal and credentials. This is acceptable because this method is only ever invoked after
- * a successful authentication attempt, which means the provided principal and credentials were correct, and can
- * be used directly to populate the (now verified) {@code AuthenticationInfo}.
- *
- * Subclasses however are free to override this method for more advanced construction logic.
- *
- * @param token the submitted {@code AuthenticationToken} that resulted in a successful authentication
- * @param ldapPrincipal the LDAP principal used when creating the LDAP connection. Unlike the token's
- * {@link AuthenticationToken#getPrincipal() principal}, this value is usually a constructed
- * User DN and not a simple username or uid. The exact value is depending on the
- * configured
- *
- * LDAP authentication mechanism in use.
- * @param ldapCredentials the LDAP credentials used when creating the LDAP connection.
- * @param ldapContext the LdapContext created that resulted in a successful authentication. It can be used
- * further by subclasses for more complex operations. It does not need to be closed -
- * it will be closed automatically after this method returns.
- * @return the {@link AuthenticationInfo} resulting from a Subject's successful LDAP authentication attempt.
- * @throws NamingException if there was any problem using the {@code LdapContext}
- */
- @SuppressWarnings({"UnusedDeclaration"})
- protected AuthenticationInfo createAuthenticationInfo(AuthenticationToken token, Object ldapPrincipal,
- Object ldapCredentials, LdapContext ldapContext)
- throws NamingException {
- return new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName());
- }
-
-
- /**
- * Method that should be implemented by subclasses to build an
- * {@link AuthorizationInfo} object by querying the LDAP context for the
- * specified principal.
- *
- * @param principals the principals of the Subject whose AuthenticationInfo should be queried from the LDAP server.
- * @param ldapContextFactory factory used to retrieve LDAP connections.
- * @return an {@link AuthorizationInfo} instance containing information retrieved from the LDAP server.
- * @throws NamingException if any LDAP errors occur during the search.
- */
- protected AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principals,
- LdapContextFactory ldapContextFactory) throws NamingException {
- return null;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.realm.ldap;
+
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.ldap.UnsupportedAuthenticationMechanismException;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.lang.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.AuthenticationNotSupportedException;
+import javax.naming.NamingException;
+import javax.naming.ldap.LdapContext;
+
+/**
+ * An LDAP {@link org.apache.shiro.realm.Realm Realm} implementation utilizing Sun's/Oracle's
+ * JNDI API as an LDAP API. This is
+ * Shiro's default implementation for supporting LDAP, as using the JNDI API has been a common approach for Java LDAP
+ * support for many years.
+ *
+ * This realm implementation and its backing {@link JndiLdapContextFactory} should cover 99% of all Shiro-related LDAP
+ * authentication and authorization needs. However, if it does not suit your needs, you might want to look into
+ * creating your own realm using an alternative, perhaps more robust, LDAP communication API, such as the
+ * Apache LDAP API.
+ *
Authentication
+ * During an authentication attempt, if the submitted {@code AuthenticationToken}'s
+ * {@link org.apache.shiro.authc.AuthenticationToken#getPrincipal() principal} is a simple username, but the
+ * LDAP directory expects a complete User Distinguished Name (User DN) to establish a connection, the
+ * {@link #setUserDnTemplate(String) userDnTemplate} property must be configured. If not configured,
+ * the property will pass the simple username directly as the User DN, which is often incorrect in most LDAP
+ * environments (maybe Microsoft ActiveDirectory being the exception).
+ *
Authorization
+ * By default, authorization is effectively disabled due to the default
+ * {@link #doGetAuthorizationInfo(org.apache.shiro.subject.PrincipalCollection)} implementation returning {@code null}.
+ * If you wish to perform authorization based on an LDAP schema, you must subclass this one
+ * and override that method to reflect your organization's data model.
+ *
Configuration
+ * This class primarily provides the {@link #setUserDnTemplate(String) userDnTemplate} property to allow you to specify
+ * the your LDAP server's User DN format. Most other configuration is performed via the nested
+ * {@link LdapContextFactory contextFactory} property.
+ *
+ * For example, defining this realm in Shiro .ini:
+ *
+ * The default {@link #setContextFactory contextFactory} instance is a {@link JndiLdapContextFactory}. See that
+ * class's JavaDoc for more information on configuring the LDAP connection as well as specifying JNDI environment
+ * properties as necessary.
+ *
+ * @see JndiLdapContextFactory
+ * @since 1.3
+ */
+public class DefaultLdapRealm extends AuthorizingRealm {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultLdapRealm.class);
+
+ //The zero index currently means nothing, but could be utilized in the future for other substitution techniques.
+ private static final String USERDN_SUBSTITUTION_TOKEN = "{0}";
+
+ private String userDnPrefix;
+ private String userDnSuffix;
+
+ /*--------------------------------------------
+ | I N S T A N C E V A R I A B L E S |
+ ============================================*/
+ /**
+ * The LdapContextFactory instance used to acquire {@link javax.naming.ldap.LdapContext LdapContext}'s at runtime
+ * to acquire connections to the LDAP directory to perform authentication attempts and authorization queries.
+ */
+ private LdapContextFactory contextFactory;
+
+ /*--------------------------------------------
+ | C O N S T R U C T O R S |
+ ============================================*/
+
+ /**
+ * Default no-argument constructor that defaults the internal {@link LdapContextFactory} instance to a
+ * {@link JndiLdapContextFactory}.
+ */
+ public DefaultLdapRealm() {
+ //Credentials Matching is not necessary - the LDAP directory will do it automatically:
+ setCredentialsMatcher(new AllowAllCredentialsMatcher());
+ //Any Object principal and Object credentials may be passed to the LDAP provider, so accept any token:
+ setAuthenticationTokenClass(AuthenticationToken.class);
+ this.contextFactory = new JndiLdapContextFactory();
+ }
+
+ /*--------------------------------------------
+ | A C C E S S O R S / M O D I F I E R S |
+ ============================================*/
+
+ /**
+ * Returns the User DN prefix to use when building a runtime User DN value or {@code null} if no
+ * {@link #getUserDnTemplate() userDnTemplate} has been configured. If configured, this value is the text that
+ * occurs before the {@link #USERDN_SUBSTITUTION_TOKEN} in the {@link #getUserDnTemplate() userDnTemplate} value.
+ *
+ * @return the the User DN prefix to use when building a runtime User DN value or {@code null} if no
+ * {@link #getUserDnTemplate() userDnTemplate} has been configured.
+ */
+ protected String getUserDnPrefix() {
+ return userDnPrefix;
+ }
+
+ /**
+ * Returns the User DN suffix to use when building a runtime User DN value. or {@code null} if no
+ * {@link #getUserDnTemplate() userDnTemplate} has been configured. If configured, this value is the text that
+ * occurs after the {@link #USERDN_SUBSTITUTION_TOKEN} in the {@link #getUserDnTemplate() userDnTemplate} value.
+ *
+ * @return the User DN suffix to use when building a runtime User DN value or {@code null} if no
+ * {@link #getUserDnTemplate() userDnTemplate} has been configured.
+ */
+ protected String getUserDnSuffix() {
+ return userDnSuffix;
+ }
+
+ /*--------------------------------------------
+ | M E T H O D S |
+ ============================================*/
+
+ /**
+ * Sets the User Distinguished Name (DN) template to use when creating User DNs at runtime. A User DN is an LDAP
+ * fully-qualified unique user identifier which is required to establish a connection with the LDAP
+ * directory to authenticate users and query for authorization information.
+ *
Usage
+ * User DN formats are unique to the LDAP directory's schema, and each environment differs - you will need to
+ * specify the format corresponding to your directory. You do this by specifying the full User DN as normal, but
+ * but you use a {@code {0}} placeholder token in the string representing the location where the
+ * user's submitted principal (usually a username or uid) will be substituted at runtime.
+ *
+ * For example, if your directory
+ * uses an LDAP {@code uid} attribute to represent usernames, the User DN for the {@code jsmith} user may look like
+ * this:
+ *
+ *
uid=jsmith,ou=users,dc=mycompany,dc=com
+ *
+ * in which case you would set this property with the following template value:
+ *
+ *
uid={0},ou=users,dc=mycompany,dc=com
+ *
+ * If no template is configured, the raw {@code AuthenticationToken}
+ * {@link AuthenticationToken#getPrincipal() principal} will be used as the LDAP principal. This is likely
+ * incorrect as most LDAP directories expect a fully-qualified User DN as opposed to the raw uid or username. So,
+ * ensure you set this property to match your environment!
+ *
+ * @param template the User Distinguished Name template to use for runtime substitution
+ * @throws IllegalArgumentException if the template is null, empty, or does not contain the
+ * {@code {0}} substitution token.
+ * @see LdapContextFactory#getLdapContext(Object, Object)
+ */
+ public void setUserDnTemplate(String template) throws IllegalArgumentException {
+ if (!StringUtils.hasText(template)) {
+ String msg = "User DN template cannot be null or empty.";
+ throw new IllegalArgumentException(msg);
+ }
+ int index = template.indexOf(USERDN_SUBSTITUTION_TOKEN);
+ if (index < 0) {
+ String msg = "User DN template must contain the '"
+ + USERDN_SUBSTITUTION_TOKEN + "' replacement token to understand where to "
+ + "insert the runtime authentication principal.";
+ throw new IllegalArgumentException(msg);
+ }
+ String prefix = template.substring(0, index);
+ String suffix = template.substring(prefix.length() + USERDN_SUBSTITUTION_TOKEN.length());
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Determined user DN prefix [{}] and suffix [{}]", prefix, suffix);
+ }
+ this.userDnPrefix = prefix;
+ this.userDnSuffix = suffix;
+ }
+
+ /**
+ * Returns the User Distinguished Name (DN) template to use when creating User DNs at runtime - see the
+ * {@link #setUserDnTemplate(String) setUserDnTemplate} JavaDoc for a full explanation.
+ *
+ * @return the User Distinguished Name (DN) template to use when creating User DNs at runtime.
+ */
+ public String getUserDnTemplate() {
+ return getUserDn(USERDN_SUBSTITUTION_TOKEN);
+ }
+
+ /**
+ * Returns the LDAP User Distinguished Name (DN) to use when acquiring an
+ * {@link javax.naming.ldap.LdapContext LdapContext} from the {@link LdapContextFactory}.
+ *
+ * If the the {@link #getUserDnTemplate() userDnTemplate} property has been set, this implementation will construct
+ * the User DN by substituting the specified {@code principal} into the configured template. If the
+ * {@link #getUserDnTemplate() userDnTemplate} has not been set, the method argument will be returned directly
+ * (indicating that the submitted authentication token principal is the User DN).
+ *
+ * @param principal the principal to substitute into the configured {@link #getUserDnTemplate() userDnTemplate}.
+ * @return the constructed User DN to use at runtime when acquiring an {@link javax.naming.ldap.LdapContext}.
+ * @throws IllegalArgumentException if the method argument is null or empty
+ * @throws IllegalStateException if the {@link #getUserDnTemplate userDnTemplate} has not been set.
+ * @see LdapContextFactory#getLdapContext(Object, Object)
+ */
+ protected String getUserDn(String principal) throws IllegalArgumentException, IllegalStateException {
+ if (!StringUtils.hasText(principal)) {
+ throw new IllegalArgumentException("User principal cannot be null or empty for User DN construction.");
+ }
+ String prefix = getUserDnPrefix();
+ String suffix = getUserDnSuffix();
+ if (prefix == null && suffix == null) {
+ LOGGER.debug("userDnTemplate property has not been configured, indicating the submitted "
+ + "AuthenticationToken's principal is the same as the User DN. Returning the method argument "
+ + "as is.");
+ return principal;
+ }
+
+ int prefixLength = prefix != null ? prefix.length() : 0;
+ int suffixLength = suffix != null ? suffix.length() : 0;
+ StringBuilder sb = new StringBuilder(prefixLength + principal.length() + suffixLength);
+ if (prefixLength > 0) {
+ sb.append(prefix);
+ }
+ sb.append(principal);
+ if (suffixLength > 0) {
+ sb.append(suffix);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Sets the LdapContextFactory instance used to acquire connections to the LDAP directory during authentication
+ * attempts and authorization queries. Unless specified otherwise, the default is a {@link JndiLdapContextFactory}
+ * instance.
+ *
+ * @param contextFactory the LdapContextFactory instance used to acquire connections to the LDAP directory during
+ * authentication attempts and authorization queries
+ */
+ @SuppressWarnings({"UnusedDeclaration"})
+ public void setContextFactory(LdapContextFactory contextFactory) {
+ this.contextFactory = contextFactory;
+ }
+
+ /**
+ * Returns the LdapContextFactory instance used to acquire connections to the LDAP directory during authentication
+ * attempts and authorization queries. Unless specified otherwise, the default is a {@link JndiLdapContextFactory}
+ * instance.
+ *
+ * @return the LdapContextFactory instance used to acquire connections to the LDAP directory during
+ * authentication attempts and authorization queries
+ */
+ public LdapContextFactory getContextFactory() {
+ return this.contextFactory;
+ }
+
+ /*--------------------------------------------
+ | M E T H O D S |
+ ============================================*/
+
+ /**
+ * Delegates to {@link #queryForAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken, LdapContextFactory)},
+ * wrapping any {@link NamingException}s in a Shiro {@link AuthenticationException} to satisfy the parent method
+ * signature.
+ *
+ * @param token the authentication token containing the user's principal and credentials.
+ * @return the {@link AuthenticationInfo} acquired after a successful authentication attempt
+ * @throws AuthenticationException if the authentication attempt fails or if a
+ * {@link NamingException} occurs.
+ */
+ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+ AuthenticationInfo info;
+ try {
+ info = queryForAuthenticationInfo(token, getContextFactory());
+ } catch (AuthenticationNotSupportedException e) {
+ String msg = "Unsupported configured authentication mechanism";
+ throw new UnsupportedAuthenticationMechanismException(msg, e);
+ } catch (javax.naming.AuthenticationException e) {
+ throw new AuthenticationException("LDAP authentication failed.", e);
+ } catch (NamingException e) {
+ String msg = "LDAP naming error while attempting to authenticate user.";
+ throw new AuthenticationException(msg, e);
+ }
+
+ return info;
+ }
+
+
+ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+ AuthorizationInfo info;
+ try {
+ info = queryForAuthorizationInfo(principals, getContextFactory());
+ } catch (NamingException e) {
+ String msg = "LDAP naming error while attempting to retrieve authorization for user [" + principals + "].";
+ throw new AuthorizationException(msg, e);
+ }
+
+ return info;
+ }
+
+ /**
+ * Returns the principal to use when creating the LDAP connection for an authentication attempt.
+ *
+ * This implementation uses a heuristic: it checks to see if the specified token's
+ * {@link AuthenticationToken#getPrincipal() principal} is a {@code String}, and if so,
+ * {@link #getUserDn(String) converts it} from what is
+ * assumed to be a raw uid or username {@code String} into a User DN {@code String}. Almost all LDAP directories
+ * expect the authentication connection to present a User DN and not an unqualified username or uid.
+ *
+ * If the token's {@code principal} is not a String, it is assumed to already be in the format supported by the
+ * underlying {@link LdapContextFactory} implementation and the raw principal is returned directly.
+ *
+ * @param token the {@link AuthenticationToken} submitted during the authentication process
+ * @return the User DN or raw principal to use to acquire the LdapContext.
+ * @see LdapContextFactory#getLdapContext(Object, Object)
+ */
+ protected Object getLdapPrincipal(AuthenticationToken token) {
+ Object principal = token.getPrincipal();
+ if (principal instanceof String) {
+ String sPrincipal = (String) principal;
+ return getUserDn(sPrincipal);
+ }
+ return principal;
+ }
+
+ /**
+ * This implementation opens an LDAP connection using the token's
+ * {@link #getLdapPrincipal(org.apache.shiro.authc.AuthenticationToken) discovered principal} and provided
+ * {@link AuthenticationToken#getCredentials() credentials}. If the connection opens successfully, the
+ * authentication attempt is immediately considered successful and a new
+ * {@link AuthenticationInfo} instance is
+ * {@link #createAuthenticationInfo(AuthenticationToken, Object, Object, LdapContext) created}
+ * and returned. If the connection cannot be opened, either because LDAP authentication failed or some other
+ * JNDI problem, an {@link NamingException} will be thrown.
+ *
+ * @param token the submitted authentication token that triggered the authentication attempt.
+ * @param ldapContextFactory factory used to retrieve LDAP connections.
+ * @return an {@link AuthenticationInfo} instance representing the authenticated user's information.
+ * @throws NamingException if any LDAP errors occur.
+ */
+ protected AuthenticationInfo queryForAuthenticationInfo(AuthenticationToken token,
+ LdapContextFactory ldapContextFactory)
+ throws NamingException {
+
+ Object principal = token.getPrincipal();
+ Object credentials = token.getCredentials();
+
+ LOGGER.debug("Authenticating user '{}' through LDAP", principal);
+
+ principal = getLdapPrincipal(token);
+
+ LdapContext ctx = null;
+ try {
+ ctx = ldapContextFactory.getLdapContext(principal, credentials);
+ //context was opened successfully, which means their credentials were valid. Return the AuthenticationInfo:
+ return createAuthenticationInfo(token, principal, credentials, ctx);
+ } finally {
+ LdapUtils.closeContext(ctx);
+ }
+ }
+
+ /**
+ * Returns the {@link AuthenticationInfo} resulting from a Subject's successful LDAP authentication attempt.
+ *
+ * This implementation ignores the {@code ldapPrincipal}, {@code ldapCredentials}, and the opened
+ * {@code ldapContext} arguments and merely returns an {@code AuthenticationInfo} instance mirroring the
+ * submitted token's principal and credentials. This is acceptable because this method is only ever invoked after
+ * a successful authentication attempt, which means the provided principal and credentials were correct, and can
+ * be used directly to populate the (now verified) {@code AuthenticationInfo}.
+ *
+ * Subclasses however are free to override this method for more advanced construction logic.
+ *
+ * @param token the submitted {@code AuthenticationToken} that resulted in a successful authentication
+ * @param ldapPrincipal the LDAP principal used when creating the LDAP connection. Unlike the token's
+ * {@link AuthenticationToken#getPrincipal() principal}, this value is usually a constructed
+ * User DN and not a simple username or uid. The exact value is depending on the
+ * configured
+ *
+ * LDAP authentication mechanism in use.
+ * @param ldapCredentials the LDAP credentials used when creating the LDAP connection.
+ * @param ldapContext the LdapContext created that resulted in a successful authentication. It can be used
+ * further by subclasses for more complex operations. It does not need to be closed -
+ * it will be closed automatically after this method returns.
+ * @return the {@link AuthenticationInfo} resulting from a Subject's successful LDAP authentication attempt.
+ * @throws NamingException if there was any problem using the {@code LdapContext}
+ */
+ @SuppressWarnings({"UnusedDeclaration"})
+ protected AuthenticationInfo createAuthenticationInfo(AuthenticationToken token, Object ldapPrincipal,
+ Object ldapCredentials, LdapContext ldapContext)
+ throws NamingException {
+ return new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName());
+ }
+
+
+ /**
+ * Method that should be implemented by subclasses to build an
+ * {@link AuthorizationInfo} object by querying the LDAP context for the
+ * specified principal.
+ *
+ * @param principals the principals of the Subject whose AuthenticationInfo should be queried from the LDAP server.
+ * @param ldapContextFactory factory used to retrieve LDAP connections.
+ * @return an {@link AuthorizationInfo} instance containing information retrieved from the LDAP server.
+ * @throws NamingException if any LDAP errors occur during the search.
+ */
+ protected AuthorizationInfo queryForAuthorizationInfo(PrincipalCollection principals,
+ LdapContextFactory ldapContextFactory) throws NamingException {
+ return null;
+ }
+}
diff --git a/core/src/main/java/org/apache/shiro/realm/ldap/JndiLdapContextFactory.java b/core/src/main/java/org/apache/shiro/realm/ldap/JndiLdapContextFactory.java
index db667931d3..4659b26f0d 100644
--- a/core/src/main/java/org/apache/shiro/realm/ldap/JndiLdapContextFactory.java
+++ b/core/src/main/java/org/apache/shiro/realm/ldap/JndiLdapContextFactory.java
@@ -1,533 +1,533 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.shiro.realm.ldap;
-
-import org.apache.shiro.lang.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.naming.AuthenticationException;
-import javax.naming.Context;
-import javax.naming.NamingException;
-import javax.naming.ldap.InitialLdapContext;
-import javax.naming.ldap.LdapContext;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-
-/**
- * {@link LdapContextFactory} implementation using the default Sun/Oracle JNDI Ldap API, utilizing JNDI
- * environment properties and an {@link javax.naming.InitialContext}.
- *
Configuration
- * This class basically wraps a default template JNDI environment properties Map. This properties map is the base
- * configuration template used to acquire JNDI {@link LdapContext} connections at runtime. The
- * {@link #getLdapContext(Object, Object)} method implementation merges this default template with other properties
- * accessible at runtime only (for example per-method principals and credentials). The constructed runtime map is the
- * one used to acquire the {@link LdapContext}.
- *
- * The template can be configured directly via the {@link #getEnvironment()}/{@link #setEnvironment(java.util.Map)}
- * properties directly if necessary, but it is usually more convenient to use the supporting wrapper get/set methods
- * for various environment properties. These wrapper methods interact with the environment
- * template on your behalf, leaving your configuration cleaner and easier to understand.
- *
- * For example, consider the following two identical configurations:
- *
- * As you can see, the 2nd configuration block is a little more difficult to read and also requires knowledge
- * of the underlying JNDI Context property keys. The first is easier to read and understand.
- *
- * Note that occasionally it will be necessary to use the latter configuration style to set environment properties
- * where no corresponding wrapper method exists. In this case, the hybrid approach is still a little easier to read.
- * For example:
- *
- *
- * @since 1.1
- */
-public class JndiLdapContextFactory implements LdapContextFactory {
-
- /*-------------------------------------------
- | C O N S T A N T S |
- ===========================================*/
- /**
- * The Sun LDAP property used to enable connection pooling. This is used in the default implementation
- * to enable LDAP connection pooling.
- */
- protected static final String SUN_CONNECTION_POOLING_PROPERTY = "com.sun.jndi.ldap.connect.pool";
- protected static final String DEFAULT_CONTEXT_FACTORY_CLASS_NAME = "com.sun.jndi.ldap.LdapCtxFactory";
- protected static final String SIMPLE_AUTHENTICATION_MECHANISM_NAME = "simple";
- protected static final String DEFAULT_REFERRAL = "follow";
-
- private static final Logger log = LoggerFactory.getLogger(JndiLdapContextFactory.class);
-
- /*-------------------------------------------
- | I N S T A N C E V A R I A B L E S |
- ============================================*/
- private Map environment;
- private boolean poolingEnabled;
- private String systemPassword;
- private String systemUsername;
-
- /*-------------------------------------------
- | C O N S T R U C T O R S |
- ===========================================*/
-
- /**
- * Default no-argument constructor that initializes the backing {@link #getEnvironment() environment template} with
- * the {@link #setContextFactoryClassName(String) contextFactoryClassName} equal to
- * {@code com.sun.jndi.ldap.LdapCtxFactory} (the Sun/Oracle default) and the default
- * {@link #setReferral(String) referral} behavior to {@code follow}.
- */
- public JndiLdapContextFactory() {
- this.environment = new HashMap();
- setContextFactoryClassName(DEFAULT_CONTEXT_FACTORY_CLASS_NAME);
- setReferral(DEFAULT_REFERRAL);
- poolingEnabled = true;
- }
-
- /*-------------------------------------------
- | A C C E S S O R S / M O D I F I E R S |
- ===========================================*/
-
- /**
- * Sets the type of LDAP authentication mechanism to use when connecting to the LDAP server.
- * This is a wrapper method for setting the JNDI {@link #getEnvironment() environment template}'s
- * {@link Context#SECURITY_AUTHENTICATION} property.
- *
- * "none" (i.e. anonymous) and "simple" authentications are supported automatically and don't need to be configured
- * via this property. However, if you require a different mechanism, such as a SASL or External mechanism, you
- * must configure that explicitly via this property. See the
- * JNDI LDAP
- * Authentication Mechanisms for more information.
- *
- * @param authenticationMechanism the type of LDAP authentication to perform.
- * @see
- * http://download-llnw.oracle.com/javase/tutorial/jndi/ldap/auth_mechs.html
- */
- public void setAuthenticationMechanism(String authenticationMechanism) {
- setEnvironmentProperty(Context.SECURITY_AUTHENTICATION, authenticationMechanism);
- }
-
- /**
- * Returns the type of LDAP authentication mechanism to use when connecting to the LDAP server.
- * This is a wrapper method for getting the JNDI {@link #getEnvironment() environment template}'s
- * {@link Context#SECURITY_AUTHENTICATION} property.
- *
- * If this property remains un-configured (i.e. {@code null} indicating the
- * {@link #setAuthenticationMechanism(String)} method wasn't used), this indicates that the default JNDI
- * "none" (anonymous) and "simple" authentications are supported automatically. Any non-null value returned
- * represents an explicitly configured mechanism (e.g. a SASL or external mechanism). See the
- * JNDI LDAP
- * Authentication Mechanisms for more information.
- *
- * @return the type of LDAP authentication mechanism to use when connecting to the LDAP server.
- * @see
- * http://download-llnw.oracle.com/javase/tutorial/jndi/ldap/auth_mechs.html
- */
- public String getAuthenticationMechanism() {
- return (String) getEnvironmentProperty(Context.SECURITY_AUTHENTICATION);
- }
-
- /**
- * The name of the ContextFactory class to use. This defaults to the SUN LDAP JNDI implementation
- * but can be overridden to use custom LDAP factories.
- *
- * This is a wrapper method for setting the JNDI environment's {@link Context#INITIAL_CONTEXT_FACTORY} property.
- *
- * @param contextFactoryClassName the context factory that should be used.
- */
- public void setContextFactoryClassName(String contextFactoryClassName) {
- setEnvironmentProperty(Context.INITIAL_CONTEXT_FACTORY, contextFactoryClassName);
- }
-
- /**
- * Sets the name of the ContextFactory class to use. This defaults to the SUN LDAP JNDI implementation
- * but can be overridden to use custom LDAP factories.
- *
- * This is a wrapper method for getting the JNDI environment's {@link Context#INITIAL_CONTEXT_FACTORY} property.
- *
- * @return the name of the ContextFactory class to use.
- */
- public String getContextFactoryClassName() {
- return (String) getEnvironmentProperty(Context.INITIAL_CONTEXT_FACTORY);
- }
-
- /**
- * Returns the base JNDI environment template to use when acquiring an LDAP connection (an {@link LdapContext}).
- * This property is the base configuration template to use for all connections. This template is then
- * merged with appropriate runtime values as necessary in the
- * {@link #getLdapContext(Object, Object)} implementation. The merged environment instance is what is used to
- * acquire the {@link LdapContext} at runtime.
- *
- * Most other get/set methods in this class act as thin proxy wrappers that interact with this property. The
- * benefit of using them is you have an easier-to-use configuration mechanism compared to setting map properties
- * based on JNDI context keys.
- *
- * @return the base JNDI environment template to use when acquiring an LDAP connection (an {@link LdapContext})
- */
- public Map getEnvironment() {
- return this.environment;
- }
-
- /**
- * Sets the base JNDI environment template to use when acquiring LDAP connections. It is typically more common
- * to use the other get/set methods in this class to set individual environment settings rather than use
- * this method, but it is available for advanced users that want full control over the base JNDI environment
- * settings.
- *
- * Note that this template only represents the base/default environment settings. It is then merged with
- * appropriate runtime values as necessary in the {@link #getLdapContext(Object, Object)} implementation.
- * The merged environment instance is what is used to acquire the connection ({@link LdapContext}) at runtime.
- *
- * @param env the base JNDI environment template to use when acquiring LDAP connections.
- */
- @SuppressWarnings({"unchecked"})
- public void setEnvironment(Map env) {
- this.environment = env;
- }
-
- /**
- * Returns the environment property value bound under the specified key.
- *
- * @param name the name of the environment property
- * @return the property value or {@code null} if the value has not been set.
- */
- private Object getEnvironmentProperty(String name) {
- return this.environment.get(name);
- }
-
- /**
- * Will apply the value to the environment attribute if and only if the value is not null or empty. If it is
- * null or empty, the corresponding environment attribute will be removed.
- *
- * @param name the environment property key
- * @param value the environment property value. A null/empty value will trigger removal.
- */
- private void setEnvironmentProperty(String name, String value) {
- if (StringUtils.hasText(value)) {
- this.environment.put(name, value);
- } else {
- this.environment.remove(name);
- }
- }
-
- /**
- * Returns whether or not connection pooling should be used when possible and appropriate. This property is NOT
- * backed by the {@link #getEnvironment() environment template} like most other properties in this class. It
- * is a flag to indicate that pooling is preferred. The default value is {@code true}.
- *
- * However, pooling will only actually be enabled if this property is {@code true} and the connection
- * being created is for the {@link #getSystemUsername() systemUsername} user. Connection pooling is not used for
- * general authentication attempts by application end-users because the probability of re-use for that same
- * user-specific connection after an authentication attempt is extremely low.
- *
- * If this attribute is {@code true} and it has been determined that the connection is being made with the
- * {@link #getSystemUsername() systemUsername}, the
- * {@link #getLdapContext(Object, Object)} implementation will set the Sun/Oracle-specific
- * {@code com.sun.jndi.ldap.connect.pool} environment property to "{@code true}". This means setting
- * this property is only likely to work if using the Sun/Oracle default context factory class (i.e. not using
- * a custom {@link #getContextFactoryClassName() contextFactoryClassName}).
- *
- * @return whether or not connection pooling should be used when possible and appropriate
- */
- public boolean isPoolingEnabled() {
- return poolingEnabled;
- }
-
- /**
- * Sets whether or not connection pooling should be used when possible and appropriate. This property is NOT
- * a wrapper to the {@link #getEnvironment() environment template} like most other properties in this class. It
- * is a flag to indicate that pooling is preferred. The default value is {@code true}.
- *
- * However, pooling will only actually be enabled if this property is {@code true} and the connection
- * being created is for the {@link #getSystemUsername() systemUsername} user. Connection pooling is not used for
- * general authentication attempts by application end-users because the probability of re-use for that same
- * user-specific connection after an authentication attempt is extremely low.
- *
- * If this attribute is {@code true} and it has been determined that the connection is being made with the
- * {@link #getSystemUsername() systemUsername}, the
- * {@link #getLdapContext(Object, Object)} implementation will set the Sun/Oracle-specific
- * {@code com.sun.jndi.ldap.connect.pool} environment property to "{@code true}". This means setting
- * this property is only likely to work if using the Sun/Oracle default context factory class (i.e. not using
- * a custom {@link #getContextFactoryClassName() contextFactoryClassName}).
- *
- * @param poolingEnabled whether or not connection pooling should be used when possible and appropriate
- */
- public void setPoolingEnabled(boolean poolingEnabled) {
- this.poolingEnabled = poolingEnabled;
- }
-
- /**
- * Sets the LDAP referral behavior when creating a connection. Defaults to {@code follow}. See the Sun/Oracle LDAP
- * referral documentation for more.
- *
- * @param referral the referral property.
- * @see Referrals in JNDI
- */
- public void setReferral(String referral) {
- setEnvironmentProperty(Context.REFERRAL, referral);
- }
-
- /**
- * Returns the LDAP referral behavior when creating a connection. Defaults to {@code follow}.
- * See the Sun/Oracle LDAP
- * referral documentation for more.
- *
- * @return the LDAP referral behavior when creating a connection.
- * @see Referrals in JNDI
- */
- public String getReferral() {
- return (String) getEnvironmentProperty(Context.REFERRAL);
- }
-
- /**
- * The LDAP url to connect to. (e.g. ldap://<ldapDirectoryHostname>:<port>). This must be configured.
- *
- * @param url the LDAP url to connect to. (e.g. ldap://<ldapDirectoryHostname>:<port>)
- */
- public void setUrl(String url) {
- setEnvironmentProperty(Context.PROVIDER_URL, url);
- }
-
- /**
- * Returns the LDAP url to connect to. (e.g. ldap://<ldapDirectoryHostname>:<port>).
- * This must be configured.
- *
- * @return the LDAP url to connect to. (e.g. ldap://<ldapDirectoryHostname>:<port>)
- */
- public String getUrl() {
- return (String) getEnvironmentProperty(Context.PROVIDER_URL);
- }
-
- /**
- * Sets the password of the {@link #setSystemUsername(String) systemUsername} that will be used when creating an
- * LDAP connection used for authorization queries.
- *
- * Note that setting this property is not required if the calling LDAP Realm does not perform authorization
- * checks.
- *
- * @param systemPassword the password of the {@link #setSystemUsername(String) systemUsername} that will be used
- * when creating an LDAP connection used for authorization queries.
- */
- public void setSystemPassword(String systemPassword) {
- this.systemPassword = systemPassword;
- }
-
- /**
- * Returns the password of the {@link #setSystemUsername(String) systemUsername} that will be used when creating an
- * LDAP connection used for authorization queries.
- *
- * Note that setting this property is not required if the calling LDAP Realm does not perform authorization
- * checks.
- *
- * @return the password of the {@link #setSystemUsername(String) systemUsername} that will be used when creating an
- * LDAP connection used for authorization queries.
- */
- public String getSystemPassword() {
- return this.systemPassword;
- }
-
- /**
- * Sets the system username that will be used when creating an LDAP connection used for authorization queries.
- * The user must have the ability to query for authorization data for any application user.
- *
- * Note that setting this property is not required if the calling LDAP Realm does not perform authorization
- * checks.
- *
- * @param systemUsername the system username that will be used when creating an LDAP connection used for
- * authorization queries.
- */
- public void setSystemUsername(String systemUsername) {
- this.systemUsername = systemUsername;
- }
-
- /**
- * Returns the system username that will be used when creating an LDAP connection used for authorization queries.
- * The user must have the ability to query for authorization data for any application user.
- *
- * Note that setting this property is not required if the calling LDAP Realm does not perform authorization
- * checks.
- *
- * @return the system username that will be used when creating an LDAP connection used for authorization queries.
- */
- public String getSystemUsername() {
- return systemUsername;
- }
-
- /*--------------------------------------------
- | M E T H O D S |
- ============================================*/
-
- /**
- * This implementation delegates to {@link #getLdapContext(Object, Object)} using the
- * {@link #getSystemUsername() systemUsername} and {@link #getSystemPassword() systemPassword} properties as
- * arguments.
- *
- * @return the system LdapContext
- * @throws NamingException if there is a problem connecting to the LDAP directory
- */
- public LdapContext getSystemLdapContext() throws NamingException {
- return getLdapContext(getSystemUsername(), getSystemPassword());
- }
-
- /**
- * Returns {@code true} if LDAP connection pooling should be used when acquiring a connection based on the specified
- * account principal, {@code false} otherwise.
- *
- * This implementation returns {@code true} only if {@link #isPoolingEnabled()} and the principal equals the
- * {@link #getSystemUsername()}. The reasoning behind this is that connection pooling is not desirable for
- * general authentication attempts by application end-users because the probability of re-use for that same
- * user-specific connection after an authentication attempt is extremely low.
- *
- * @param principal the principal under which the connection will be made
- * @return {@code true} if LDAP connection pooling should be used when acquiring a connection based on the specified
- * account principal, {@code false} otherwise.
- */
- protected boolean isPoolingConnections(Object principal) {
- return isPoolingEnabled() && principal != null && principal.equals(getSystemUsername());
- }
-
- /**
- * This implementation returns an LdapContext based on the configured JNDI/LDAP environment configuration.
- * The environment (Map) used at runtime is created by merging the default/configured
- * {@link #getEnvironment() environment template} with some runtime values as necessary (e.g. a principal and
- * credential available at runtime only).
- *
- * After the merged Map instance is created, the LdapContext connection is
- * {@link #createLdapContext(java.util.Hashtable) created} and returned.
- *
- * @param principal the principal to use when acquiring a connection to the LDAP directory
- * @param credentials the credentials (password, X.509 certificate, etc.) to use when acquiring a connection to the
- * LDAP directory
- * @return the acquired {@code LdapContext} connection bound using the specified principal and credentials.
- * @throws NamingException
- * @throws IllegalStateException
- */
- public LdapContext getLdapContext(Object principal, Object credentials) throws NamingException,
- IllegalStateException {
-
- String url = getUrl();
- if (url == null) {
- throw new IllegalStateException("An LDAP URL must be specified of the form ldap://:");
- }
-
- //copy the environment template into the runtime instance that will be further edited based on
- //the method arguments and other class attributes.
- Hashtable env = new Hashtable(this.environment);
-
- Object authcMech = getAuthenticationMechanism();
- if (authcMech == null && (principal != null || credentials != null)) {
- //authenticationMechanism has not been set, but either a principal and/or credentials were
- //supplied, indicating that at least a 'simple' authentication attempt is indeed occurring - the Shiro
- //end-user just didn't configure it explicitly. So we set it to be 'simple' here as a convenience;
- //the Sun provider implementation already does this same logic, but by repeating that logic here, we ensure
- //this convenience exists regardless of provider implementation):
- env.put(Context.SECURITY_AUTHENTICATION, SIMPLE_AUTHENTICATION_MECHANISM_NAME);
- }
- if (principal != null) {
- env.put(Context.SECURITY_PRINCIPAL, principal);
- }
- if (credentials != null) {
- env.put(Context.SECURITY_CREDENTIALS, credentials);
- }
-
- boolean pooling = isPoolingConnections(principal);
- if (pooling) {
- env.put(SUN_CONNECTION_POOLING_PROPERTY, "true");
- }
-
- if (log.isDebugEnabled()) {
- log.debug("Initializing LDAP context using URL [{}] and principal [{}] with pooling {}",
- new Object[]{url, principal, (pooling ? "enabled" : "disabled")});
- }
-
- // validate the config before creating the context
- validateAuthenticationInfo(env);
-
- return createLdapContext(env);
- }
-
- /**
- * Creates and returns a new {@link javax.naming.ldap.InitialLdapContext} instance. This method exists primarily
- * to support testing where a mock LdapContext can be returned instead of actually creating a connection, but
- * subclasses are free to provide a different implementation if necessary.
- *
- * @param env the JNDI environment settings used to create the LDAP connection
- * @return an LdapConnection
- * @throws NamingException if a problem occurs creating the connection
- */
- protected LdapContext createLdapContext(Hashtable env) throws NamingException {
- return new InitialLdapContext(env, null);
- }
-
-
- /**
- * Validates the configuration in the JNDI environment settings and throws an exception if a problem
- * exists.
- *
- * This implementation will throw a {@link AuthenticationException} if the authentication mechanism is set to
- * 'simple', the principal is non-empty, and the credentials are empty (as per
- * rfc4513 section-5.1.2).
- *
- * @param environment the JNDI environment settings to be validated
- * @throws AuthenticationException if a configuration problem is detected
- */
- protected void validateAuthenticationInfo(Hashtable environment)
- throws AuthenticationException
- {
- // validate when using Simple auth both principal and credentials are set
- if(SIMPLE_AUTHENTICATION_MECHANISM_NAME.equals(environment.get(Context.SECURITY_AUTHENTICATION))) {
-
- // only validate credentials if we have a non-empty principal
- if( environment.get(Context.SECURITY_PRINCIPAL) != null &&
- StringUtils.hasText( String.valueOf( environment.get(Context.SECURITY_PRINCIPAL) ))) {
-
- Object credentials = environment.get(Context.SECURITY_CREDENTIALS);
-
- // from the FAQ, we need to check for empty credentials:
- // http://docs.oracle.com/javase/tutorial/jndi/ldap/faq.html
- if( credentials == null ||
- (credentials instanceof byte[] && ((byte[])credentials).length <= 0) || // empty byte[]
- (credentials instanceof char[] && ((char[])credentials).length <= 0) || // empty char[]
- (String.class.isInstance(credentials) && !StringUtils.hasText(String.valueOf(credentials)))) {
-
- throw new javax.naming.AuthenticationException("LDAP Simple authentication requires both a "
- + "principal and credentials.");
- }
- }
- }
- }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.realm.ldap;
+
+import org.apache.shiro.lang.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.AuthenticationException;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapContext;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * {@link LdapContextFactory} implementation using the default Sun/Oracle JNDI Ldap API, utilizing JNDI
+ * environment properties and an {@link javax.naming.InitialContext}.
+ *
Configuration
+ * This class basically wraps a default template JNDI environment properties Map. This properties map is the base
+ * configuration template used to acquire JNDI {@link LdapContext} connections at runtime. The
+ * {@link #getLdapContext(Object, Object)} method implementation merges this default template with other properties
+ * accessible at runtime only (for example per-method principals and credentials). The constructed runtime map is the
+ * one used to acquire the {@link LdapContext}.
+ *
+ * The template can be configured directly via the {@link #getEnvironment()}/{@link #setEnvironment(java.util.Map)}
+ * properties directly if necessary, but it is usually more convenient to use the supporting wrapper get/set methods
+ * for various environment properties. These wrapper methods interact with the environment
+ * template on your behalf, leaving your configuration cleaner and easier to understand.
+ *
+ * For example, consider the following two identical configurations:
+ *
+ * As you can see, the 2nd configuration block is a little more difficult to read and also requires knowledge
+ * of the underlying JNDI Context property keys. The first is easier to read and understand.
+ *
+ * Note that occasionally it will be necessary to use the latter configuration style to set environment properties
+ * where no corresponding wrapper method exists. In this case, the hybrid approach is still a little easier to read.
+ * For example:
+ *
+ *
+ * @since 1.1
+ */
+public class JndiLdapContextFactory implements LdapContextFactory {
+
+ /*-------------------------------------------
+ | C O N S T A N T S |
+ ===========================================*/
+ /**
+ * The Sun LDAP property used to enable connection pooling. This is used in the default implementation
+ * to enable LDAP connection pooling.
+ */
+ protected static final String SUN_CONNECTION_POOLING_PROPERTY = "com.sun.jndi.ldap.connect.pool";
+ protected static final String DEFAULT_CONTEXT_FACTORY_CLASS_NAME = "com.sun.jndi.ldap.LdapCtxFactory";
+ protected static final String SIMPLE_AUTHENTICATION_MECHANISM_NAME = "simple";
+ protected static final String DEFAULT_REFERRAL = "follow";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JndiLdapContextFactory.class);
+
+ /*-------------------------------------------
+ | I N S T A N C E V A R I A B L E S |
+ ============================================*/
+ private Map environment;
+ private boolean poolingEnabled;
+ private String systemPassword;
+ private String systemUsername;
+
+ /*-------------------------------------------
+ | C O N S T R U C T O R S |
+ ===========================================*/
+
+ /**
+ * Default no-argument constructor that initializes the backing {@link #getEnvironment() environment template} with
+ * the {@link #setContextFactoryClassName(String) contextFactoryClassName} equal to
+ * {@code com.sun.jndi.ldap.LdapCtxFactory} (the Sun/Oracle default) and the default
+ * {@link #setReferral(String) referral} behavior to {@code follow}.
+ */
+ public JndiLdapContextFactory() {
+ this.environment = new HashMap();
+ setContextFactoryClassName(DEFAULT_CONTEXT_FACTORY_CLASS_NAME);
+ setReferral(DEFAULT_REFERRAL);
+ poolingEnabled = true;
+ }
+
+ /*-------------------------------------------
+ | A C C E S S O R S / M O D I F I E R S |
+ ===========================================*/
+
+ /**
+ * Sets the type of LDAP authentication mechanism to use when connecting to the LDAP server.
+ * This is a wrapper method for setting the JNDI {@link #getEnvironment() environment template}'s
+ * {@link Context#SECURITY_AUTHENTICATION} property.
+ *
+ * "none" (i.e. anonymous) and "simple" authentications are supported automatically and don't need to be configured
+ * via this property. However, if you require a different mechanism, such as a SASL or External mechanism, you
+ * must configure that explicitly via this property. See the
+ * JNDI LDAP
+ * Authentication Mechanisms for more information.
+ *
+ * @param authenticationMechanism the type of LDAP authentication to perform.
+ * @see
+ * http://download-llnw.oracle.com/javase/tutorial/jndi/ldap/auth_mechs.html
+ */
+ public void setAuthenticationMechanism(String authenticationMechanism) {
+ setEnvironmentProperty(Context.SECURITY_AUTHENTICATION, authenticationMechanism);
+ }
+
+ /**
+ * Returns the type of LDAP authentication mechanism to use when connecting to the LDAP server.
+ * This is a wrapper method for getting the JNDI {@link #getEnvironment() environment template}'s
+ * {@link Context#SECURITY_AUTHENTICATION} property.
+ *
+ * If this property remains un-configured (i.e. {@code null} indicating the
+ * {@link #setAuthenticationMechanism(String)} method wasn't used), this indicates that the default JNDI
+ * "none" (anonymous) and "simple" authentications are supported automatically. Any non-null value returned
+ * represents an explicitly configured mechanism (e.g. a SASL or external mechanism). See the
+ * JNDI LDAP
+ * Authentication Mechanisms for more information.
+ *
+ * @return the type of LDAP authentication mechanism to use when connecting to the LDAP server.
+ * @see
+ * http://download-llnw.oracle.com/javase/tutorial/jndi/ldap/auth_mechs.html
+ */
+ public String getAuthenticationMechanism() {
+ return (String) getEnvironmentProperty(Context.SECURITY_AUTHENTICATION);
+ }
+
+ /**
+ * The name of the ContextFactory class to use. This defaults to the SUN LDAP JNDI implementation
+ * but can be overridden to use custom LDAP factories.
+ *
+ * This is a wrapper method for setting the JNDI environment's {@link Context#INITIAL_CONTEXT_FACTORY} property.
+ *
+ * @param contextFactoryClassName the context factory that should be used.
+ */
+ public void setContextFactoryClassName(String contextFactoryClassName) {
+ setEnvironmentProperty(Context.INITIAL_CONTEXT_FACTORY, contextFactoryClassName);
+ }
+
+ /**
+ * Sets the name of the ContextFactory class to use. This defaults to the SUN LDAP JNDI implementation
+ * but can be overridden to use custom LDAP factories.
+ *
+ * This is a wrapper method for getting the JNDI environment's {@link Context#INITIAL_CONTEXT_FACTORY} property.
+ *
+ * @return the name of the ContextFactory class to use.
+ */
+ public String getContextFactoryClassName() {
+ return (String) getEnvironmentProperty(Context.INITIAL_CONTEXT_FACTORY);
+ }
+
+ /**
+ * Returns the base JNDI environment template to use when acquiring an LDAP connection (an {@link LdapContext}).
+ * This property is the base configuration template to use for all connections. This template is then
+ * merged with appropriate runtime values as necessary in the
+ * {@link #getLdapContext(Object, Object)} implementation. The merged environment instance is what is used to
+ * acquire the {@link LdapContext} at runtime.
+ *
+ * Most other get/set methods in this class act as thin proxy wrappers that interact with this property. The
+ * benefit of using them is you have an easier-to-use configuration mechanism compared to setting map properties
+ * based on JNDI context keys.
+ *
+ * @return the base JNDI environment template to use when acquiring an LDAP connection (an {@link LdapContext})
+ */
+ public Map getEnvironment() {
+ return this.environment;
+ }
+
+ /**
+ * Sets the base JNDI environment template to use when acquiring LDAP connections. It is typically more common
+ * to use the other get/set methods in this class to set individual environment settings rather than use
+ * this method, but it is available for advanced users that want full control over the base JNDI environment
+ * settings.
+ *
+ * Note that this template only represents the base/default environment settings. It is then merged with
+ * appropriate runtime values as necessary in the {@link #getLdapContext(Object, Object)} implementation.
+ * The merged environment instance is what is used to acquire the connection ({@link LdapContext}) at runtime.
+ *
+ * @param env the base JNDI environment template to use when acquiring LDAP connections.
+ */
+ @SuppressWarnings({"unchecked"})
+ public void setEnvironment(Map env) {
+ this.environment = env;
+ }
+
+ /**
+ * Returns the environment property value bound under the specified key.
+ *
+ * @param name the name of the environment property
+ * @return the property value or {@code null} if the value has not been set.
+ */
+ private Object getEnvironmentProperty(String name) {
+ return this.environment.get(name);
+ }
+
+ /**
+ * Will apply the value to the environment attribute if and only if the value is not null or empty. If it is
+ * null or empty, the corresponding environment attribute will be removed.
+ *
+ * @param name the environment property key
+ * @param value the environment property value. A null/empty value will trigger removal.
+ */
+ private void setEnvironmentProperty(String name, String value) {
+ if (StringUtils.hasText(value)) {
+ this.environment.put(name, value);
+ } else {
+ this.environment.remove(name);
+ }
+ }
+
+ /**
+ * Returns whether or not connection pooling should be used when possible and appropriate. This property is NOT
+ * backed by the {@link #getEnvironment() environment template} like most other properties in this class. It
+ * is a flag to indicate that pooling is preferred. The default value is {@code true}.
+ *
+ * However, pooling will only actually be enabled if this property is {@code true} and the connection
+ * being created is for the {@link #getSystemUsername() systemUsername} user. Connection pooling is not used for
+ * general authentication attempts by application end-users because the probability of re-use for that same
+ * user-specific connection after an authentication attempt is extremely low.
+ *
+ * If this attribute is {@code true} and it has been determined that the connection is being made with the
+ * {@link #getSystemUsername() systemUsername}, the
+ * {@link #getLdapContext(Object, Object)} implementation will set the Sun/Oracle-specific
+ * {@code com.sun.jndi.ldap.connect.pool} environment property to "{@code true}". This means setting
+ * this property is only likely to work if using the Sun/Oracle default context factory class (i.e. not using
+ * a custom {@link #getContextFactoryClassName() contextFactoryClassName}).
+ *
+ * @return whether or not connection pooling should be used when possible and appropriate
+ */
+ public boolean isPoolingEnabled() {
+ return poolingEnabled;
+ }
+
+ /**
+ * Sets whether or not connection pooling should be used when possible and appropriate. This property is NOT
+ * a wrapper to the {@link #getEnvironment() environment template} like most other properties in this class. It
+ * is a flag to indicate that pooling is preferred. The default value is {@code true}.
+ *
+ * However, pooling will only actually be enabled if this property is {@code true} and the connection
+ * being created is for the {@link #getSystemUsername() systemUsername} user. Connection pooling is not used for
+ * general authentication attempts by application end-users because the probability of re-use for that same
+ * user-specific connection after an authentication attempt is extremely low.
+ *
+ * If this attribute is {@code true} and it has been determined that the connection is being made with the
+ * {@link #getSystemUsername() systemUsername}, the
+ * {@link #getLdapContext(Object, Object)} implementation will set the Sun/Oracle-specific
+ * {@code com.sun.jndi.ldap.connect.pool} environment property to "{@code true}". This means setting
+ * this property is only likely to work if using the Sun/Oracle default context factory class (i.e. not using
+ * a custom {@link #getContextFactoryClassName() contextFactoryClassName}).
+ *
+ * @param poolingEnabled whether or not connection pooling should be used when possible and appropriate
+ */
+ public void setPoolingEnabled(boolean poolingEnabled) {
+ this.poolingEnabled = poolingEnabled;
+ }
+
+ /**
+ * Sets the LDAP referral behavior when creating a connection. Defaults to {@code follow}. See the Sun/Oracle LDAP
+ * referral documentation for more.
+ *
+ * @param referral the referral property.
+ * @see Referrals in JNDI
+ */
+ public void setReferral(String referral) {
+ setEnvironmentProperty(Context.REFERRAL, referral);
+ }
+
+ /**
+ * Returns the LDAP referral behavior when creating a connection. Defaults to {@code follow}.
+ * See the Sun/Oracle LDAP
+ * referral documentation for more.
+ *
+ * @return the LDAP referral behavior when creating a connection.
+ * @see Referrals in JNDI
+ */
+ public String getReferral() {
+ return (String) getEnvironmentProperty(Context.REFERRAL);
+ }
+
+ /**
+ * The LDAP url to connect to. (e.g. ldap://<ldapDirectoryHostname>:<port>). This must be configured.
+ *
+ * @param url the LDAP url to connect to. (e.g. ldap://<ldapDirectoryHostname>:<port>)
+ */
+ public void setUrl(String url) {
+ setEnvironmentProperty(Context.PROVIDER_URL, url);
+ }
+
+ /**
+ * Returns the LDAP url to connect to. (e.g. ldap://<ldapDirectoryHostname>:<port>).
+ * This must be configured.
+ *
+ * @return the LDAP url to connect to. (e.g. ldap://<ldapDirectoryHostname>:<port>)
+ */
+ public String getUrl() {
+ return (String) getEnvironmentProperty(Context.PROVIDER_URL);
+ }
+
+ /**
+ * Sets the password of the {@link #setSystemUsername(String) systemUsername} that will be used when creating an
+ * LDAP connection used for authorization queries.
+ *
+ * Note that setting this property is not required if the calling LDAP Realm does not perform authorization
+ * checks.
+ *
+ * @param systemPassword the password of the {@link #setSystemUsername(String) systemUsername} that will be used
+ * when creating an LDAP connection used for authorization queries.
+ */
+ public void setSystemPassword(String systemPassword) {
+ this.systemPassword = systemPassword;
+ }
+
+ /**
+ * Returns the password of the {@link #setSystemUsername(String) systemUsername} that will be used when creating an
+ * LDAP connection used for authorization queries.
+ *
+ * Note that setting this property is not required if the calling LDAP Realm does not perform authorization
+ * checks.
+ *
+ * @return the password of the {@link #setSystemUsername(String) systemUsername} that will be used when creating an
+ * LDAP connection used for authorization queries.
+ */
+ public String getSystemPassword() {
+ return this.systemPassword;
+ }
+
+ /**
+ * Sets the system username that will be used when creating an LDAP connection used for authorization queries.
+ * The user must have the ability to query for authorization data for any application user.
+ *
+ * Note that setting this property is not required if the calling LDAP Realm does not perform authorization
+ * checks.
+ *
+ * @param systemUsername the system username that will be used when creating an LDAP connection used for
+ * authorization queries.
+ */
+ public void setSystemUsername(String systemUsername) {
+ this.systemUsername = systemUsername;
+ }
+
+ /**
+ * Returns the system username that will be used when creating an LDAP connection used for authorization queries.
+ * The user must have the ability to query for authorization data for any application user.
+ *
+ * Note that setting this property is not required if the calling LDAP Realm does not perform authorization
+ * checks.
+ *
+ * @return the system username that will be used when creating an LDAP connection used for authorization queries.
+ */
+ public String getSystemUsername() {
+ return systemUsername;
+ }
+
+ /*--------------------------------------------
+ | M E T H O D S |
+ ============================================*/
+
+ /**
+ * This implementation delegates to {@link #getLdapContext(Object, Object)} using the
+ * {@link #getSystemUsername() systemUsername} and {@link #getSystemPassword() systemPassword} properties as
+ * arguments.
+ *
+ * @return the system LdapContext
+ * @throws NamingException if there is a problem connecting to the LDAP directory
+ */
+ public LdapContext getSystemLdapContext() throws NamingException {
+ return getLdapContext(getSystemUsername(), getSystemPassword());
+ }
+
+ /**
+ * Returns {@code true} if LDAP connection pooling should be used when acquiring a connection based on the specified
+ * account principal, {@code false} otherwise.
+ *
+ * This implementation returns {@code true} only if {@link #isPoolingEnabled()} and the principal equals the
+ * {@link #getSystemUsername()}. The reasoning behind this is that connection pooling is not desirable for
+ * general authentication attempts by application end-users because the probability of re-use for that same
+ * user-specific connection after an authentication attempt is extremely low.
+ *
+ * @param principal the principal under which the connection will be made
+ * @return {@code true} if LDAP connection pooling should be used when acquiring a connection based on the specified
+ * account principal, {@code false} otherwise.
+ */
+ protected boolean isPoolingConnections(Object principal) {
+ return isPoolingEnabled() && principal != null && principal.equals(getSystemUsername());
+ }
+
+ /**
+ * This implementation returns an LdapContext based on the configured JNDI/LDAP environment configuration.
+ * The environment (Map) used at runtime is created by merging the default/configured
+ * {@link #getEnvironment() environment template} with some runtime values as necessary (e.g. a principal and
+ * credential available at runtime only).
+ *
+ * After the merged Map instance is created, the LdapContext connection is
+ * {@link #createLdapContext(java.util.Hashtable) created} and returned.
+ *
+ * @param principal the principal to use when acquiring a connection to the LDAP directory
+ * @param credentials the credentials (password, X.509 certificate, etc.) to use when acquiring a connection to the
+ * LDAP directory
+ * @return the acquired {@code LdapContext} connection bound using the specified principal and credentials.
+ * @throws NamingException
+ * @throws IllegalStateException
+ */
+ public LdapContext getLdapContext(Object principal, Object credentials) throws NamingException,
+ IllegalStateException {
+
+ String url = getUrl();
+ if (url == null) {
+ throw new IllegalStateException("An LDAP URL must be specified of the form ldap://:");
+ }
+
+ //copy the environment template into the runtime instance that will be further edited based on
+ //the method arguments and other class attributes.
+ Hashtable env = new Hashtable(this.environment);
+
+ Object authcMech = getAuthenticationMechanism();
+ if (authcMech == null && (principal != null || credentials != null)) {
+ //authenticationMechanism has not been set, but either a principal and/or credentials were
+ //supplied, indicating that at least a 'simple' authentication attempt is indeed occurring - the Shiro
+ //end-user just didn't configure it explicitly. So we set it to be 'simple' here as a convenience;
+ //the Sun provider implementation already does this same logic, but by repeating that logic here, we ensure
+ //this convenience exists regardless of provider implementation):
+ env.put(Context.SECURITY_AUTHENTICATION, SIMPLE_AUTHENTICATION_MECHANISM_NAME);
+ }
+ if (principal != null) {
+ env.put(Context.SECURITY_PRINCIPAL, principal);
+ }
+ if (credentials != null) {
+ env.put(Context.SECURITY_CREDENTIALS, credentials);
+ }
+
+ boolean pooling = isPoolingConnections(principal);
+ if (pooling) {
+ env.put(SUN_CONNECTION_POOLING_PROPERTY, "true");
+ }
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Initializing LDAP context using URL [{}] and principal [{}] with pooling {}",
+ new Object[] {url, principal, (pooling ? "enabled" : "disabled")});
+ }
+
+ // validate the config before creating the context
+ validateAuthenticationInfo(env);
+
+ return createLdapContext(env);
+ }
+
+ /**
+ * Creates and returns a new {@link javax.naming.ldap.InitialLdapContext} instance. This method exists primarily
+ * to support testing where a mock LdapContext can be returned instead of actually creating a connection, but
+ * subclasses are free to provide a different implementation if necessary.
+ *
+ * @param env the JNDI environment settings used to create the LDAP connection
+ * @return an LdapConnection
+ * @throws NamingException if a problem occurs creating the connection
+ */
+ protected LdapContext createLdapContext(Hashtable env) throws NamingException {
+ return new InitialLdapContext(env, null);
+ }
+
+
+ /**
+ * Validates the configuration in the JNDI environment settings and throws an exception if a problem
+ * exists.
+ *
+ * This implementation will throw a {@link AuthenticationException} if the authentication mechanism is set to
+ * 'simple', the principal is non-empty, and the credentials are empty (as per
+ * rfc4513 section-5.1.2).
+ *
+ * @param environment the JNDI environment settings to be validated
+ * @throws AuthenticationException if a configuration problem is detected
+ */
+ @SuppressWarnings({"checkstyle:BooleanExpressionComplexity"})
+ protected void validateAuthenticationInfo(Hashtable environment)
+ throws AuthenticationException {
+ // validate when using Simple auth both principal and credentials are set
+ if (SIMPLE_AUTHENTICATION_MECHANISM_NAME.equals(environment.get(Context.SECURITY_AUTHENTICATION))) {
+
+ // only validate credentials if we have a non-empty principal
+ if (environment.get(Context.SECURITY_PRINCIPAL) != null
+ && StringUtils.hasText(String.valueOf(environment.get(Context.SECURITY_PRINCIPAL)))) {
+
+ Object credentials = environment.get(Context.SECURITY_CREDENTIALS);
+
+ // from the FAQ, we need to check for empty credentials:
+ // http://docs.oracle.com/javase/tutorial/jndi/ldap/faq.html
+ if (credentials == null
+ || (credentials instanceof byte[] && ((byte[]) credentials).length <= 0)
+ || (credentials instanceof char[] && ((char[]) credentials).length <= 0)
+ || (String.class.isInstance(credentials) && !StringUtils.hasText(String.valueOf(credentials)))) {
+
+ throw new javax.naming.AuthenticationException("LDAP Simple authentication requires both a "
+ + "principal and credentials.");
+ }
+ }
+ }
+ }
+
+}
diff --git a/core/src/main/java/org/apache/shiro/realm/ldap/JndiLdapRealm.java b/core/src/main/java/org/apache/shiro/realm/ldap/JndiLdapRealm.java
index 1c7fd54626..415c97fbe4 100644
--- a/core/src/main/java/org/apache/shiro/realm/ldap/JndiLdapRealm.java
+++ b/core/src/main/java/org/apache/shiro/realm/ldap/JndiLdapRealm.java
@@ -20,10 +20,10 @@
/**
* This class has been replaced with DefaultLdapRealm.
+ *
* @see DefaultLdapRealm
- * @deprecated Renamed to {@link DefaultLdapRealm}, this class will be removed prior to 2.0
* @since 1.1
- *
+ * @deprecated Renamed to {@link DefaultLdapRealm}, this class will be removed prior to 2.0
*/
public class JndiLdapRealm extends DefaultLdapRealm {
diff --git a/core/src/main/java/org/apache/shiro/realm/ldap/LdapContextFactory.java b/core/src/main/java/org/apache/shiro/realm/ldap/LdapContextFactory.java
index 632d3b6b51..6b69c025ff 100644
--- a/core/src/main/java/org/apache/shiro/realm/ldap/LdapContextFactory.java
+++ b/core/src/main/java/org/apache/shiro/realm/ldap/LdapContextFactory.java
@@ -34,7 +34,7 @@ public interface LdapContextFactory {
* anonymously if no system account is configured.
*
* @return a {@code LdapContext} bound by the system account, or bound anonymously if no system account
- * is configured.
+ * is configured.
* @throws javax.naming.NamingException if there is an error creating the context.
*/
LdapContext getSystemLdapContext() throws NamingException;
@@ -59,5 +59,5 @@ public interface LdapContextFactory {
* @since 1.1
*/
LdapContext getLdapContext(Object principal, Object credentials) throws NamingException;
-
+
}
diff --git a/core/src/main/java/org/apache/shiro/realm/ldap/LdapUtils.java b/core/src/main/java/org/apache/shiro/realm/ldap/LdapUtils.java
index 750b017f75..ba12a2a28f 100644
--- a/core/src/main/java/org/apache/shiro/realm/ldap/LdapUtils.java
+++ b/core/src/main/java/org/apache/shiro/realm/ldap/LdapUtils.java
@@ -40,7 +40,10 @@ public final class LdapUtils {
/**
* Private internal log instance.
*/
- private static final Logger log = LoggerFactory.getLogger(LdapUtils.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(LdapUtils.class);
+
+ private LdapUtils() {
+ }
/**
* Closes an LDAP context, logging any errors, but not throwing
@@ -54,7 +57,7 @@ public static void closeContext(LdapContext ctx) {
ctx.close();
}
} catch (NamingException e) {
- log.error("Exception while closing LDAP context. ", e);
+ LOGGER.error("Exception while closing LDAP context. ", e);
}
}
@@ -81,16 +84,18 @@ public static Collection getAllAttributeValues(Attribute attr) throws Na
return values;
}
- //added based on SHIRO-127, per Emmanuel's comment [1]
- // [1] https://issues.apache.org/jira/browse/SHIRO-127?focusedCommentId=12891380&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12891380
-
+ /**
+ * added based on SHIRO-127, per Emmanuel's comment [1]
+ * [1]
+ */
public static void closeEnumeration(NamingEnumeration ne) {
try {
if (ne != null) {
ne.close();
}
} catch (NamingException e) {
- log.error("Exception while closing NamingEnumeration: ", e);
+ LOGGER.error("Exception while closing NamingEnumeration: ", e);
}
}
diff --git a/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java b/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java
index 10b993ba9b..96b9ba32b8 100644
--- a/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java
+++ b/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java
@@ -44,13 +44,23 @@
*/
public class IniRealm extends TextConfigurationRealm {
+ /**
+ * users section name
+ */
public static final String USERS_SECTION_NAME = "users";
+ /**
+ * roles section name
+ */
public static final String ROLES_SECTION_NAME = "roles";
- private static transient final Logger log = LoggerFactory.getLogger(IniRealm.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(IniRealm.class);
private String resourcePath;
- private Ini ini; //reference added in 1.2 for SHIRO-322
+
+ /**
+ * reference added in 1.2 for SHIRO-322
+ */
+ private Ini ini;
public IniRealm() {
super();
@@ -107,7 +117,7 @@ public void setResourcePath(String resourcePath) {
/**
* Returns the Ini instance used to configure this realm. Provided for JavaBeans-style configuration of this
* realm, particularly useful in Dependency Injection environments.
- *
+ *
* @return the Ini instance which will be inspected to create accounts, groups and permissions for this realm.
*/
public Ini getIni() {
@@ -117,7 +127,7 @@ public Ini getIni() {
/**
* Sets the Ini instance used to configure this realm. Provided for JavaBeans-style configuration of this
* realm, particularly useful in Dependency Injection environments.
- *
+ *
* @param ini the Ini instance which will be inspected to create accounts, groups and permissions for this realm.
*/
public void setIni(Ini ini) {
@@ -130,38 +140,38 @@ protected void onInit() {
// This is an in-memory realm only - no need for an additional cache when we're already
// as memory-efficient as we can be.
-
+
Ini ini = getIni();
String resourcePath = getResourcePath();
-
+
if (!CollectionUtils.isEmpty(this.users) || !CollectionUtils.isEmpty(this.roles)) {
if (!CollectionUtils.isEmpty(ini)) {
- log.warn("Users or Roles are already populated. Configured Ini instance will be ignored.");
+ LOGGER.warn("Users or Roles are already populated. Configured Ini instance will be ignored.");
}
if (StringUtils.hasText(resourcePath)) {
- log.warn("Users or Roles are already populated. resourcePath '{}' will be ignored.", resourcePath);
+ LOGGER.warn("Users or Roles are already populated. resourcePath '{}' will be ignored.", resourcePath);
}
-
- log.debug("Instance is already populated with users or roles. No additional user/role population " +
- "will be performed.");
+
+ LOGGER.debug("Instance is already populated with users or roles. No additional user/role population "
+ + "will be performed.");
return;
}
-
+
if (CollectionUtils.isEmpty(ini)) {
- log.debug("No INI instance configuration present. Checking resourcePath...");
-
+ LOGGER.debug("No INI instance configuration present. Checking resourcePath...");
+
if (StringUtils.hasText(resourcePath)) {
- log.debug("Resource path {} defined. Creating INI instance.", resourcePath);
+ LOGGER.debug("Resource path {} defined. Creating INI instance.", resourcePath);
ini = Ini.fromResourcePath(resourcePath);
if (!CollectionUtils.isEmpty(ini)) {
setIni(ini);
}
}
}
-
+
if (CollectionUtils.isEmpty(ini)) {
- String msg = "Ini instance and/or resourcePath resulted in null or empty Ini configuration. Cannot " +
- "load account data.";
+ String msg = "Ini instance and/or resourcePath resulted in null or empty Ini configuration. Cannot "
+ + "load account data.";
throw new IllegalStateException(msg);
}
@@ -170,24 +180,24 @@ protected void onInit() {
private void processDefinitions(Ini ini) {
if (CollectionUtils.isEmpty(ini)) {
- log.warn("{} defined, but the ini instance is null or empty.", getClass().getSimpleName());
+ LOGGER.warn("{} defined, but the ini instance is null or empty.", getClass().getSimpleName());
return;
}
Ini.Section rolesSection = ini.getSection(ROLES_SECTION_NAME);
if (!CollectionUtils.isEmpty(rolesSection)) {
- log.debug("Discovered the [{}] section. Processing...", ROLES_SECTION_NAME);
+ LOGGER.debug("Discovered the [{}] section. Processing...", ROLES_SECTION_NAME);
processRoleDefinitions(rolesSection);
}
Ini.Section usersSection = ini.getSection(USERS_SECTION_NAME);
if (!CollectionUtils.isEmpty(usersSection)) {
- log.debug("Discovered the [{}] section. Processing...", USERS_SECTION_NAME);
+ LOGGER.debug("Discovered the [{}] section. Processing...", USERS_SECTION_NAME);
processUserDefinitions(usersSection);
} else {
- log.info("{} defined, but there is no [{}] section defined. This realm will not be populated with any " +
- "users and it is assumed that they will be populated programatically. Users must be defined " +
- "for this Realm instance to be useful.", getClass().getSimpleName(), USERS_SECTION_NAME);
+ LOGGER.info("{} defined, but there is no [{}] section defined. This realm will not be populated with any "
+ + "users and it is assumed that they will be populated programatically. Users must be defined "
+ + "for this Realm instance to be useful.", getClass().getSimpleName(), USERS_SECTION_NAME);
}
}
}
diff --git a/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java b/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java
index 3ced80f8ce..fc48083ea8 100644
--- a/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java
+++ b/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java
@@ -96,10 +96,10 @@ public class PropertiesRealm extends TextConfigurationRealm implements Destroyab
/*-------------------------------------------
| I N S T A N C E V A R I A B L E S |
============================================*/
- private static final Logger log = LoggerFactory.getLogger(PropertiesRealm.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesRealm.class);
- protected ExecutorService scheduler = null;
- protected boolean useXmlFormat = false;
+ protected ExecutorService scheduler;
+ protected boolean useXmlFormat;
protected String resourcePath = DEFAULT_RESOURCE_PATH;
protected long fileLastModified;
protected int reloadIntervalSeconds = DEFAULT_RELOAD_INTERVAL_SECONDS;
@@ -176,8 +176,8 @@ public void destroy() {
scheduler.shutdown();
}
} catch (Exception e) {
- if (log.isInfoEnabled()) {
- log.info("Unable to cleanly shutdown Scheduler. Ignoring (shutting down)...", e);
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("Unable to cleanly shutdown Scheduler. Ignoring (shutting down)...", e);
}
} finally {
scheduler = null;
@@ -187,7 +187,8 @@ public void destroy() {
protected void startReloadThread() {
if (this.reloadIntervalSeconds > 0) {
this.scheduler = Executors.newSingleThreadScheduledExecutor();
- ((ScheduledExecutorService) this.scheduler).scheduleAtFixedRate(this, reloadIntervalSeconds, reloadIntervalSeconds, TimeUnit.SECONDS);
+ ((ScheduledExecutorService) this.scheduler)
+ .scheduleAtFixedRate(this, reloadIntervalSeconds, reloadIntervalSeconds, TimeUnit.SECONDS);
}
}
@@ -195,20 +196,20 @@ public void run() {
try {
reloadPropertiesIfNecessary();
} catch (Exception e) {
- if (log.isErrorEnabled()) {
- log.error("Error while reloading property files for realm.", e);
+ if (LOGGER.isErrorEnabled()) {
+ LOGGER.error("Error while reloading property files for realm.", e);
}
}
}
private void loadProperties() {
if (resourcePath == null || resourcePath.length() == 0) {
- throw new IllegalStateException("The resourcePath property is not set. " +
- "It must be set prior to this realm being initialized.");
+ throw new IllegalStateException("The resourcePath property is not set. "
+ + "It must be set prior to this realm being initialized.");
}
- if (log.isDebugEnabled()) {
- log.debug("Loading user security information from file [" + resourcePath + "]...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Loading user security information from file [" + resourcePath + "]...");
}
Properties properties = loadProperties(resourcePath);
@@ -221,30 +222,30 @@ private Properties loadProperties(String resourcePath) {
InputStream is = null;
try {
- if (log.isDebugEnabled()) {
- log.debug("Opening input stream for path [" + resourcePath + "]...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Opening input stream for path [" + resourcePath + "]...");
}
is = ResourceUtils.getInputStreamForPath(resourcePath);
if (useXmlFormat) {
- if (log.isDebugEnabled()) {
- log.debug("Loading properties from path [" + resourcePath + "] in XML format...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Loading properties from path [" + resourcePath + "] in XML format...");
}
props.loadFromXML(is);
} else {
- if (log.isDebugEnabled()) {
- log.debug("Loading properties from path [" + resourcePath + "]...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Loading properties from path [" + resourcePath + "]...");
}
props.load(is);
}
} catch (IOException e) {
- throw new ShiroException("Error reading properties path [" + resourcePath + "]. " +
- "Initializing of the realm from this file failed.", e);
+ throw new ShiroException("Error reading properties path [" + resourcePath + "]. "
+ + "Initializing of the realm from this file failed.", e);
} finally {
ResourceUtils.close(is);
}
@@ -280,12 +281,12 @@ private boolean isFileModified() {
@SuppressWarnings("unchecked")
private void restart() {
if (resourcePath == null || resourcePath.length() == 0) {
- throw new IllegalStateException("The resourcePath property is not set. " +
- "It must be set prior to this realm being initialized.");
+ throw new IllegalStateException("The resourcePath property is not set. "
+ + "It must be set prior to this realm being initialized.");
}
- if (log.isDebugEnabled()) {
- log.debug("Loading user security information from file [" + resourcePath + "]...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Loading user security information from file [" + resourcePath + "]...");
}
try {
@@ -308,8 +309,8 @@ private void createRealmEntitiesFromProperties(Properties properties) {
String key = propNames.nextElement().trim();
String value = properties.getProperty(key).trim();
- if (log.isTraceEnabled()) {
- log.trace("Processing properties line - key: [" + key + "], value: [" + value + "].");
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("Processing properties line - key: [" + key + "], value: [" + value + "].");
}
if (isUsername(key)) {
@@ -319,8 +320,8 @@ private void createRealmEntitiesFromProperties(Properties properties) {
String rolename = getRolename(key);
roleDefs.append(rolename).append(" = ").append(value).append("\n");
} else {
- String msg = "Encountered unexpected key/value pair. All keys must be prefixed with either '" +
- USERNAME_PREFIX + "' or '" + ROLENAME_PREFIX + "'.";
+ String msg = "Encountered unexpected key/value pair. All keys must be prefixed with either '"
+ + USERNAME_PREFIX + "' or '" + ROLENAME_PREFIX + "'.";
throw new IllegalStateException(msg);
}
}
diff --git a/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java b/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java
index 8feb159929..c3880a4922 100644
--- a/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java
+++ b/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java
@@ -62,8 +62,8 @@ public TextConfigurationRealm() {
/**
* Will call 'processDefinitions' on startup.
*
- * @since 1.2
* @see SHIRO-223
+ * @since 1.2
*/
@Override
protected void onInit() {
@@ -148,7 +148,7 @@ protected void processRoleDefinitions(Map roleDefs) {
if (roleDefs == null || roleDefs.isEmpty()) {
return;
}
- for (Map.Entry entry : roleDefs.entrySet()) {
+ for (Map.Entry entry : roleDefs.entrySet()) {
String rolename = entry.getKey();
String value = entry.getValue();
@@ -178,7 +178,7 @@ protected void processUserDefinitions(Map userDefs) {
if (userDefs == null || userDefs.isEmpty()) {
return;
}
- for (Map.Entry entry : userDefs.entrySet()) {
+ for (Map.Entry entry : userDefs.entrySet()) {
String username = entry.getKey();
String value = entry.getValue();
diff --git a/core/src/main/java/org/apache/shiro/session/Session.java b/core/src/main/java/org/apache/shiro/session/Session.java
index f91d224003..109dc69129 100644
--- a/core/src/main/java/org/apache/shiro/session/Session.java
+++ b/core/src/main/java/org/apache/shiro/session/Session.java
@@ -104,7 +104,7 @@ public interface Session {
* if the host is unknown.
*
* @return the host name or IP string of the host that originated this session, or {@code null}
- * if the host address is unknown.
+ * if the host address is unknown.
*/
String getHost();
@@ -149,7 +149,8 @@ public interface Session {
* It is common for a {@code Subject} implementation to retain authentication state in the
* {@code Session}. If the session
* is explicitly stopped by application code by calling this method directly, it could clear out any
- * authentication state that might exist, thereby effectively removing the "authenticated" state of the {@code Subject}.
+ * authentication state that might exist, thereby effectively removing
+ * the "authenticated" state of the {@code Subject}.
*
* As such, you might consider {@link org.apache.shiro.subject.Subject#logout logging-out} the 'owning'
* {@code Subject} instead of manually calling this method, as a log out is expected to stop the
@@ -164,7 +165,7 @@ public interface Session {
* attributes, this returns an empty collection.
*
* @return the keys of all attributes stored under this session, or an empty collection if
- * there are no session attributes.
+ * there are no session attributes.
* @throws InvalidSessionException if this session has stopped or expired prior to calling this method.
* @since 0.2
*/
@@ -176,7 +177,7 @@ public interface Session {
*
* @param key the unique name of the object bound to this session
* @return the object bound under the specified {@code key} name or {@code null} if there is
- * no object bound under that name.
+ * no object bound under that name.
* @throws InvalidSessionException if this session has stopped or expired prior to calling
* this method.
*/
@@ -202,7 +203,7 @@ public interface Session {
*
* @param key the name uniquely identifying the object to remove
* @return the object removed or {@code null} if there was no object bound under the name
- * {@code key}.
+ * {@code key}.
* @throws InvalidSessionException if this session has stopped or expired prior to calling
* this method.
*/
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/AbstractNativeSessionManager.java b/core/src/main/java/org/apache/shiro/session/mgt/AbstractNativeSessionManager.java
index 86353bd63f..a172a01d03 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/AbstractNativeSessionManager.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/AbstractNativeSessionManager.java
@@ -42,9 +42,10 @@
*
* @since 1.0
*/
+@SuppressWarnings({"checkstyle:MethodCount"})
public abstract class AbstractNativeSessionManager extends AbstractSessionManager implements NativeSessionManager, EventBusAware {
- private static final Logger log = LoggerFactory.getLogger(AbstractSessionManager.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSessionManager.class);
private EventBus eventBus;
@@ -112,11 +113,11 @@ public Session start(SessionContext context) {
* @param context the initialization data that can be used by the implementation or underlying
* {@link SessionFactory} when instantiating the internal {@code Session} instance.
* @return the new {@code Session} instance.
- * @throws org.apache.shiro.authz.HostUnauthorizedException
- * if the system access control policy restricts access based
- * on client location/IP and the specified hostAddress hasn't been enabled.
- * @throws AuthorizationException if the system access control policy does not allow the currently executing
- * caller to start sessions.
+ * @throws org.apache.shiro.authz.HostUnauthorizedException if the system access control policy restricts access based
+ * on client location/IP and
+ * the specified hostAddress hasn't been enabled.
+ * @throws AuthorizationException if the system access control policy does not allow
+ * the currently executing caller to start sessions.
*/
protected abstract Session createSession(SessionContext context) throws AuthorizationException;
@@ -280,8 +281,8 @@ public boolean isValid(SessionKey key) {
public void stop(SessionKey key) throws InvalidSessionException {
Session session = lookupRequiredSession(key);
try {
- if (log.isDebugEnabled()) {
- log.debug("Stopping session with id [" + session.getId() + "]");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Stopping session with id [" + session.getId() + "]");
}
session.stop();
onStop(session, key);
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java b/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java
index 8991bbae31..45e57f3bac 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java
@@ -39,16 +39,14 @@
public abstract class AbstractValidatingSessionManager extends AbstractNativeSessionManager
implements ValidatingSessionManager, Destroyable {
- //TODO - complete JavaDoc
-
- private static final Logger log = LoggerFactory.getLogger(AbstractValidatingSessionManager.class);
-
/**
* The default interval at which sessions will be validated (1 hour);
* This can be overridden by calling {@link #setSessionValidationInterval(long)}
*/
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = MILLIS_PER_HOUR;
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractValidatingSessionManager.class);
+
protected boolean sessionValidationSchedulerEnabled;
/**
@@ -113,7 +111,7 @@ public long getSessionValidationInterval() {
protected final Session doGetSession(final SessionKey key) throws InvalidSessionException {
enableSessionValidationIfNecessary();
- log.trace("Attempting to retrieve session with key {}", key);
+ LOGGER.trace("Attempting to retrieve session with key {}", key);
Session s = retrieveSession(key);
if (s != null) {
@@ -151,7 +149,7 @@ protected void validate(Session session, SessionKey key) throws InvalidSessionEx
}
protected void onExpiration(Session s, ExpiredSessionException ese, SessionKey key) {
- log.trace("Session with id [{}] has expired.", s.getId());
+ LOGGER.trace("Session with id [{}] has expired.", s.getId());
try {
onExpiration(s);
notifyExpiration(s);
@@ -172,7 +170,7 @@ protected void onInvalidation(Session s, InvalidSessionException ise, SessionKey
onExpiration(s, (ExpiredSessionException) ise, key);
return;
}
- log.trace("Session with id [{}] is invalid.", s.getId());
+ LOGGER.trace("Session with id [{}] is invalid.", s.getId());
try {
onStop(s);
notifyStop(s);
@@ -185,10 +183,10 @@ protected void doValidate(Session session) throws InvalidSessionException {
if (session instanceof ValidatingSession) {
((ValidatingSession) session).validate();
} else {
- String msg = "The " + getClass().getName() + " implementation only supports validating " +
- "Session implementations of the " + ValidatingSession.class.getName() + " interface. " +
- "Please either implement this interface in your session implementation or override the " +
- AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation.";
+ String msg = "The " + getClass().getName() + " implementation only supports validating "
+ + "Session implementations of the " + ValidatingSession.class.getName() + " interface. "
+ + "Please either implement this interface in your session implementation or override the "
+ + AbstractValidatingSessionManager.class.getName() + ".doValidate(Session) method to perform validation.";
throw new IllegalStateException(msg);
}
}
@@ -209,13 +207,13 @@ protected long getTimeout(Session session) {
protected SessionValidationScheduler createSessionValidationScheduler() {
ExecutorServiceSessionValidationScheduler scheduler;
- if (log.isDebugEnabled()) {
- log.debug("No sessionValidationScheduler set. Attempting to create default instance.");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("No sessionValidationScheduler set. Attempting to create default instance.");
}
scheduler = new ExecutorServiceSessionValidationScheduler(this);
scheduler.setSessionValidationInterval(getSessionValidationInterval());
- if (log.isTraceEnabled()) {
- log.trace("Created default SessionValidationScheduler instance of type [" + scheduler.getClass().getName() + "].");
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("Created default SessionValidationScheduler instance of type [" + scheduler.getClass().getName() + "].");
}
return scheduler;
}
@@ -229,8 +227,8 @@ protected synchronized void enableSessionValidation() {
// it is possible that that a scheduler was already created and set via 'setSessionValidationScheduler()'
// but would not have been enabled/started yet
if (!scheduler.isEnabled()) {
- if (log.isInfoEnabled()) {
- log.info("Enabling session validation scheduler...");
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("Enabling session validation scheduler...");
}
scheduler.enableSessionValidation();
afterSessionValidationEnabled();
@@ -246,13 +244,13 @@ protected synchronized void disableSessionValidation() {
if (scheduler != null) {
try {
scheduler.disableSessionValidation();
- if (log.isInfoEnabled()) {
- log.info("Disabled session validation scheduler.");
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("Disabled session validation scheduler.");
}
} catch (Exception e) {
- if (log.isDebugEnabled()) {
+ if (LOGGER.isDebugEnabled()) {
String msg = "Unable to disable SessionValidationScheduler. Ignoring (shutting down)...";
- log.debug(msg, e);
+ LOGGER.debug(msg, e);
}
}
LifecycleUtils.destroy(scheduler);
@@ -271,8 +269,8 @@ public void destroy() {
* @see ValidatingSessionManager#validateSessions()
*/
public void validateSessions() {
- if (log.isInfoEnabled()) {
- log.info("Validating all active sessions...");
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("Validating all active sessions...");
}
int invalidCount = 0;
@@ -287,25 +285,25 @@ public void validateSessions() {
SessionKey key = new DefaultSessionKey(s.getId());
validate(s, key);
} catch (InvalidSessionException e) {
- if (log.isDebugEnabled()) {
+ if (LOGGER.isDebugEnabled()) {
boolean expired = (e instanceof ExpiredSessionException);
- String msg = "Invalidated session with id [" + s.getId() + "]" +
- (expired ? " (expired)" : " (stopped)");
- log.debug(msg);
+ String msg = "Invalidated session with id [" + s.getId() + "]"
+ + (expired ? " (expired)" : " (stopped)");
+ LOGGER.debug(msg);
}
invalidCount++;
}
}
}
- if (log.isInfoEnabled()) {
+ if (LOGGER.isInfoEnabled()) {
String msg = "Finished session validation.";
if (invalidCount > 0) {
msg += " [" + invalidCount + "] sessions were stopped.";
} else {
msg += " No sessions were stopped.";
}
- log.info(msg);
+ LOGGER.info(msg);
}
}
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java b/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java
index c7e40cfcd1..604a9de425 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java
@@ -40,13 +40,13 @@
*/
public class DefaultSessionManager extends AbstractValidatingSessionManager implements CacheManagerAware {
- //TODO - complete JavaDoc
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSessionManager.class);
- private static final Logger log = LoggerFactory.getLogger(DefaultSessionManager.class);
+ //todo - move SessionDAO up to AbstractValidatingSessionManager?
+ protected SessionDAO sessionDAO;
- private SessionFactory sessionFactory;
- protected SessionDAO sessionDAO; //todo - move SessionDAO up to AbstractValidatingSessionManager?
+ private SessionFactory sessionFactory;
private CacheManager cacheManager;
@@ -104,7 +104,7 @@ public void setSessionFactory(SessionFactory sessionFactory) {
* some other means (cron, quartz, etc.).
*
* @return {@code true} if sessions should be automatically deleted after they are discovered to be invalid,
- * {@code false} if invalid sessions will be manually deleted by some process external to Shiro's control.
+ * {@code false} if invalid sessions will be manually deleted by some process external to Shiro's control.
* @since 1.0
*/
public boolean isDeleteInvalidSessions() {
@@ -152,8 +152,8 @@ private void applyCacheManagerToSessionDAO() {
protected Session doCreateSession(SessionContext context) {
Session s = newSessionInstance(context);
- if (log.isTraceEnabled()) {
- log.trace("Creating session for host {}", s.getHost());
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("Creating session for host {}", s.getHost());
}
create(s);
return s;
@@ -171,8 +171,8 @@ protected Session newSessionInstance(SessionContext context) {
* @param session the Session instance to persist to the underlying EIS.
*/
protected void create(Session session) {
- if (log.isDebugEnabled()) {
- log.debug("Creating new EIS record for new session instance [" + session + "]");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Creating new EIS record for new session instance [" + session + "]");
}
sessionDAO.create(session);
}
@@ -215,8 +215,8 @@ protected void onChange(Session session) {
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
Serializable sessionId = getSessionId(sessionKey);
if (sessionId == null) {
- log.debug("Unable to resolve session ID from SessionKey [{}]. Returning null to indicate a " +
- "session could not be found.", sessionKey);
+ LOGGER.debug("Unable to resolve session ID from SessionKey [{}]. Returning null to indicate a "
+ + "session could not be found.", sessionKey);
return null;
}
Session s = retrieveSessionFromDataSource(sessionId);
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java b/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java
index 115b008df0..1e38fdc511 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java
@@ -47,8 +47,8 @@ public class DelegatingSession implements Session, Serializable {
private final SessionKey key;
//cached fields to avoid a server-side method call if out-of-process:
- private Date startTimestamp = null;
- private String host = null;
+ private Date startTimestamp;
+ private String host;
/**
* Handle to the target NativeSessionManager that will support the delegate calls.
@@ -64,9 +64,9 @@ public DelegatingSession(NativeSessionManager sessionManager, SessionKey key) {
throw new IllegalArgumentException("sessionKey argument cannot be null.");
}
if (key.getSessionId() == null) {
- String msg = "The " + DelegatingSession.class.getName() + " implementation requires that the " +
- "SessionKey argument returns a non-null sessionId to support the " +
- "Session.getId() invocations.";
+ String msg = "The " + DelegatingSession.class.getName() + " implementation requires that the "
+ + "SessionKey argument returns a non-null sessionId to support the "
+ + "Session.getId() invocations.";
throw new IllegalArgumentException(msg);
}
this.sessionManager = sessionManager;
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/ExecutorServiceSessionValidationScheduler.java b/core/src/main/java/org/apache/shiro/session/mgt/ExecutorServiceSessionValidationScheduler.java
index fc10de7a96..72b16174a0 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/ExecutorServiceSessionValidationScheduler.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/ExecutorServiceSessionValidationScheduler.java
@@ -39,13 +39,15 @@ public class ExecutorServiceSessionValidationScheduler implements SessionValidat
//TODO - complete JavaDoc
- /** Private internal log instance. */
- private static final Logger log = LoggerFactory.getLogger(ExecutorServiceSessionValidationScheduler.class);
+ /**
+ * Private internal log instance.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(ExecutorServiceSessionValidationScheduler.class);
ValidatingSessionManager sessionManager;
private ScheduledExecutorService service;
private long sessionValidationInterval = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
- private boolean enabled = false;
+ private boolean enabled;
private String threadNamePrefix = "SessionValidationThread-";
public ExecutorServiceSessionValidationScheduler() {
@@ -85,47 +87,47 @@ public String getThreadNamePrefix() {
}
/**
- * Creates a single thread {@link ScheduledExecutorService} to validate sessions at fixed intervals
+ * Creates a single thread {@link ScheduledExecutorService} to validate sessions at fixed intervals
* and enables this scheduler. The executor is created as a daemon thread to allow JVM to shut down
*/
//TODO Implement an integration test to test for jvm exit as part of the standalone example
// (so we don't have to change the unit test execution model for the core module)
public void enableSessionValidation() {
- if (this.sessionValidationInterval > 0l) {
- this.service = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
- private final AtomicInteger count = new AtomicInteger(1);
-
- public Thread newThread(Runnable r) {
- Thread thread = new Thread(r);
- thread.setDaemon(true);
- thread.setName(threadNamePrefix + count.getAndIncrement());
- return thread;
- }
- });
+ if (this.sessionValidationInterval > 0L) {
+ this.service = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
+ private final AtomicInteger count = new AtomicInteger(1);
+
+ public Thread newThread(Runnable r) {
+ Thread thread = new Thread(r);
+ thread.setDaemon(true);
+ thread.setName(threadNamePrefix + count.getAndIncrement());
+ return thread;
+ }
+ });
this.service.scheduleAtFixedRate(this, sessionValidationInterval,
- sessionValidationInterval, TimeUnit.MILLISECONDS);
+ sessionValidationInterval, TimeUnit.MILLISECONDS);
}
this.enabled = true;
}
public void run() {
- if (log.isDebugEnabled()) {
- log.debug("Executing session validation...");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Executing session validation...");
}
Thread.currentThread().setUncaughtExceptionHandler((t, e) -> {
- log.error("Error while validating the session, the thread will be stopped and session validation disabled", e);
+ LOGGER.error("Error while validating the session, the thread will be stopped and session validation disabled", e);
this.disableSessionValidation();
});
long startTime = System.currentTimeMillis();
try {
this.sessionManager.validateSessions();
} catch (RuntimeException e) {
- log.error("Error while validating the session", e);
+ LOGGER.error("Error while validating the session", e);
//we don't stop the thread
}
long stopTime = System.currentTimeMillis();
- if (log.isDebugEnabled()) {
- log.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds.");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Session validation completed successfully in " + (stopTime - startTime) + " milliseconds.");
}
}
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/ImmutableProxiedSession.java b/core/src/main/java/org/apache/shiro/session/mgt/ImmutableProxiedSession.java
index 8b8c74a6bf..5f99f76a85 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/ImmutableProxiedSession.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/ImmutableProxiedSession.java
@@ -58,8 +58,8 @@ public ImmutableProxiedSession(Session target) {
* @throws InvalidSessionException in all cases - used by the Session 'write' method implementations.
*/
protected void throwImmutableException() throws InvalidSessionException {
- String msg = "This session is immutable and read-only - it cannot be altered. This is usually because " +
- "the session has been stopped or expired already.";
+ String msg = "This session is immutable and read-only - it cannot be altered. This is usually because "
+ + "the session has been stopped or expired already.";
throw new InvalidSessionException(msg);
}
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/NativeSessionManager.java b/core/src/main/java/org/apache/shiro/session/mgt/NativeSessionManager.java
index 8c1259e48f..3e24bec6bb 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/NativeSessionManager.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/NativeSessionManager.java
@@ -64,8 +64,8 @@ public interface NativeSessionManager extends SessionManager {
* the reason for invalidation.
*
* @param key the session key to use to look up the target session.
- * @throws org.apache.shiro.session.InvalidSessionException
- * if the session id is invalid (it does not exist or it is stopped or expired).
+ * @throws org.apache.shiro.session.InvalidSessionException if the session id is invalid
+ * (it does not exist, or it is stopped or expired).
*/
void checkValid(SessionKey key) throws InvalidSessionException;
@@ -79,8 +79,8 @@ public interface NativeSessionManager extends SessionManager {
*
* @param key the session key to use to look up the target session.
* @return the time in milliseconds that the associated session may remain idle before expiring.
- * @throws org.apache.shiro.session.InvalidSessionException
- * if the session has been stopped or expired prior to calling this method.
+ * @throws org.apache.shiro.session.InvalidSessionException if the session has been stopped or
+ * expired prior to calling this method.
*/
long getTimeout(SessionKey key) throws InvalidSessionException;
@@ -94,8 +94,8 @@ public interface NativeSessionManager extends SessionManager {
*
* @param key the session key to use to look up the target session.
* @param maxIdleTimeInMillis the time in milliseconds that the associated session may remain idle before expiring.
- * @throws org.apache.shiro.session.InvalidSessionException
- * if the session has been stopped or expired prior to calling this method.
+ * @throws org.apache.shiro.session.InvalidSessionException if the session has been stopped
+ * or expired prior to calling this method.
*/
void setTimeout(SessionKey key, long maxIdleTimeInMillis) throws InvalidSessionException;
@@ -104,8 +104,8 @@ public interface NativeSessionManager extends SessionManager {
* can be used to explicitly ensure that a session does not time out.
*
* @param key the session key to use to look up the target session.
- * @throws org.apache.shiro.session.InvalidSessionException
- * if the session has been stopped or expired prior to calling this method.
+ * @throws org.apache.shiro.session.InvalidSessionException if the session has been stopped
+ * or expired prior to calling this method.
* @see org.apache.shiro.session.Session#touch
*/
void touch(SessionKey key) throws InvalidSessionException;
@@ -116,7 +116,7 @@ public interface NativeSessionManager extends SessionManager {
*
* @param key the session key to use to look up the target session.
* @return the host name or ip address of the host where the session originated, if known. If unknown,
- * this method returns {@code null}.
+ * this method returns {@code null}.
*/
String getHost(SessionKey key);
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/SessionContext.java b/core/src/main/java/org/apache/shiro/session/mgt/SessionContext.java
index b5506df9bd..36471ed57f 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/SessionContext.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/SessionContext.java
@@ -79,7 +79,7 @@ public interface SessionContext extends Map {
* {@code Session} host.
*
* @return the originating host name or IP address (as a String) from where the {@code Subject} is initiating the
- * {@code Session}.
+ * {@code Session}.
* @see #setHost(String) setHost(String)
*/
String getHost();
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/SessionManager.java b/core/src/main/java/org/apache/shiro/session/mgt/SessionManager.java
index b23af5718d..593e158af7 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/SessionManager.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/SessionManager.java
@@ -53,7 +53,7 @@ public interface SessionManager {
*
* @param key the Session key to use to look-up the Session
* @return the {@code Session} instance corresponding to the given lookup key or {@code null} if no session
- * could be acquired.
+ * could be acquired.
* @throws SessionException if a session was found but it was invalid (stopped/expired).
* @since 1.0
*/
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/SessionValidationScheduler.java b/core/src/main/java/org/apache/shiro/session/mgt/SessionValidationScheduler.java
index 633239d68a..260b3c22fb 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/SessionValidationScheduler.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/SessionValidationScheduler.java
@@ -20,7 +20,8 @@
/**
* Interface that should be implemented by classes that can control validating sessions on a regular
- * basis. This interface is used as a delegate for session validation by the {@link org.apache.shiro.session.mgt.DefaultSessionManager}
+ * basis. This interface is used as a delegate for session validation
+ * by the {@link org.apache.shiro.session.mgt.DefaultSessionManager}
*
* @see org.apache.shiro.session.mgt.DefaultSessionManager#setSessionValidationScheduler(SessionValidationScheduler)
* @since 0.1
@@ -49,4 +50,4 @@ public interface SessionValidationScheduler {
*/
void disableSessionValidation();
-}
\ No newline at end of file
+}
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/SimpleSession.java b/core/src/main/java/org/apache/shiro/session/mgt/SimpleSession.java
index e7101b4f1b..8b125a3184 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/SimpleSession.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/SimpleSession.java
@@ -30,7 +30,11 @@
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.DateFormat;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
/**
@@ -39,8 +43,16 @@
*
* @since 0.1
*/
+@SuppressWarnings("checkstyle:MethodCount")
public class SimpleSession implements ValidatingSession, Serializable {
+ protected static final long MILLIS_PER_SECOND = 1000;
+ protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
+ protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
+
+ //serialization bitmask fields. DO NOT CHANGE THE ORDER THEY ARE DECLARED!
+ static int bitIndexCounter;
+
// Serialization reminder:
// You _MUST_ change this number if you introduce a change to this class
// that is NOT serialization backwards compatible. Serialization-compatible
@@ -48,15 +60,7 @@ public class SimpleSession implements ValidatingSession, Serializable {
// a new number in this case, use the JDK's 'serialver' program to generate it.
private static final long serialVersionUID = -7125642695178165650L;
- //TODO - complete JavaDoc
- private transient static final Logger log = LoggerFactory.getLogger(SimpleSession.class);
-
- protected static final long MILLIS_PER_SECOND = 1000;
- protected static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
- protected static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
-
- //serialization bitmask fields. DO NOT CHANGE THE ORDER THEY ARE DECLARED!
- static int bitIndexCounter = 0;
+ private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSession.class);
private static final int ID_BIT_MASK = 1 << bitIndexCounter++;
private static final int START_TIMESTAMP_BIT_MASK = 1 << bitIndexCounter++;
private static final int STOP_TIMESTAMP_BIT_MASK = 1 << bitIndexCounter++;
@@ -93,7 +97,8 @@ public class SimpleSession implements ValidatingSession, Serializable {
private transient Map attributes;
public SimpleSession() {
- this.timeout = DefaultSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT; //TODO - remove concrete reference to DefaultSessionManager
+ //TODO - remove concrete reference to DefaultSessionManager
+ this.timeout = DefaultSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT;
this.startTimestamp = new Date();
this.lastAccessTime = this.startTimestamp;
}
@@ -134,7 +139,7 @@ public void setStartTimestamp(Date startTimestamp) {
* Once stopped, a session may no longer be used. It is locked from all further activity.
*
* @return The time the session was stopped, or null if the session is still
- * active.
+ * active.
*/
public Date getStopTimestamp() {
return stopTimestamp;
@@ -229,16 +234,16 @@ protected boolean isTimedOut() {
long timeout = getTimeout();
- if (timeout >= 0l) {
+ if (timeout >= 0L) {
Date lastAccessTime = getLastAccessTime();
if (lastAccessTime == null) {
- String msg = "session.lastAccessTime for session with id [" +
- getId() + "] is null. This value must be set at " +
- "least once, preferably at least upon instantiation. Please check the " +
- getClass().getName() + " implementation and ensure " +
- "this value will be set (perhaps in the constructor?)";
+ String msg = "session.lastAccessTime for session with id ["
+ + getId() + "] is null. This value must be set at "
+ + "least once, preferably at least upon instantiation. Please check the "
+ + getClass().getName() + " implementation and ensure "
+ + "this value will be set (perhaps in the constructor?)";
throw new IllegalStateException(msg);
}
@@ -251,9 +256,9 @@ protected boolean isTimedOut() {
Date expireTime = new Date(expireTimeMillis);
return lastAccessTime.before(expireTime);
} else {
- if (log.isTraceEnabled()) {
- log.trace("No timeout for session with id [" + getId() +
- "]. Session is not considered expired.");
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("No timeout for session with id [" + getId()
+ + "]. Session is not considered expired.");
}
}
@@ -264,9 +269,9 @@ public void validate() throws InvalidSessionException {
//check for stopped:
if (isStopped()) {
//timestamp is set, so the session is considered stopped:
- String msg = "Session with id [" + getId() + "] has been " +
- "explicitly stopped. No further interaction under this session is " +
- "allowed.";
+ String msg = "Session with id [" + getId() + "] has been "
+ + "explicitly stopped. No further interaction under this session is "
+ + "allowed.";
throw new StoppedSessionException(msg);
}
@@ -281,13 +286,13 @@ public void validate() throws InvalidSessionException {
Serializable sessionId = getId();
DateFormat df = DateFormat.getInstance();
- String msg = "Session with id [" + sessionId + "] has expired. " +
- "Last access time: " + df.format(lastAccessTime) +
- ". Current time: " + df.format(new Date()) +
- ". Session timeout is set to " + timeout / MILLIS_PER_SECOND + " seconds (" +
- timeout / MILLIS_PER_MINUTE + " minutes)";
- if (log.isTraceEnabled()) {
- log.trace(msg);
+ String msg = "Session with id [" + sessionId + "] has expired. "
+ + "Last access time: " + df.format(lastAccessTime)
+ + ". Current time: " + df.format(new Date())
+ + ". Session timeout is set to " + timeout / MILLIS_PER_SECOND + " seconds ("
+ + timeout / MILLIS_PER_MINUTE + " minutes)";
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(msg);
}
throw new ExpiredSessionException(msg);
}
@@ -374,14 +379,16 @@ public boolean equals(Object obj) {
* @return true if all the attributes, except the id, are equal to this object's attributes.
* @since 1.0
*/
+ @SuppressWarnings({"checkstyle:BooleanExpressionComplexity", "checkstyle:MethodCount"})
protected boolean onEquals(SimpleSession ss) {
- return (getStartTimestamp() != null ? getStartTimestamp().equals(ss.getStartTimestamp()) : ss.getStartTimestamp() == null) &&
- (getStopTimestamp() != null ? getStopTimestamp().equals(ss.getStopTimestamp()) : ss.getStopTimestamp() == null) &&
- (getLastAccessTime() != null ? getLastAccessTime().equals(ss.getLastAccessTime()) : ss.getLastAccessTime() == null) &&
- (getTimeout() == ss.getTimeout()) &&
- (isExpired() == ss.isExpired()) &&
- (getHost() != null ? getHost().equals(ss.getHost()) : ss.getHost() == null) &&
- (getAttributes() != null ? getAttributes().equals(ss.getAttributes()) : ss.getAttributes() == null);
+ return (getStartTimestamp() != null ? getStartTimestamp().equals(ss.getStartTimestamp()) : ss.getStartTimestamp() == null)
+ && (getStopTimestamp() != null ? getStopTimestamp().equals(ss.getStopTimestamp()) : ss.getStopTimestamp() == null)
+ && (getLastAccessTime() != null
+ ? getLastAccessTime().equals(ss.getLastAccessTime()) : ss.getLastAccessTime() == null)
+ && (getTimeout() == ss.getTimeout())
+ && (isExpired() == ss.isExpired())
+ && (getHost() != null ? getHost().equals(ss.getHost()) : ss.getHost() == null)
+ && (getAttributes() != null ? getAttributes().equals(ss.getAttributes()) : ss.getAttributes() == null);
}
/**
@@ -415,7 +422,7 @@ public int hashCode() {
* getClass().getName() + ",id=" + getId().
*
* @return the string representation of this SimpleSession, equal to
- * getClass().getName() + ",id=" + getId().
+ * getClass().getName() + ",id=" + getId().
* @since 1.0
*/
@Override
@@ -432,6 +439,7 @@ public String toString() {
* @throws IOException if any of this object's fields cannot be written to the stream.
* @since 1.0
*/
+ @SuppressWarnings("checkstyle:NPathComplexity")
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
short alteredFieldsBitMask = getAlteredFieldsBitMask();
@@ -448,7 +456,7 @@ private void writeObject(ObjectOutputStream out) throws IOException {
if (lastAccessTime != null) {
out.writeObject(lastAccessTime);
}
- if (timeout != 0l) {
+ if (timeout != 0L) {
out.writeLong(timeout);
}
if (expired) {
@@ -470,7 +478,7 @@ private void writeObject(ObjectOutputStream out) throws IOException {
* @throws ClassNotFoundException if a required class needed for instantiation is not available in the present JVM
* @since 1.0
*/
- @SuppressWarnings({"unchecked"})
+ @SuppressWarnings({"unchecked", "checkstyle:NPathComplexity"})
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
short bitMask = in.readShort();
@@ -509,13 +517,14 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
* @return a bit mask used during serialization indicating which fields have been serialized.
* @since 1.0
*/
+ @SuppressWarnings("checkstyle:NPathComplexity")
private short getAlteredFieldsBitMask() {
int bitMask = 0;
bitMask = id != null ? bitMask | ID_BIT_MASK : bitMask;
bitMask = startTimestamp != null ? bitMask | START_TIMESTAMP_BIT_MASK : bitMask;
bitMask = stopTimestamp != null ? bitMask | STOP_TIMESTAMP_BIT_MASK : bitMask;
bitMask = lastAccessTime != null ? bitMask | LAST_ACCESS_TIME_BIT_MASK : bitMask;
- bitMask = timeout != 0l ? bitMask | TIMEOUT_BIT_MASK : bitMask;
+ bitMask = timeout != 0L ? bitMask | TIMEOUT_BIT_MASK : bitMask;
bitMask = expired ? bitMask | EXPIRED_BIT_MASK : bitMask;
bitMask = host != null ? bitMask | HOST_BIT_MASK : bitMask;
bitMask = !CollectionUtils.isEmpty(attributes) ? bitMask | ATTRIBUTES_BIT_MASK : bitMask;
@@ -531,7 +540,7 @@ private short getAlteredFieldsBitMask() {
* been serialized, 0 means it hasn't been serialized.
* @param fieldBitMask the field bit mask constant identifying which bit to inspect (corresponds to a class attribute).
* @return {@code true} if the given {@code bitMask} argument indicates that the specified field has been
- * serialized and therefore should be read during deserialization, {@code false} otherwise.
+ * serialized and therefore should be read during deserialization, {@code false} otherwise.
* @since 1.0
*/
private static boolean isFieldPresent(short bitMask, int fieldBitMask) {
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/ValidatingSession.java b/core/src/main/java/org/apache/shiro/session/mgt/ValidatingSession.java
index 8b88228261..6d68a17a42 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/ValidatingSession.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/ValidatingSession.java
@@ -28,7 +28,7 @@
*
* Validation is usually an exercise of determining when the session was last accessed or modified and determining if
* that time is longer than a specified allowed duration.
- *
+ *
* @since 0.9
*/
public interface ValidatingSession extends Session {
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java b/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java
index b8055e0074..4a472ed5f1 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/eis/AbstractSessionDAO.java
@@ -65,7 +65,7 @@ public AbstractSessionDAO() {
* is a {@link JavaUuidSessionIdGenerator}.
*
* @return the {@code SessionIdGenerator} used by the {@link #generateSessionId(org.apache.shiro.session.Session)}
- * method.
+ * method.
*/
public SessionIdGenerator getSessionIdGenerator() {
return sessionIdGenerator;
@@ -151,7 +151,7 @@ protected void assignSessionId(Session session, Serializable sessionId) {
*
* @param session the Session instance to persist to the EIS.
* @return the id of the session created in the EIS (i.e. this is almost always a primary key and should be the
- * value returned from {@link org.apache.shiro.session.Session#getId() Session.getId()}.
+ * value returned from {@link org.apache.shiro.session.Session#getId() Session.getId()}.
*/
protected abstract Serializable doCreate(Session session);
@@ -178,7 +178,7 @@ public Session readSession(Serializable sessionId) throws UnknownSessionExceptio
*
* @param sessionId the id of the Session to retrieve.
* @return the Session in the EIS identified by sessionId or {@code null} if a
- * session with that ID could not be found.
+ * session with that ID could not be found.
*/
protected abstract Session doReadSession(Serializable sessionId);
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java b/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java
index f48dc75159..6ed409c187 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/eis/CachingSessionDAO.java
@@ -120,7 +120,7 @@ public void setActiveSessionsCacheName(String activeSessionsCacheName) {
* {@code CacheManager} using the {@link #getActiveSessionsCacheName() activeSessionsCacheName}.
*
* @return the cache instance to use for storing active sessions or {@code null} if the {@code Cache} instance
- * should be retrieved from the
+ * should be retrieved from the
*/
public Cache getActiveSessionsCache() {
return this.activeSessions;
@@ -162,7 +162,7 @@ private Cache getActiveSessionsCacheLazy() {
* cacheManager.getCache(name);
*
* @return a cache instance used to store active sessions, or {@code null} if the {@code CacheManager} has
- * not been set.
+ * not been set.
*/
protected Cache createActiveSessionsCache() {
Cache cache = null;
@@ -192,7 +192,7 @@ public Serializable create(Session session) {
*
* @param sessionId the id of the cached session to acquire.
* @return the cached session with the corresponding {@code sessionId}, or {@code null} if the session
- * does not exist or is not cached.
+ * does not exist or is not cached.
*/
protected Session getCachedSession(Serializable sessionId) {
Session cached = null;
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java b/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java
index 0896fba51d..c131dfa156 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/eis/EnterpriseCacheSessionDAO.java
@@ -67,9 +67,10 @@ protected Serializable doCreate(Session session) {
}
protected Session doReadSession(Serializable sessionId) {
- return null; //should never execute because this implementation relies on parent class to access cache, which
+ //should never execute because this implementation relies on parent class to access cache, which
//is where all sessions reside - it is the cache implementation that determines if the
//cache is memory only or disk-persistent, etc.
+ return null;
}
protected void doUpdate(Session session) {
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java b/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java
index 0095a26800..aa07f99767 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/eis/MemorySessionDAO.java
@@ -55,9 +55,9 @@
*/
public class MemorySessionDAO extends AbstractSessionDAO {
- private static final Logger log = LoggerFactory.getLogger(MemorySessionDAO.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(MemorySessionDAO.class);
- private ConcurrentMap sessions;
+ private final ConcurrentMap sessions;
public MemorySessionDAO() {
this.sessions = new ConcurrentHashMap();
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java b/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java
index 09cf0ccf74..d4249cd701 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/eis/RandomSessionIdGenerator.java
@@ -33,7 +33,7 @@
*/
public class RandomSessionIdGenerator implements SessionIdGenerator {
- private static final Logger log = LoggerFactory.getLogger(RandomSessionIdGenerator.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(RandomSessionIdGenerator.class);
private static final String RANDOM_NUM_GENERATOR_ALGORITHM_NAME = "SHA1PRNG";
private Random random;
@@ -42,8 +42,8 @@ public RandomSessionIdGenerator() {
try {
this.random = java.security.SecureRandom.getInstance(RANDOM_NUM_GENERATOR_ALGORITHM_NAME);
} catch (java.security.NoSuchAlgorithmException e) {
- log.debug("The SecureRandom SHA1PRNG algorithm is not available on the current platform. Using the " +
- "platform's default SecureRandom algorithm.", e);
+ LOGGER.debug("The SecureRandom SHA1PRNG algorithm is not available on the current platform. Using the "
+ + "platform's default SecureRandom algorithm.", e);
this.random = new java.security.SecureRandom();
}
}
diff --git a/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionDAO.java b/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionDAO.java
index 04722eba6e..ce831e4738 100644
--- a/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionDAO.java
+++ b/core/src/main/java/org/apache/shiro/session/mgt/eis/SessionDAO.java
@@ -82,9 +82,8 @@ public interface SessionDAO {
* errors.
*
* @param session the Session to update
- * @throws org.apache.shiro.session.UnknownSessionException
- * if no existing EIS session record exists with the
- * identifier of {@link Session#getId() session.getSessionId()}
+ * @throws org.apache.shiro.session.UnknownSessionException if no existing EIS session record exists with the
+ * identifier of {@link Session#getId() session.getSessionId()}
*/
void update(Session session) throws UnknownSessionException;
@@ -124,7 +123,7 @@ public interface SessionDAO {
* (e.g. now - 30 minutes).
*
* @return a Collection of {@code Session}s that are considered active, or an
- * empty collection or {@code null} if there are no active sessions.
+ * empty collection or {@code null} if there are no active sessions.
*/
Collection getActiveSessions();
}
diff --git a/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java b/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java
index 75da30c286..1de2cc3ad1 100644
--- a/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java
+++ b/core/src/main/java/org/apache/shiro/subject/PrincipalCollection.java
@@ -18,6 +18,10 @@
*/
package org.apache.shiro.subject;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.pam.AuthenticationStrategy;
+
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
@@ -68,7 +72,8 @@ public interface PrincipalCollection extends Iterable, Serializable {
* If this heuristic is not sufficient, most Shiro end-users will need to implement a custom
* {@link org.apache.shiro.authc.pam.AuthenticationStrategy}. An {@code AuthenticationStrategy} has exact control
* over the {@link PrincipalCollection} returned at the end of an authentication attempt via the
- * AuthenticationStrategy#{@link org.apache.shiro.authc.pam.AuthenticationStrategy#afterAllAttempts(org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.authc.AuthenticationInfo) afterAllAttempts}
+ * AuthenticationStrategy#
+ * {@link AuthenticationStrategy#afterAllAttempts(AuthenticationToken, AuthenticationInfo) afterAllAttempts}
* implementation.
*
* @return the primary principal used to uniquely identify the owning account/Subject
@@ -95,7 +100,7 @@ public interface PrincipalCollection extends Iterable, Serializable {
*
* @param type the type of the principals that should be returned.
* @return a Collection of principals that are assignable from the specified type, or
- * an empty Collection if no principals of this type are associated.
+ * an empty Collection if no principals of this type are associated.
*/
Collection byType(Class type);
@@ -127,7 +132,7 @@ public interface PrincipalCollection extends Iterable, Serializable {
*
* @param realmName the name of the Realm from which the principals were retrieved.
* @return the Subject's principals from the specified Realm only as a Collection or an empty Collection if there
- * are not any principals from that realm.
+ * are not any principals from that realm.
*/
Collection fromRealm(String realmName);
diff --git a/core/src/main/java/org/apache/shiro/subject/PrincipalMap.java b/core/src/main/java/org/apache/shiro/subject/PrincipalMap.java
index 3c5841718d..d08a73c430 100644
--- a/core/src/main/java/org/apache/shiro/subject/PrincipalMap.java
+++ b/core/src/main/java/org/apache/shiro/subject/PrincipalMap.java
@@ -47,11 +47,11 @@
*
* @since 1.2
*/
-public interface PrincipalMap extends PrincipalCollection, Map {
+public interface PrincipalMap extends PrincipalCollection, Map {
- Map getRealmPrincipals(String realmName);
+ Map getRealmPrincipals(String realmName);
- Map setRealmPrincipals(String realmName, Map principals);
+ Map setRealmPrincipals(String realmName, Map principals);
Object setRealmPrincipal(String realmName, String principalName, Object principal);
diff --git a/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java b/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
index 080c831b19..daf47e81ad 100644
--- a/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
+++ b/core/src/main/java/org/apache/shiro/subject/SimplePrincipalCollection.java
@@ -24,8 +24,16 @@
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.util.*;
-
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
/**
* A simple implementation of the {@link MutablePrincipalCollection} interface that tracks principals internally
@@ -44,10 +52,10 @@ public class SimplePrincipalCollection implements MutablePrincipalCollection {
private static final long serialVersionUID = -6305224034025797558L;
//TODO - complete JavaDoc
-
private Map realmPrincipals;
- private transient String cachedToString; //cached toString() result, as this can be printed many times in logging
+ //cached toString() result, as this can be printed many times in logging
+ private transient String cachedToString;
public SimplePrincipalCollection() {
}
@@ -229,7 +237,7 @@ public boolean equals(Object o) {
}
if (o instanceof SimplePrincipalCollection) {
SimplePrincipalCollection other = (SimplePrincipalCollection) o;
- return this.realmPrincipals != null ? this.realmPrincipals.equals(other.realmPrincipals) : other.realmPrincipals == null;
+ return Objects.equals(this.realmPrincipals, other.realmPrincipals);
}
return false;
}
diff --git a/core/src/main/java/org/apache/shiro/subject/SimplePrincipalMap.java b/core/src/main/java/org/apache/shiro/subject/SimplePrincipalMap.java
index 258ac88a1f..e2b3e69b5e 100644
--- a/core/src/main/java/org/apache/shiro/subject/SimplePrincipalMap.java
+++ b/core/src/main/java/org/apache/shiro/subject/SimplePrincipalMap.java
@@ -20,11 +20,19 @@
import org.apache.shiro.util.CollectionUtils;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* Default implementation of the {@link PrincipalMap} interface.
- *
+ *
* *EXPERIMENTAL for Shiro 1.2 - DO NOT USE YET*
*
* @since 1.2
@@ -48,7 +56,7 @@ public SimplePrincipalMap(Map> backingMap) {
if (!CollectionUtils.isEmpty(backingMap)) {
this.realmPrincipals = backingMap;
for (Map principals : this.realmPrincipals.values()) {
- if (!CollectionUtils.isEmpty(principals) ) {
+ if (!CollectionUtils.isEmpty(principals)) {
ensureCombinedPrincipals().putAll(principals);
}
}
@@ -93,21 +101,18 @@ public void putAll(Map extends String, ?> map) {
}
public Set keySet() {
- return CollectionUtils.isEmpty(this.combinedPrincipals) ?
- Collections.emptySet() :
- Collections.unmodifiableSet(this.combinedPrincipals.keySet());
+ return CollectionUtils.isEmpty(this.combinedPrincipals) ? Collections.emptySet()
+ : Collections.unmodifiableSet(this.combinedPrincipals.keySet());
}
public Collection values() {
- return CollectionUtils.isEmpty(this.combinedPrincipals) ?
- Collections.emptySet() :
- Collections.unmodifiableCollection(this.combinedPrincipals.values());
+ return CollectionUtils.isEmpty(this.combinedPrincipals) ? Collections.emptySet()
+ : Collections.unmodifiableCollection(this.combinedPrincipals.values());
}
public Set> entrySet() {
- return CollectionUtils.isEmpty(this.combinedPrincipals) ?
- Collections.>emptySet() :
- Collections.unmodifiableSet(this.combinedPrincipals.entrySet());
+ return CollectionUtils.isEmpty(this.combinedPrincipals)
+ ? Collections.>emptySet() : Collections.unmodifiableSet(this.combinedPrincipals.entrySet());
}
public void clear() {
@@ -117,17 +122,15 @@ public void clear() {
public Object getPrimaryPrincipal() {
//heuristic - just use the first one we come across:
- return !CollectionUtils.isEmpty(this.combinedPrincipals) ?
- this.combinedPrincipals.values().iterator().next() :
- null;
+ return !CollectionUtils.isEmpty(this.combinedPrincipals) ? this.combinedPrincipals.values().iterator().next() : null;
}
public T oneByType(Class type) {
if (CollectionUtils.isEmpty(this.combinedPrincipals)) {
return null;
}
- for( Object value : this.combinedPrincipals.values()) {
- if (type.isInstance(value) ) {
+ for (Object value : this.combinedPrincipals.values()) {
+ if (type.isInstance(value)) {
return type.cast(value);
}
}
@@ -139,8 +142,8 @@ public Collection byType(Class type) {
return Collections.emptySet();
}
Collection instances = null;
- for( Object value : this.combinedPrincipals.values()) {
- if (type.isInstance(value) ) {
+ for (Object value : this.combinedPrincipals.values()) {
+ if (type.isInstance(value)) {
if (instances == null) {
instances = new ArrayList();
}
@@ -172,7 +175,7 @@ public Collection fromRealm(String realmName) {
if (CollectionUtils.isEmpty(this.realmPrincipals)) {
return Collections.emptySet();
}
- Map principals = this.realmPrincipals.get(realmName);
+ Map principals = this.realmPrincipals.get(realmName);
if (CollectionUtils.isEmpty(principals)) {
return Collections.emptySet();
}
@@ -198,28 +201,28 @@ public Map getRealmPrincipals(String name) {
if (this.realmPrincipals == null) {
return null;
}
- Map principals = this.realmPrincipals.get(name);
+ Map principals = this.realmPrincipals.get(name);
if (principals == null) {
return null;
}
return Collections.unmodifiableMap(principals);
}
- public Map setRealmPrincipals(String realmName, Map principals) {
+ public Map setRealmPrincipals(String realmName, Map principals) {
if (realmName == null) {
throw new NullPointerException("realmName argument cannot be null.");
}
if (this.realmPrincipals == null) {
if (!CollectionUtils.isEmpty(principals)) {
- this.realmPrincipals = new HashMap>();
- return this.realmPrincipals.put(realmName, new HashMap(principals));
+ this.realmPrincipals = new HashMap>();
+ return this.realmPrincipals.put(realmName, new HashMap(principals));
} else {
return null;
}
} else {
- Map existingPrincipals = this.realmPrincipals.remove(realmName);
+ Map existingPrincipals = this.realmPrincipals.remove(realmName);
if (!CollectionUtils.isEmpty(principals)) {
- this.realmPrincipals.put(realmName, new HashMap(principals));
+ this.realmPrincipals.put(realmName, new HashMap(principals));
}
return existingPrincipals;
}
@@ -236,11 +239,11 @@ public Object setRealmPrincipal(String realmName, String principalName, Object p
return removeRealmPrincipal(realmName, principalName);
}
if (this.realmPrincipals == null) {
- this.realmPrincipals = new HashMap>();
+ this.realmPrincipals = new HashMap>();
}
- Map principals = this.realmPrincipals.get(realmName);
+ Map principals = this.realmPrincipals.get(realmName);
if (principals == null) {
- principals = new HashMap();
+ principals = new HashMap();
this.realmPrincipals.put(realmName, principals);
}
return principals.put(principalName, principal);
@@ -256,7 +259,7 @@ public Object getRealmPrincipal(String realmName, String principalName) {
if (this.realmPrincipals == null) {
return null;
}
- Map principals = this.realmPrincipals.get(realmName);
+ Map principals = this.realmPrincipals.get(realmName);
if (principals != null) {
return principals.get(principalName);
}
@@ -273,7 +276,7 @@ public Object removeRealmPrincipal(String realmName, String principalName) {
if (this.realmPrincipals == null) {
return null;
}
- Map principals = this.realmPrincipals.get(realmName);
+ Map principals = this.realmPrincipals.get(realmName);
if (principals != null) {
return principals.remove(principalName);
}
diff --git a/core/src/main/java/org/apache/shiro/subject/Subject.java b/core/src/main/java/org/apache/shiro/subject/Subject.java
index 8599c7d548..7b1c83f967 100644
--- a/core/src/main/java/org/apache/shiro/subject/Subject.java
+++ b/core/src/main/java/org/apache/shiro/subject/Subject.java
@@ -57,6 +57,7 @@
*
* @since 0.1
*/
+@SuppressWarnings("checkstyle:MethodCount")
public interface Subject {
/**
@@ -83,7 +84,8 @@ public interface Subject {
* or any other similar suitable unique mechanism valuable to your application.
*
* Most implementations will simply return
- * {@link #getPrincipals()}.{@link org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal() getPrimaryPrincipal()}
+ * {@link #getPrincipals()}.
+ * {@link org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal() getPrimaryPrincipal()}
*
* @return this Subject's application-specific unique identity.
* @see org.apache.shiro.subject.PrincipalCollection#getPrimaryPrincipal()
@@ -140,9 +142,9 @@ public interface Subject {
*
* @param permissions the String representations of the Permissions that are being checked.
* @return a boolean array where indices correspond to the index of the
- * permissions in the given list. A true value at an index indicates this Subject is permitted for
- * for the associated {@code Permission} string in the list. A false value at an index
- * indicates otherwise.
+ * permissions in the given list. A true value at an index indicates this Subject is permitted for
+ * for the associated {@code Permission} string in the list. A false value at an index
+ * indicates otherwise.
* @since 0.9
*/
boolean[] isPermitted(String... permissions);
@@ -160,9 +162,9 @@ public interface Subject {
*
* @param permissions the permissions that are being checked.
* @return a boolean array where indices correspond to the index of the
- * permissions in the given list. A true value at an index indicates this Subject is permitted for
- * for the associated {@code Permission} object in the list. A false value at an index
- * indicates otherwise.
+ * permissions in the given list. A true value at an index indicates this Subject is permitted for
+ * for the associated {@code Permission} object in the list. A false value at an index
+ * indicates otherwise.
*/
boolean[] isPermitted(List permissions);
@@ -200,8 +202,7 @@ public interface Subject {
* Please see the class-level JavaDoc for more information on these String-based permission methods.
*
* @param permission the String representation of the Permission to check.
- * @throws org.apache.shiro.authz.AuthorizationException
- * if the user does not have the permission.
+ * @throws org.apache.shiro.authz.AuthorizationException if the user does not have the permission.
* @since 0.9
*/
void checkPermission(String permission) throws AuthorizationException;
@@ -213,8 +214,7 @@ public interface Subject {
* the given permission, an {@link org.apache.shiro.authz.AuthorizationException} will be thrown.
*
* @param permission the Permission to check.
- * @throws org.apache.shiro.authz.AuthorizationException
- * if this Subject does not have the permission.
+ * @throws org.apache.shiro.authz.AuthorizationException if this Subject does not have the permission.
*/
void checkPermission(Permission permission) throws AuthorizationException;
@@ -267,8 +267,8 @@ public interface Subject {
*
* @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
* @return a boolean array where indices correspond to the index of the
- * roles in the given identifiers. A true value indicates this Subject has the
- * role at that index. False indicates this Subject does not have the role at that index.
+ * roles in the given identifiers. A true value indicates this Subject has the
+ * role at that index. False indicates this Subject does not have the role at that index.
*/
boolean[] hasRoles(List roleIdentifiers);
@@ -285,8 +285,7 @@ public interface Subject {
* {@link org.apache.shiro.authz.AuthorizationException} if they do not.
*
* @param roleIdentifier the application-specific role identifier (usually a role id or role name ).
- * @throws org.apache.shiro.authz.AuthorizationException
- * if this Subject does not have the role.
+ * @throws org.apache.shiro.authz.AuthorizationException if this Subject does not have the role.
*/
void checkRole(String roleIdentifier) throws AuthorizationException;
@@ -295,8 +294,7 @@ public interface Subject {
* {@link org.apache.shiro.authz.AuthorizationException} if they do not.
*
* @param roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
- * @throws org.apache.shiro.authz.AuthorizationException
- * if this Subject does not have all of the specified roles.
+ * @throws org.apache.shiro.authz.AuthorizationException if this Subject does not have all of the specified roles.
*/
void checkRoles(Collection roleIdentifiers) throws AuthorizationException;
@@ -308,7 +306,7 @@ public interface Subject {
*
* @param roleIdentifiers roleIdentifiers the application-specific role identifiers to check (usually role ids or role names).
* @throws AuthorizationException org.apache.shiro.authz.AuthorizationException
- * if this Subject does not have all of the specified roles.
+ * if this Subject does not have all of the specified roles.
* @since 1.1.0
*/
void checkRoles(String... roleIdentifiers) throws AuthorizationException;
@@ -325,8 +323,7 @@ public interface Subject {
*
* @param token the token encapsulating the subject's principals and credentials to be passed to the
* Authentication subsystem for verification.
- * @throws org.apache.shiro.authc.AuthenticationException
- * if the authentication attempt fails.
+ * @throws org.apache.shiro.authc.AuthenticationException if the authentication attempt fails.
* @since 0.9
*/
void login(AuthenticationToken token) throws AuthenticationException;
@@ -340,7 +337,7 @@ public interface Subject {
* current session. See the {@link #isRemembered() isRemembered()} method JavaDoc for more.
*
* @return {@code true} if this Subject proved their identity during their current session
- * by providing valid credentials matching those known to the system, {@code false} otherwise.
+ * by providing valid credentials matching those known to the system, {@code false} otherwise.
* @since 0.9
*/
boolean isAuthenticated();
@@ -392,7 +389,7 @@ public interface Subject {
* check this guarantee via the {@link #isAuthenticated() isAuthenticated()} method and not via this method.
*
* @return {@code true} if this {@code Subject}'s identity (aka {@link #getPrincipals() principals}) is
- * remembered from a successful authentication during a previous session, {@code false} otherwise.
+ * remembered from a successful authentication during a previous session, {@code false} otherwise.
* @since 1.0
*/
boolean isRemembered();
@@ -420,7 +417,7 @@ public interface Subject {
*
* @param create boolean argument determining if a new session should be created or not if there is no existing session.
* @return the application {@code Session} associated with this {@code Subject} or {@code null} based
- * on the above described logic.
+ * on the above described logic.
* @since 0.2
*/
Session getSession(boolean create);
@@ -534,7 +531,7 @@ public interface Subject {
* information.
*
* @return {@code true} if this {@code Subject} is 'running as' another identity other than its original one or
- * {@code false} otherwise (normal {@code Subject} state).
+ * {@code false} otherwise (normal {@code Subject} state).
* @see #runAs
* @since 1.0
*/
@@ -546,8 +543,8 @@ public interface Subject {
* identity (normal state). See the {@link #runAs runAs} method for more information.
*
* @return the previous 'pre run as' identity of this {@code Subject} before assuming the current
- * {@link #runAs runAs} identity, or {@code null} if this {@code Subject} is not operating under an assumed
- * identity (normal state).
+ * {@link #runAs runAs} identity, or {@code null} if this {@code Subject} is not operating under an assumed
+ * identity (normal state).
* @see #runAs
* @since 1.0
*/
@@ -561,7 +558,7 @@ public interface Subject {
* operating under an assumed identity.
*
* @return the 'run as' (assumed) identity being released or {@code null} if this {@code Subject} is not operating
- * under an assumed identity.
+ * under an assumed identity.
* @see #runAs
* @since 1.0
*/
@@ -604,7 +601,7 @@ public interface Subject {
*
* @since 1.0
*/
- public static class Builder {
+ class Builder {
/**
* Hold all contextual data via the Builder instance's method invocations to be sent to the
@@ -639,8 +636,8 @@ public Builder(SecurityManager securityManager) {
this.securityManager = securityManager;
this.subjectContext = newSubjectContextInstance();
if (this.subjectContext == null) {
- throw new IllegalStateException("Subject instance returned from 'newSubjectContextInstance' " +
- "cannot be null.");
+ throw new IllegalStateException("Subject instance returned from 'newSubjectContextInstance' "
+ + "cannot be null.");
}
this.subjectContext.setSecurityManager(securityManager);
}
@@ -737,7 +734,8 @@ public Builder session(Session session) {
* was named "{@code myRealm}", you might create the '{@code jsmith} {@code Subject} instance this
* way:
*
- * PrincipalCollection identity = new {@link org.apache.shiro.subject.SimplePrincipalCollection#SimplePrincipalCollection(Object, String) SimplePrincipalCollection}("jsmith", "myRealm");
+ * PrincipalCollection identity = new {@link SimplePrincipalCollection#SimplePrincipalCollection(Object, String)
+ * SimplePrincipalCollection}("jsmith", "myRealm");
* Subject jsmith = new Subject.Builder().principals(identity).buildSubject();
*
* Similarly, if your application's unique identifier for users is a {@code long} value (such as might be used
@@ -746,7 +744,8 @@ public Builder session(Session session) {
* instance this way:
*
* long userId = //get user ID from somewhere
- * PrincipalCollection userIdentity = new {@link org.apache.shiro.subject.SimplePrincipalCollection#SimplePrincipalCollection(Object, String) SimplePrincipalCollection}(userId, "jdbcRealm");
+ * PrincipalCollection userIdentity = new {@link SimplePrincipalCollection#SimplePrincipalCollection(Object, String)
+ * SimplePrincipalCollection}(userId, "jdbcRealm");
* Subject user = new Subject.Builder().principals(identity).buildSubject();
*
* @param principals the principals to use as the {@code Subject}'s identity.
@@ -839,7 +838,7 @@ public Builder contextAttribute(String attributeKey, Object attributeValue) {
* framework developer to bind the returned {@code Subject} for continued use if desired.
*
* @return a new {@code Subject} instance reflecting the cumulative state acquired by the
- * other methods in this class.
+ * other methods in this class.
*/
public Subject buildSubject() {
return this.securityManager.createSubject(this.subjectContext);
diff --git a/core/src/main/java/org/apache/shiro/subject/SubjectContext.java b/core/src/main/java/org/apache/shiro/subject/SubjectContext.java
index 3cb7a88099..d9e29a6392 100644
--- a/core/src/main/java/org/apache/shiro/subject/SubjectContext.java
+++ b/core/src/main/java/org/apache/shiro/subject/SubjectContext.java
@@ -63,7 +63,7 @@ public interface SubjectContext extends Map {
* {@code null} if one has not yet been provided to this context.
*
* @return the SecurityManager instance that should be used to back the constructed {@link Subject} instance or
- * {@code null} if one has not yet been provided to this context.
+ * {@code null} if one has not yet been provided to this context.
*/
SecurityManager getSecurityManager();
@@ -78,10 +78,11 @@ public interface SubjectContext extends Map {
/**
* Resolves the {@code SecurityManager} instance that should be used to back the constructed {@link Subject}
- * instance (typically used to support {@link org.apache.shiro.subject.support.DelegatingSubject DelegatingSubject} implementations).
+ * instance (typically used to support
+ * {@link org.apache.shiro.subject.support.DelegatingSubject DelegatingSubject} implementations).
*
* @return the {@code SecurityManager} instance that should be used to back the constructed {@link Subject}
- * instance
+ * instance
*/
SecurityManager resolveSecurityManager();
@@ -116,7 +117,7 @@ public interface SubjectContext extends Map {
* newly authenticated instance.
*
* @return any existing {@code Subject} that may be in use at the time the new {@code Subject} instance is
- * being created.
+ * being created.
*/
Subject getSubject();
@@ -176,7 +177,7 @@ public interface SubjectContext extends Map {
* reason for ignoring Shiro's default authentication state mechanisms.
*
* @return {@code true} if the constructed {@code Subject} should be considered authenticated, {@code false}
- * otherwise.
+ * otherwise.
*/
boolean isAuthenticated();
@@ -204,7 +205,7 @@ public interface SubjectContext extends Map {
* {@code false} otherwise.
*
* @param enabled whether or not the constructed {@code Subject} instance should be allowed to create a session,
- * {@code false} otherwise.
+ * {@code false} otherwise.
* @since 1.2
*/
void setSessionCreationEnabled(boolean enabled);
diff --git a/core/src/main/java/org/apache/shiro/subject/support/DefaultSubjectContext.java b/core/src/main/java/org/apache/shiro/subject/support/DefaultSubjectContext.java
index 5e888258bd..b2d9d99986 100644
--- a/core/src/main/java/org/apache/shiro/subject/support/DefaultSubjectContext.java
+++ b/core/src/main/java/org/apache/shiro/subject/support/DefaultSubjectContext.java
@@ -46,6 +46,21 @@
*/
public class DefaultSubjectContext extends MapContext implements SubjectContext {
+ /**
+ * session creation enabled key.
+ */
+ public static final String SESSION_CREATION_ENABLED = DefaultSubjectContext.class.getName() + ".SESSION_CREATION_ENABLED";
+
+ /**
+ * The session key that is used to store subject principals.
+ */
+ public static final String PRINCIPALS_SESSION_KEY = DefaultSubjectContext.class.getName() + "_PRINCIPALS_SESSION_KEY";
+
+ /**
+ * The session key that is used to store whether or not the user is authenticated.
+ */
+ public static final String AUTHENTICATED_SESSION_KEY = DefaultSubjectContext.class.getName() + "_AUTHENTICATED_SESSION_KEY";
+
private static final String SECURITY_MANAGER = DefaultSubjectContext.class.getName() + ".SECURITY_MANAGER";
private static final String SESSION_ID = DefaultSubjectContext.class.getName() + ".SESSION_ID";
@@ -64,19 +79,7 @@ public class DefaultSubjectContext extends MapContext implements SubjectContext
private static final String HOST = DefaultSubjectContext.class.getName() + ".HOST";
- public static final String SESSION_CREATION_ENABLED = DefaultSubjectContext.class.getName() + ".SESSION_CREATION_ENABLED";
-
- /**
- * The session key that is used to store subject principals.
- */
- public static final String PRINCIPALS_SESSION_KEY = DefaultSubjectContext.class.getName() + "_PRINCIPALS_SESSION_KEY";
-
- /**
- * The session key that is used to store whether or not the user is authenticated.
- */
- public static final String AUTHENTICATED_SESSION_KEY = DefaultSubjectContext.class.getName() + "_AUTHENTICATED_SESSION_KEY";
-
- private static final transient Logger log = LoggerFactory.getLogger(DefaultSubjectContext.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSubjectContext.class);
public DefaultSubjectContext() {
super();
@@ -97,15 +100,15 @@ public void setSecurityManager(SecurityManager securityManager) {
public SecurityManager resolveSecurityManager() {
SecurityManager securityManager = getSecurityManager();
if (securityManager == null) {
- if (log.isDebugEnabled()) {
- log.debug("No SecurityManager available in subject context map. " +
- "Falling back to SecurityUtils.getSecurityManager() lookup.");
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("No SecurityManager available in subject context map. "
+ + "Falling back to SecurityUtils.getSecurityManager() lookup.");
}
try {
securityManager = SecurityUtils.getSecurityManager();
} catch (UnavailableSecurityManagerException e) {
- if (log.isDebugEnabled()) {
- log.debug("No SecurityManager available via SecurityUtils. Heuristics exhausted.", e);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("No SecurityManager available via SecurityUtils. Heuristics exhausted.", e);
}
}
}
diff --git a/core/src/main/java/org/apache/shiro/subject/support/DelegatingSubject.java b/core/src/main/java/org/apache/shiro/subject/support/DelegatingSubject.java
index 5605da2d46..d5c19c440d 100644
--- a/core/src/main/java/org/apache/shiro/subject/support/DelegatingSubject.java
+++ b/core/src/main/java/org/apache/shiro/subject/support/DelegatingSubject.java
@@ -69,9 +69,10 @@
*
* @since 0.1
*/
+@SuppressWarnings("checkstyle:MethodCount")
public class DelegatingSubject implements Subject {
- private static final Logger log = LoggerFactory.getLogger(DelegatingSubject.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(DelegatingSubject.class);
private static final String RUN_AS_PRINCIPALS_SESSION_KEY =
DelegatingSubject.class.getName() + ".RUN_AS_PRINCIPALS_SESSION_KEY";
@@ -193,14 +194,14 @@ public boolean isPermittedAll(Collection permissions) {
protected void assertAuthzCheckPossible() throws AuthorizationException {
if (!hasPrincipals()) {
- String msg = "This subject is anonymous - it does not have any identifying principals and " +
- "authorization operations require an identity to check against. A Subject instance will " +
- "acquire these identifying principals automatically after a successful login is performed " +
- "be executing " + Subject.class.getName() + ".login(AuthenticationToken) or when 'Remember Me' " +
- "functionality is enabled by the SecurityManager. This exception can also occur when a " +
- "previously logged-in Subject has logged out which " +
- "makes it anonymous again. Because an identity is currently not known due to any of these " +
- "conditions, authorization is denied.";
+ String msg = "This subject is anonymous - it does not have any identifying principals and "
+ + "authorization operations require an identity to check against. A Subject instance will "
+ + "acquire these identifying principals automatically after a successful login is performed "
+ + "be executing " + Subject.class.getName() + ".login(AuthenticationToken) or when 'Remember Me' "
+ + "functionality is enabled by the SecurityManager. This exception can also occur when a "
+ + "previously logged-in Subject has logged out which "
+ + "makes it anonymous again. Because an identity is currently not known due to any of these "
+ + "conditions, authorization is denied.";
throw new UnauthenticatedException(msg);
}
}
@@ -274,8 +275,8 @@ public void login(AuthenticationToken token) throws AuthenticationException {
}
if (principals == null || principals.isEmpty()) {
- String msg = "Principals returned from securityManager.login( token ) returned a null or " +
- "empty value. This value must be non null and populated with one or more elements.";
+ String msg = "Principals returned from securityManager.login( token ) returned a null or "
+ + "empty value. This value must be non null and populated with one or more elements.";
throw new IllegalStateException(msg);
}
this.principals = principals;
@@ -318,25 +319,25 @@ public Session getSession() {
}
public Session getSession(boolean create) {
- if (log.isTraceEnabled()) {
- log.trace("attempting to get session; create = " + create +
- "; session is null = " + (this.session == null) +
- "; session has id = " + (this.session != null && session.getId() != null));
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("attempting to get session; create = " + create
+ + "; session is null = " + (this.session == null)
+ + "; session has id = " + (this.session != null && session.getId() != null));
}
if (this.session == null && create) {
//added in 1.2:
if (!isSessionCreationEnabled()) {
- String msg = "Session creation has been disabled for the current subject. This exception indicates " +
- "that there is either a programming error (using a session when it should never be " +
- "used) or that Shiro's configuration needs to be adjusted to allow Sessions to be created " +
- "for the current Subject. See the " + DisabledSessionException.class.getName() + " JavaDoc " +
- "for more.";
+ String msg = "Session creation has been disabled for the current subject. This exception indicates "
+ + "that there is either a programming error (using a session when it should never be "
+ + "used) or that Shiro's configuration needs to be adjusted to allow Sessions to be created "
+ + "for the current Subject. See the " + DisabledSessionException.class.getName() + " JavaDoc "
+ + "for more.";
throw new DisabledSessionException(msg);
}
- log.trace("Starting session for host {}", getHost());
+ LOGGER.trace("Starting session for host {}", getHost());
SessionContext sessionContext = createSessionContext();
Session session = this.securityManager.start(sessionContext);
this.session = decorate(session);
@@ -357,8 +358,8 @@ private void clearRunAsIdentitiesInternal() {
try {
clearRunAsIdentities();
} catch (SessionException se) {
- log.debug("Encountered session exception trying to clear 'runAs' identities during logout. This " +
- "can generally safely be ignored.", se);
+ LOGGER.debug("Encountered session exception trying to clear 'runAs' identities during logout. This "
+ + "can generally safely be ignored.", se);
}
}
@@ -402,16 +403,16 @@ public Callable associateWith(Callable callable) {
public Runnable associateWith(Runnable runnable) {
if (runnable instanceof Thread) {
- String msg = "This implementation does not support Thread arguments because of JDK ThreadLocal " +
- "inheritance mechanisms required by Shiro. Instead, the method argument should be a non-Thread " +
- "Runnable and the return value from this method can then be given to an ExecutorService or " +
- "another Thread.";
+ String msg = "This implementation does not support Thread arguments because of JDK ThreadLocal "
+ + "inheritance mechanisms required by Shiro. Instead, the method argument should be a non-Thread "
+ + "Runnable and the return value from this method can then be given to an ExecutorService or "
+ + "another Thread.";
throw new UnsupportedOperationException(msg);
}
return new SubjectRunnable(this, runnable);
}
- private class StoppingAwareProxiedSession extends ProxiedSession {
+ private static final class StoppingAwareProxiedSession extends ProxiedSession {
private final DelegatingSubject owner;
@@ -433,10 +434,10 @@ public void stop() throws InvalidSessionException {
public void runAs(PrincipalCollection principals) {
if (!hasPrincipals()) {
- String msg = "This subject does not yet have an identity. Assuming the identity of another " +
- "Subject is only allowed for Subjects with an existing identity. Try logging this subject in " +
- "first, or using the " + Subject.Builder.class.getName() + " to build ad hoc Subject instances " +
- "with identities as necessary.";
+ String msg = "This subject does not yet have an identity. Assuming the identity of another "
+ + "Subject is only allowed for Subjects with an existing identity. Try logging this subject in "
+ + "first, or using the " + Subject.Builder.class.getName() + " to build ad hoc Subject instances "
+ + "with identities as necessary.";
throw new IllegalStateException(msg);
}
pushIdentity(principals);
@@ -478,7 +479,7 @@ private List getRunAsPrincipalsStack() {
// this thread could throw this exception, so we catch it
// similar issue as in clearRunAsIdentitiesInternal()
// See https://issues.apache.org/jira/browse/SHIRO-512
- log.debug("Encountered session exception trying to get 'runAs' principal stack. This "
+ LOGGER.debug("Encountered session exception trying to get 'runAs' principal stack. This "
+ "can generally safely be ignored.", se);
}
}
@@ -529,12 +530,12 @@ private PrincipalCollection popIdentity() {
@Override
public String toString() {
return new StringJoiner(", ", "DelegatingSubject{", "}")
- .add("principals=" + principals)
- .add("authenticated=" + authenticated)
- .add("host='******")
- .add("session='******'")
- .add("sessionCreationEnabled=" + sessionCreationEnabled)
- .add("securityManager=" + securityManager)
- .toString();
+ .add("principals=" + principals)
+ .add("authenticated=" + authenticated)
+ .add("host='******")
+ .add("session='******'")
+ .add("sessionCreationEnabled=" + sessionCreationEnabled)
+ .add("securityManager=" + securityManager)
+ .toString();
}
}
diff --git a/core/src/main/java/org/apache/shiro/subject/support/SubjectCallable.java b/core/src/main/java/org/apache/shiro/subject/support/SubjectCallable.java
index d23971b7b4..d6d1ecfcbd 100644
--- a/core/src/main/java/org/apache/shiro/subject/support/SubjectCallable.java
+++ b/core/src/main/java/org/apache/shiro/subject/support/SubjectCallable.java
@@ -44,7 +44,7 @@
* invocations. It also guarantees that the running thread remains 'clean' in any thread-pooled environments.
*
*
Usage
- *
+ *
* This is typically considered a support class and is not often directly referenced. Most people prefer to use
* the {@code Subject.}{@link Subject#associateWith(Callable) associateWith} method, which will automatically return
* an instance of this class.
@@ -53,6 +53,7 @@
* {@link org.apache.shiro.concurrent.SubjectAwareExecutorService SubjectAwareExecutorService}, which
* transparently uses instances of this class.
*
+ * @param V
* @see Subject#associateWith(Callable)
* @see org.apache.shiro.concurrent.SubjectAwareExecutorService SubjectAwareExecutorService
* @since 1.0
diff --git a/core/src/main/java/org/apache/shiro/subject/support/SubjectRunnable.java b/core/src/main/java/org/apache/shiro/subject/support/SubjectRunnable.java
index 9e633dd411..42eeb61bdb 100644
--- a/core/src/main/java/org/apache/shiro/subject/support/SubjectRunnable.java
+++ b/core/src/main/java/org/apache/shiro/subject/support/SubjectRunnable.java
@@ -40,7 +40,7 @@
*
*
*
Usage
- *
+ *
* This is typically considered a support class and is not often directly referenced. Most people prefer to use
* the {@code Subject.}{@link Subject#execute(Runnable) execute} or
* {@code Subject.}{@link Subject#associateWith(Runnable) associateWith} methods, which transparently perform the
diff --git a/core/src/main/java/org/apache/shiro/subject/support/SubjectThreadState.java b/core/src/main/java/org/apache/shiro/subject/support/SubjectThreadState.java
index 2e439b1425..50a9c043d0 100644
--- a/core/src/main/java/org/apache/shiro/subject/support/SubjectThreadState.java
+++ b/core/src/main/java/org/apache/shiro/subject/support/SubjectThreadState.java
@@ -59,10 +59,10 @@ public SubjectThreadState(Subject subject) {
this.subject = subject;
SecurityManager securityManager = null;
- if ( subject instanceof DelegatingSubject) {
- securityManager = ((DelegatingSubject)subject).getSecurityManager();
+ if (subject instanceof DelegatingSubject) {
+ securityManager = ((DelegatingSubject) subject).getSecurityManager();
}
- if ( securityManager == null) {
+ if (securityManager == null) {
securityManager = ThreadContext.getSecurityManager();
}
this.securityManager = securityManager;
@@ -88,7 +88,7 @@ protected Subject getSubject() {
*/
public void bind() {
SecurityManager securityManager = this.securityManager;
- if ( securityManager == null ) {
+ if (securityManager == null) {
//try just in case the constructor didn't find one at the time:
securityManager = ThreadContext.getSecurityManager();
}
diff --git a/core/src/main/java/org/apache/shiro/subject/support/package-info.java b/core/src/main/java/org/apache/shiro/subject/support/package-info.java
index f3441f93f5..b339001837 100644
--- a/core/src/main/java/org/apache/shiro/subject/support/package-info.java
+++ b/core/src/main/java/org/apache/shiro/subject/support/package-info.java
@@ -19,4 +19,4 @@
/**
* Concrete support implementations of most of the {@code org.apache.shiro.subject} interfaces.
*/
-package org.apache.shiro.subject.support;
\ No newline at end of file
+package org.apache.shiro.subject.support;
diff --git a/core/src/main/java/org/apache/shiro/util/AbstractFactory.java b/core/src/main/java/org/apache/shiro/util/AbstractFactory.java
index 09e7e48cd1..97fce29f0e 100644
--- a/core/src/main/java/org/apache/shiro/util/AbstractFactory.java
+++ b/core/src/main/java/org/apache/shiro/util/AbstractFactory.java
@@ -21,8 +21,9 @@
import org.apache.shiro.lang.util.Factory;
/**
- * TODO - Class JavaDoc
+ * AbstractFactory.
*
+ * @param T
* @since 1.0
*/
public abstract class AbstractFactory implements Factory {
diff --git a/core/src/main/java/org/apache/shiro/util/AntPathMatcher.java b/core/src/main/java/org/apache/shiro/util/AntPathMatcher.java
index 29f1511806..0c31e306e4 100644
--- a/core/src/main/java/org/apache/shiro/util/AntPathMatcher.java
+++ b/core/src/main/java/org/apache/shiro/util/AntPathMatcher.java
@@ -80,7 +80,9 @@ public void setPathSeparator(String pathSeparator) {
}
/**
- * Checks if {@code path} is a pattern (i.e. contains a '*', or '?'). For example the {@code /foo/**} would return {@code true}, while {@code /bar/} would return {@code false}.
+ * Checks if {@code path} is a pattern (i.e. contains a '*', or '?').
+ * For example the {@code /foo/**} would return {@code true}, while {@code /bar/} would return {@code false}.
+ *
* @param path the string to check
* @return this method returns {@code true} if {@code path} contains a '*' or '?', otherwise, {@code false}
*/
@@ -103,7 +105,6 @@ public boolean matchStart(String pattern, String path) {
return doMatch(pattern, path, false);
}
-
/**
* Actually match the given path against the given pattern.
*
@@ -112,8 +113,10 @@ public boolean matchStart(String pattern, String path) {
* @param fullMatch whether a full pattern match is required
* (else a pattern match as far as the given base path goes is sufficient)
* @return true if the supplied path matched,
- * false if it didn't
+ * false if it didn't
*/
+ @SuppressWarnings({"checkstyle:ReturnCount", "checkstyle:CyclomaticComplexity",
+ "checkstyle:NPathComplexity", "checkstyle:MethodLength"})
protected boolean doMatch(String pattern, String path, boolean fullMatch) {
if (path == null || path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
return false;
@@ -143,18 +146,18 @@ protected boolean doMatch(String pattern, String path, boolean fullMatch) {
if (pathIdxStart > pathIdxEnd) {
// Path is exhausted, only match if rest of pattern is * or **'s
if (pattIdxStart > pattIdxEnd) {
- return (pattern.endsWith(this.pathSeparator) ?
- path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator));
+ return (pattern.endsWith(this.pathSeparator)
+ ? path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator));
}
if (!fullMatch) {
return true;
}
- if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") &&
- path.endsWith(this.pathSeparator)) {
+ if (pattIdxStart == pattIdxEnd && "*".equals(pattDirs[pattIdxStart])
+ && path.endsWith(this.pathSeparator)) {
return true;
}
for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
- if (!pattDirs[i].equals("**")) {
+ if (!"**".equals(pattDirs[i])) {
return false;
}
}
@@ -249,8 +252,10 @@ protected boolean doMatch(String pattern, String path, boolean fullMatch) {
* @param str string which must be matched against the pattern.
* Must not be null.
* @return true if the string matches against the
- * pattern, or false otherwise.
+ * pattern, or false otherwise.
*/
+ @SuppressWarnings({"checkstyle:ReturnCount", "checkstyle:CyclomaticComplexity",
+ "checkstyle:NPathComplexity", "checkstyle:MethodLength"})
private boolean matchStrings(String pattern, String str) {
char[] patArr = pattern.toCharArray();
char[] strArr = str.toCharArray();
@@ -271,29 +276,34 @@ private boolean matchStrings(String pattern, String str) {
if (!containsStar) {
// No '*'s, so we make a shortcut
if (patIdxEnd != strIdxEnd) {
- return false; // Pattern and string do not have the same size
+ // Pattern and string do not have the same size
+ return false;
}
for (int i = 0; i <= patIdxEnd; i++) {
ch = patArr[i];
if (ch != '?') {
if (ch != strArr[i]) {
- return false;// Character mismatch
+ // Character mismatch
+ return false;
}
}
}
- return true; // String matches against pattern
+ // String matches against pattern
+ return true;
}
if (patIdxEnd == 0) {
- return true; // Pattern contains only '*', which matches anything
+ // Pattern contains only '*', which matches anything
+ return true;
}
// Process characters before first star
while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
if (ch != '?') {
if (ch != strArr[strIdxStart]) {
- return false;// Character mismatch
+ // Character mismatch
+ return false;
}
}
patIdxStart++;
@@ -314,7 +324,8 @@ private boolean matchStrings(String pattern, String str) {
while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
if (ch != '?') {
if (ch != strArr[strIdxEnd]) {
- return false;// Character mismatch
+ // Character mismatch
+ return false;
}
}
patIdxEnd--;
diff --git a/core/src/main/java/org/apache/shiro/util/CollectionUtils.java b/core/src/main/java/org/apache/shiro/util/CollectionUtils.java
index 67fc5c94a4..61cd05b799 100644
--- a/core/src/main/java/org/apache/shiro/util/CollectionUtils.java
+++ b/core/src/main/java/org/apache/shiro/util/CollectionUtils.java
@@ -33,9 +33,10 @@
*
* @since 0.9
*/
-public class CollectionUtils {
+public final class CollectionUtils {
- //TODO - complete JavaDoc
+ private CollectionUtils() {
+ }
public static Set asSet(E... elements) {
if (elements == null || elements.length == 0) {
@@ -57,7 +58,7 @@ public static Set asSet(E... elements) {
*
* @param c the collection to check
* @return {@code true} if the specified {@code Collection} is {@code null} or {@link Collection#isEmpty empty},
- * {@code false} otherwise.
+ * {@code false} otherwise.
* @since 1.0
*/
public static boolean isEmpty(Collection c) {
@@ -70,7 +71,7 @@ public static boolean isEmpty(Collection c) {
*
* @param m the {@code Map} to check
* @return {@code true} if the specified {@code Map} is {@code null} or {@link Map#isEmpty empty},
- * {@code false} otherwise.
+ * {@code false} otherwise.
* @since 1.0
*/
public static boolean isEmpty(Map m) {
@@ -106,7 +107,7 @@ public static int size(Map m) {
*
* @param principals the principals to check.
* @return {@code true} if the specified {@code PrincipalCollection} is {@code null} or
- * {@link PrincipalCollection#isEmpty empty}, {@code false} otherwise.
+ * {@link PrincipalCollection#isEmpty empty}, {@code false} otherwise.
* @since 1.0
* @deprecated Use PrincipalCollection.isEmpty() directly.
*/
@@ -134,7 +135,7 @@ public static List asList(E... elements) {
Collections.addAll(deque, elements);
return deque;
}*/
-
+ @SuppressWarnings("checkstyle:MagicNumber")
static int computeListCapacity(int arraySize) {
return (int) Math.min(5L + arraySize + (arraySize / 10), Integer.MAX_VALUE);
}
diff --git a/core/src/main/java/org/apache/shiro/util/JavaEnvironment.java b/core/src/main/java/org/apache/shiro/util/JavaEnvironment.java
index 3a9e1bbef7..5d752d2789 100644
--- a/core/src/main/java/org/apache/shiro/util/JavaEnvironment.java
+++ b/core/src/main/java/org/apache/shiro/util/JavaEnvironment.java
@@ -66,14 +66,16 @@ public abstract class JavaEnvironment {
*/
public static final int JAVA_18 = 5;
- /** The virtual machine version, i.e. System.getProperty("java.version");. */
- private static final String version;
+ /**
+ * The virtual machine version, i.e. System.getProperty("java.version");.
+ */
+ private static final String VERSION;
/**
* The virtual machine major version. For example, with a version of
* 1.5.6_10, this would be 1.5
*/
- private static final int majorVersion;
+ private static final int MAJOR_VERSION;
/**
* Static code initialization block that sets the
@@ -81,25 +83,25 @@ public abstract class JavaEnvironment {
* upon initialization.
*/
static {
- version = System.getProperty("java.version");
+ VERSION = System.getProperty("java.version");
// version String should look like "1.4.2_10"
// NOTE: JDK 1.9 will be versioned differently '9' and/or 9.x.x
// https://blogs.oracle.com/java-platform-group/entry/a_new_jdk_9_version
- if (version.contains("1.8.")) {
- majorVersion = JAVA_18;
- } else if (version.contains("1.7.")) {
- majorVersion = JAVA_17;
- } else if (version.contains("1.6.")) {
- majorVersion = JAVA_16;
- } else if (version.contains("1.5.")) {
- majorVersion = JAVA_15;
- } else if (version.contains("1.4.")) {
- majorVersion = JAVA_14;
+ if (VERSION.contains("1.8.")) {
+ MAJOR_VERSION = JAVA_18;
+ } else if (VERSION.contains("1.7.")) {
+ MAJOR_VERSION = JAVA_17;
+ } else if (VERSION.contains("1.6.")) {
+ MAJOR_VERSION = JAVA_16;
+ } else if (VERSION.contains("1.5.")) {
+ MAJOR_VERSION = JAVA_15;
+ } else if (VERSION.contains("1.4.")) {
+ MAJOR_VERSION = JAVA_14;
} else {
// else leave 1.3 as default (it's either 1.3 or unknown)
- majorVersion = JAVA_13;
+ MAJOR_VERSION = JAVA_13;
}
}
@@ -112,7 +114,7 @@ public abstract class JavaEnvironment {
* @see System#getProperty(String)
*/
public static String getVersion() {
- return version;
+ return VERSION;
}
/**
@@ -128,7 +130,7 @@ public static String getVersion() {
* @see #JAVA_18
*/
public static int getMajorVersion() {
- return majorVersion;
+ return MAJOR_VERSION;
}
/**
@@ -171,7 +173,6 @@ public static boolean isAtLeastVersion15() {
* @see #JAVA_16
* @see #JAVA_17
* @see #JAVA_18
- *
* @since 1.2
*/
public static boolean isAtLeastVersion16() {
diff --git a/core/src/main/java/org/apache/shiro/util/JdbcUtils.java b/core/src/main/java/org/apache/shiro/util/JdbcUtils.java
index 0c5f3aeda2..5c02fdb71b 100644
--- a/core/src/main/java/org/apache/shiro/util/JdbcUtils.java
+++ b/core/src/main/java/org/apache/shiro/util/JdbcUtils.java
@@ -35,10 +35,12 @@
*
* @since 0.2
*/
-public class JdbcUtils {
+public final class JdbcUtils {
- /** Private internal log instance. */
- private static final Logger log = LoggerFactory.getLogger(JdbcUtils.class);
+ /**
+ * Private internal log instance.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(JdbcUtils.class);
/**
* Private constructor to prevent instantiation.
@@ -57,12 +59,12 @@ public static void closeConnection(Connection connection) {
try {
connection.close();
} catch (SQLException ex) {
- if (log.isDebugEnabled()) {
- log.debug("Could not close JDBC Connection", ex);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Could not close JDBC Connection", ex);
}
} catch (Throwable ex) {
- if (log.isDebugEnabled()) {
- log.debug("Unexpected exception on closing JDBC Connection", ex);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Unexpected exception on closing JDBC Connection", ex);
}
}
}
@@ -79,12 +81,12 @@ public static void closeStatement(Statement statement) {
try {
statement.close();
} catch (SQLException ex) {
- if (log.isDebugEnabled()) {
- log.debug("Could not close JDBC Statement", ex);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Could not close JDBC Statement", ex);
}
} catch (Throwable ex) {
- if (log.isDebugEnabled()) {
- log.debug("Unexpected exception on closing JDBC Statement", ex);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Unexpected exception on closing JDBC Statement", ex);
}
}
}
@@ -101,12 +103,12 @@ public static void closeResultSet(ResultSet rs) {
try {
rs.close();
} catch (SQLException ex) {
- if (log.isDebugEnabled()) {
- log.debug("Could not close JDBC ResultSet", ex);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Could not close JDBC ResultSet", ex);
}
} catch (Throwable ex) {
- if (log.isDebugEnabled()) {
- log.debug("Unexpected exception on closing JDBC ResultSet", ex);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Unexpected exception on closing JDBC ResultSet", ex);
}
}
}
diff --git a/core/src/main/java/org/apache/shiro/util/MapContext.java b/core/src/main/java/org/apache/shiro/util/MapContext.java
index 1ea2437bda..9adbc4d91a 100644
--- a/core/src/main/java/org/apache/shiro/util/MapContext.java
+++ b/core/src/main/java/org/apache/shiro/util/MapContext.java
@@ -19,7 +19,11 @@
package org.apache.shiro.util;
import java.io.Serializable;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
/**
* A {@code MapContext} provides a common base for context-based data storage in a {@link Map}. Type-safe attribute
@@ -61,9 +65,9 @@ protected E getTypedValue(String key, Class type) {
Object o = backingMap.get(key);
if (o != null) {
if (!type.isAssignableFrom(o.getClass())) {
- String msg = "Invalid object found in SubjectContext Map under key [" + key + "]. Expected type " +
- "was [" + type.getName() + "], but the object under that key is of type " +
- "[" + o.getClass().getName() + "].";
+ String msg = "Invalid object found in SubjectContext Map under key [" + key + "]. Expected type "
+ + "was [" + type.getName() + "], but the object under that key is of type "
+ + "[" + o.getClass().getName() + "].";
throw new IllegalArgumentException(msg);
}
found = (E) o;
diff --git a/core/src/main/java/org/apache/shiro/util/PatternMatcher.java b/core/src/main/java/org/apache/shiro/util/PatternMatcher.java
index 436f693534..ac2d7a7649 100644
--- a/core/src/main/java/org/apache/shiro/util/PatternMatcher.java
+++ b/core/src/main/java/org/apache/shiro/util/PatternMatcher.java
@@ -24,7 +24,7 @@
* Different implementations can support different pattern types, for example, Ant style path expressions, or
* regular expressions, or other types of text based patterns.
*
- * @see org.apache.shiro.lang.util.AntPathMatcher AntPathMatcher
+ * @see AntPathMatcher AntPathMatcher
* @since 0.9 RC2
*/
public interface PatternMatcher {
@@ -36,7 +36,7 @@ public interface PatternMatcher {
* @param pattern the pattern to match against
* @param source the source to match
* @return true if the given source matches the specified pattern,
- * false otherwise.
+ * false otherwise.
*/
boolean matches(String pattern, String source);
}
diff --git a/core/src/main/java/org/apache/shiro/util/PermissionUtils.java b/core/src/main/java/org/apache/shiro/util/PermissionUtils.java
index 8d46eb5d72..f574b96487 100644
--- a/core/src/main/java/org/apache/shiro/util/PermissionUtils.java
+++ b/core/src/main/java/org/apache/shiro/util/PermissionUtils.java
@@ -33,7 +33,10 @@
*
* @since 0.1
*/
-public class PermissionUtils {
+public final class PermissionUtils {
+
+ private PermissionUtils() {
+ }
public static Set resolveDelimitedPermissions(String s, PermissionResolver permissionResolver) {
Set permStrings = toPermissionStrings(s);
@@ -48,7 +51,8 @@ public static Set toPermissionStrings(String permissionsString) {
return null;
}
- public static Set resolvePermissions(Collection permissionStrings, PermissionResolver permissionResolver) {
+ public static Set resolvePermissions(Collection permissionStrings,
+ PermissionResolver permissionResolver) {
Set permissions = new LinkedHashSet<>(permissionStrings.size());
for (String permissionString : permissionStrings) {
permissions.add(permissionResolver.resolvePermission(permissionString));
diff --git a/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java b/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java
index b07ce3d03a..b03d96b3da 100644
--- a/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java
+++ b/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java
@@ -33,7 +33,7 @@ public class RegExPatternMatcher implements PatternMatcher {
private static final int CASE_INSENSITIVE = DEFAULT | Pattern.CASE_INSENSITIVE;
- private boolean caseInsensitive = false;
+ private boolean caseInsensitive;
/**
* Simple implementation that merely uses the default pattern comparison logic provided by the
@@ -43,6 +43,7 @@ public class RegExPatternMatcher implements PatternMatcher {
* Pattern p = Pattern.compile(pattern, Pattern.DOTALL);
* Matcher m = p.matcher(source);
* return m.matches();
+ *
* @param pattern the pattern to match against
* @param source the source to match
* @return {@code true} if the source matches the required pattern, {@code false} otherwise.
@@ -58,6 +59,7 @@ public boolean matches(String pattern, String source) {
/**
* Returns true if regex match should be case-insensitive.
+ *
* @return true if regex match should be case-insensitive.
*/
public boolean isCaseInsensitive() {
@@ -66,6 +68,7 @@ public boolean isCaseInsensitive() {
/**
* Adds the Pattern.CASE_INSENSITIVE flag when compiling patterns.
+ *
* @param caseInsensitive true if patterns should match case-insensitive.
*/
public void setCaseInsensitive(boolean caseInsensitive) {
diff --git a/core/src/main/java/org/apache/shiro/util/ThreadContext.java b/core/src/main/java/org/apache/shiro/util/ThreadContext.java
index 28488a3e26..267a7949b9 100644
--- a/core/src/main/java/org/apache/shiro/util/ThreadContext.java
+++ b/core/src/main/java/org/apache/shiro/util/ThreadContext.java
@@ -46,14 +46,21 @@
public abstract class ThreadContext {
/**
- * Private internal log instance.
+ * security manager key.
*/
- private static final Logger log = LoggerFactory.getLogger(ThreadContext.class);
-
public static final String SECURITY_MANAGER_KEY = ThreadContext.class.getName() + "_SECURITY_MANAGER_KEY";
+
+ /**
+ * subject key.
+ */
public static final String SUBJECT_KEY = ThreadContext.class.getName() + "_SUBJECT_KEY";
- private static final ThreadLocal