News and noteworthy - phax/ph-commons GitHub Wiki

Maintenance

  • v12.x (Java 17) - is in development
  • v11.x (Java 11) - critical fixes are backported
  • v10.x (Java 1.8) - not maintained anymore
  • v9.x and older (Java 1.8) - not maintained anymore

Releases

v12.5.1 - 2026-10-08

  • Added the new interface IHttpClientCredentials as the common base of all client side credentials for the HTTP Authorization header. BasicAuthClientCredentials implements it
  • Added BearerAuthClientCredentials and HttpBearerAuth in the new package com.helger.http.bearerauth to support HTTP Bearer Token authentication (RFC 6750). The scheme name is matched case-insensitively when parsing
  • Added IJsonCollection.forEachJson (Consumer) to iterate all contained JSON children - the elements of an IJsonArray and the values of an IJsonObject
  • Added IJsonCollection.forEachMapped (Function, Consumer) and IJsonCollection.forEachMapped (Predicate, Function, Consumer) to iterate, filter and map all contained JSON children
  • Added IJsonCollection.getAllMapped (Function) and IJsonCollection.getAllMapped (Predicate, Function) to map all contained JSON children into a new list, without the intermediate copy that IJsonArray.getAll () and IJsonObject.values () create
  • Security fix: XMLTransformerFactory.makeTransformerFactorySecure (TransformerFactory, String...) denied nothing at all on Saxon, if no allowed scheme was passed in (which is the default, and what createTransformerFactory (ErrorListener, URIResolver) does). It applied the empty String to XMLConstants.ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_STYLESHEET, which is what the JAXP specification defines for "deny all access to external references" - and what the JDK implementation does. Saxon however maps ACCESS_EXTERNAL_STYLESHEET onto its own Feature.ALLOWED_PROTOCOLS, where the empty String is explicitly documented to be ignored and to fall back to the default all, so the call silently allowed every protocol. The two JAXP properties keep their specified value, and the Saxon feature http://saxon.sf.net/feature/allowedProtocols is now additionally set to the Saxon keyword #none when no scheme is allowed at all. It is applied as a separate, implementation specific attribute on purpose: #none is not a valid value according to the JAXP grammar for these properties (a scheme is alpha *( alpha | digit | "+" | "-" | "." )), so using it as the value of the standard properties would leave an implementation that validates the value completely unrestricted. An implementation that does not know the Saxon attribute ignores it - that is logged on debug level only.
  • AbstractStatisticsHandlerNumeric and AbstractStatisticsHandlerKeyedNumeric now keep the sum in a long and only switch to BigInteger if that overflows. Previously every single recorded value allocated a new BigInteger, which is noticeable in the hot path of the timer and size handlers - and for the keyed handlers it additionally meant one permanently retained BigInteger per key. The getSum () methods keep returning BigInteger and are unchanged in behaviour.
  • Incompatible change: AbstractWALDAO and AbstractSimpleDAO now throw a DAOException, if the file to be read exists but cannot be parsed as XML. Previously this was only logged as an error and the DAO silently continued with no content at all. The next write then replaced the existing file and deleted the only copy of the data - for the ph-oton user, user group and role DAOs a single broken XML file therefore locked everybody out and discarded the file afterwards. The registered read exception handlers of AbstractDAO.exceptionHandlersRead () are now invoked for this case as well. See phax/ph-oton#11
  • Deprecated XMLMaskHelper.getXML11EntityReferenceString (char) and EXMLParserFeature.SAX_IS_XML11_PARSER because XML 1.1 is deprecated - see w3ctag/obsoletion#6

v12.5.0 - 2026-09-21

  • Updated to BouncyCastle 1.86
  • Added StringHelper.is(Not)Blank in favour of is(Not)EmptyAfterTrim using String.isBlank internally
  • Deprecated StringHelper.is(Not)EmptyAfterTrim
  • Continued the "security by default" work of v12.3.2 in ph-xml, after comparing it against the security measures of Apache Commons Secure XML. The central insight taken over from that project is that a resource resolver returning null is not a block: every JAXP implementation treats null as "not handled" and then opens the URI itself. A blocked resource is therefore now resolved to an empty document instead, which cannot be bypassed.
    • Security fix: XMLTransformerFactory.createTransformerFactory (ErrorListener, URIResolver) now applies makeTransformerFactorySecure() to the returned factory. Previously only the internal getDefaultTransformerFactory() instance was secured, so a factory created through the public method combined with a URIResolver that blocked a remote scheme still let XSLTC fetch that URL itself - the remote content ended up in the transformation result (SSRF via document(), xsl:import and xsl:include).
    • Incompatible change: XMLFactory.defaultCustomizeTransformerFactory (TransformerFactory) now enables FEATURE_SECURE_PROCESSING, which was prepared but disabled in the code before. It is the only setting that stops the fetch described above, and it therefore also affects XMLFactory.createDefaultTransformerFactory (). An xsl:import/xsl:include that is resolved by a URIResolver - as DefaultTransformURIResolver does for all class path and file based resources - keeps working unchanged. A stylesheet that relies on the XSLT processor resolving an include on its own now fails; either install a resolver, or call XMLTransformerFactory.makeTransformerFactorySecure (aFactory, "file") to allow that scheme explicitly.
    • DefaultTransformURIResolver returns an empty DOMSource instead of null for a resource whose URL scheme is not allowed, so that document() evaluates to an empty node set and the wrapped URIResolver is not consulted for a blocked resource either.
    • SimpleLSResourceResolver returns an LSInput with an empty byte stream instead of null for a blocked resource. Note that an LSInput carrying only an empty string data is not sufficient - Xerces treats it like "no content at all" and opens the system ID anyway.
    • DefaultEntityResolver now performs the same URL scheme check as the other two resolvers, using the new methods setAllowedRemoteSchemes(String...) and getAllAllowedRemoteSchemes(). A blocked entity resolves to an empty document. Previously this resolver resolved every system ID without restriction, which was documented as a security warning only.
    • Added XMLSchemaValidationHelper.makeValidatorSecure (Validator, String...) that denies the external DTD and schema access of a single Validator. This is needed because the JAXP contract of SchemaFactory.setResourceResolver() explicitly states that neither the resolver nor the properties of a SchemaFactory are inherited by the Schema, Validator and ValidatorHandler objects it creates - so a Validator obtained from an unsecured SchemaFactory read the external DTD of the instance document. It is now applied by XMLSchemaValidationHelper.validate (...) and by SchemaCache.getValidatorFromSchema (Schema), the latter additionally propagating the LSResourceResolver of its SchemaFactory onto the Validator. Note that XMLSchemaValidationHelper.validate (...) reports a blocked external entity as an IllegalArgumentException and not in the error list, because that is how it handles all fatal parsing errors.
    • Added a secure StAX factory, which ph-xml was missing completely: XMLFactory.createDefaultXMLInputFactory () and XMLFactory.defaultCustomizeXMLInputFactory (XMLInputFactory) disable supportDTD and isSupportingExternalEntities and install the new com.helger.xml.stax.EmptyXMLResolver as a non-bypassable floor, for implementations that ignore supportDTD. Contrary to all other XML APIs, StAX defines no FEATURE_SECURE_PROCESSING counterpart, so the limits on the internal entity expansion remain the ones of the implementation (see XMLSystemProperties for the JDK ones).
  • Added IPagingSpec.get(StartIndex|MaxCount)AsInt overloads for all consumers bound to int range.
  • Incompatible change: CompareHelper.compareTrueBeforeFalse (boolean, boolean) and compareFalseBeforeTrue (boolean, boolean) did the exact opposite of what their names say - compareTrueBeforeFalse sorted false first and vice versa. Both now match their names (the Javadoc of compareFalseBeforeTrue was wrong as well and now reads "false before true"). The only affected caller inside ph-commons is MutableBoolean.compareTo (MutableBoolean), which now sorts false before true, consistent with Boolean.compareTo. Code that sorted booleans with either method gets the reverse order than before.
  • Bugfix: ThreadDescriptorList.getAsString () and getAsMicroNode () threw a NullPointerException for every Thread.State that had no thread, because the internal state map only contained the states that actually occurred. Both methods are now safe, and a thread that died in the meantime (and therefore has no state anymore) no longer causes a NullPointerException either.
  • Incompatible change: ICommonsOrderedSet and ICommonsSortedSet (and therefore ICommonsNavigableSet) replaced the no-argument getFirst () and getLast () with getFirstOrNull () and getLastOrNull () - the same change ICommonsList received in v11.1.5. The old no-argument methods were dead code since Java 21: SequencedCollection.getFirst ()/getLast () of the implementation classes (ArrayList, LinkedHashSet, TreeSet, ...) shadow any interface default method of the same name, so the documented @Nullable contract never applied and an empty collection threw a NoSuchElementException instead. The getFirst (default) and getLast (default) overloads are unaffected.
  • Bugfix: MimeTypeInfo.getPrimaryGlob () and getPrimaryExtension (WithSource) () are documented as @Nullable but threw a NoSuchElementException for an info without globs resp. extensions, for the reason above. They now return null as documented.
  • Bugfix: ArrayIteratorByte.next () ignored the offset, if the iterator was created with bCopyNeeded == false - it always started at index 0 of the source array instead of at the provided offset. The copying constructors were not affected, because they copy the requested range.
  • Bugfix: ICommonsSortedMap.copyOfEntrySet () always threw a ClassCastException, if the map used the natural ordering of the keys, because Map.Entry is not Comparable. The returned set is now sorted by key in all cases - using the comparator of the map, if present, and the natural ordering of the keys otherwise. Additionally an entry with a null value no longer throws a NullPointerException, because the entries are copied with MapEntry instead of Map.Entry.copyOf.
  • Incompatible change: ICommonsSortedMap.copyOfKeySet () and copyOfKeySet (Predicate) now use the comparator of the map, so that the copy has the same ordering as the map. Previously the copy always used the natural ordering of the keys, and a map with non-Comparable keys and a custom comparator could not be copied at all.
  • Incompatible change: equals of WrappedCollection, WrappedList and WrappedSet now unwraps the passed object, if it is one of these facades, so that two facades around equal collections are equal. Previously the wrapped collection was compared with the facade, so e.g. two WrappedCollection objects around equal ArrayLists were never equal, because AbstractList.equals rejects a non-List argument. A facade is still equal to the collection it wraps.
  • The coverage profile now enforces a minimum JaCoCo instruction coverage per module via jacoco:check - 80% for all modules, 90% for ph-base (configurable via the jacoco.check.minimum property)
  • Extended the unit tests of ph-base, ph-bc, ph-collection, ph-commons, ph-config, ph-dao, ph-datetime, ph-diagnostics, ph-graph, ph-http, ph-io, ph-jaxb, ph-jaxb-adapter, ph-json, ph-scopes, ph-security, ph-settings, ph-text, ph-tree, ph-typeconvert, ph-url, ph-wsclient and ph-xml to reach the new minimum code coverage.
  • All field names passed to the ToStringGenerator append* methods now start with an uppercase character, so that the toString () output is consistent across all classes. This only changes the text of the toString () results, which is not part of the API contract.
  • Extended the ValueEnforcer based parameter validation of the public API of ph-config, ph-config-json, ph-json and ph-xml. Methods that so far relied on an incidental NullPointerException, an ArrayIndexOutOfBoundsException or on no check at all now fail fast with a named message. Parser and serializer callbacks that are only invoked by a parser (e.g. the IJsonParserHandler implementations, MicroSAXHandler and the per-character helpers of XMLCharHelper) were deliberately left unchecked.
    • Incompatible change: XMLHelper.getPathToNode (Node[, String]) and getPathToNode2 (Node[, String]) now throw a NullPointerException instead of an IllegalStateException for a null node or a null separator.
    • Incompatible change: AbstractMicroNode.internalSetParentNode (AbstractMicroNodeWithChildren) now throws a NullPointerException instead of a MicroException for a null parent node.
    • XPathHelper.createNewXPathExpression (XPath, String) now enforces the documented @Nonempty contract of the XPath expression instead of only checking for null.

v12.4.0 - 2026-08-30

  • ph-security no longer requires BouncyCastle at runtime - the ph-bc dependency was changed from optional to test scope (thanks to @gregjotau for https://github.com/phax/ph-commons/pull/57). The two remaining linkages were replaced: the "CRL Distribution Points" certificate extension is now decoded by the new package private CRLDistributionPointParser, a deliberately strict DER parser for exactly that extension (RFC 5280, section 4.2.1.13), and EOCSPResponseStatus uses the numerical values of RFC 6960, section 4.2.1 directly instead of importing them from BouncyCastle. The public API, the returned CRL URLs, the CRL caching and the revocation check implementation are all unchanged, and applications are of course still free to register the BouncyCastle provider via ph-bc.
  • Incompatible change: CRLHelper.getAllDistributionPoints (X509Certificate) now throws an UncheckedIOException for a "CRL Distribution Points" extension that is not valid DER. BouncyCastle additionally accepted a few BER encodings - e.g. the indefinite length form or trailing data after the extension - and reported structural problems as IllegalArgumentException. RFC 5280 requires certificate extensions to be DER encoded, so such certificates are now rejected instead of guessed.
  • The revocation check no longer lets a failure to decode the "CRL Distribution Points" extension escape from RevocationCheckBuilder.build (). It is now handled like a failed CRL download, so the result is ERevoked.UNKNOWN ("the revocation status cannot be determined") instead of an exception.
  • Added the constant CHttpHeader.REPORTING_ENDPOINTS for the Reporting-Endpoints HTTP response header of the Reporting API. It declares the named endpoints that the CSP report-to directive (see CSPDirective.createReportTo (String)) refers to.
  • Added a builder for the Permissions-Policy HTTP response header in the new package com.helger.http.permissionspolicy, modelled after the existing CSP builder. PermissionsPolicy collects an arbitrary number of PermissionsPolicyDirective objects and PermissionsPolicy.getAsString () emits them comma separated, ready to be used as the value of CHttpHeader.PERMISSIONS_POLICY. PermissionsPolicyAllowList builds the allow list of a single directive - the wildcard * via setAll (), the empty list () that disables a feature everywhere, self, src and quoted origins via addOrigin (String); the shorthands createNone (), createAll () and createSelf () cover the most common cases. PermissionsPolicyDirective offers a static factory method for each of the 50 directives currently listed on https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Permissions-Policy (e.g. createGeolocation (...) or createPictureInPicture (...)), and additionally supports the optional per-directive reporting endpoint via getWithReportTo (String). Note that - contrary to CSP - an empty allow list is meaningful and is therefore emitted as geolocation=(), whereas a directive without any value at all is silently skipped.
  • Added the new package com.helger.collection.paging in ph-collection, containing a data store independent parameter object for paged and sorted queries. SortField is a single logical field name plus an ESortOrder, IPagingSpec/PagingSpec combine a 0-based start index, a maximum count (both of type long; all count values < 0 mean "no limit") and an ordered list of SortField objects. The intention is that a query API takes a single IPagingSpec parameter, so that it does not need to be extended whenever another paging or sorting aspect is needed. Deliberately no assumption is made about the underlying data store - the mapping of a field name onto a database column, a document field or a Comparator is up to the caller. PagingHelper.getPage (...) applies a specification onto an in-memory collection, as the fallback for all data stores that cannot do it natively. It never modifies the source collection.
  • Added the new method AbstractMapBasedWALDAO.getAllPaged (Predicate, boolean, IPagingSpec, Comparator) that applies a paging specification onto the contained items, as the in-memory implementation of a paged query.

v12.3.5 - 2026-08-12

  • Added the strict version layout major[.minor[.micro]][-qualifier] to Version, consisting of the new methods Version.parseStrictOrNull (String) and Version.getAsStringStrict () plus the new constants Version.STRICT_QUALIFIER_SEPARATOR and Version.NUMERIC_PART_SEPARATOR. Contrary to Version.parse (String) the qualifier is always introduced by the first - character, so that a purely numeric qualifier is retained as such. Version.parse ("1.4-03") returns the version 1.4.3, because the - is treated like a . and 03 ends up as the micro version number, whereas Version.parseStrictOrNull ("1.4-03") returns 1.4.0 with the qualifier 03. This inconsistency of Version.parse (String) only shows up for numeric qualifiers - 1.4-SNAPSHOT and 1.4-RC1 are parsed as expected - and it was left unchanged for backwards compatibility. getAsStringStrict () is the exact inverse of parseStrictOrNull (String), so every emitted string can be read back again.
  • Added the new overload HasInputStream.create (byte [], int, int) to create a multi-read IHasInputStream on a part of a byte array, without having to copy it first.
  • Fixed XML writing to no longer lose the namespace of an attribute whose namespace URI is identical to the default namespace URI that is currently in scope. Such an attribute was written without a namespace prefix and therefore silently ended up in no namespace at all, because the default namespace never applies to attribute names (see https://www.w3.org/TR/xml-names/#defaulting). A namespaced attribute now always gets a non-empty namespace prefix. This affects XMLWriter/XMLSerializer as well as MicroWriter/MicroSerializer.
  • Fixed XML writing of elements without a namespace that are nested inside a default namespace. Previously the invalid namespace declaration xmlns:ns0="" was created - a namespace prefix can never be bound to the empty namespace URI - so that the created XML could not be parsed again. The default namespace is now correctly undeclared using xmlns="" instead.
  • XMLWriterSettings.setUseExistingNamespaceDeclarations (true) now creates the namespace declarations that are missing in the source node, instead of emitting undeclared namespace prefixes. That is relevant for DOM and MicroDOM trees that were created programmatically, because those usually don't carry any xmlns attributes at all. For that purpose the new method AbstractXMLSerializer.NamespaceStack.ensureNamespaceDeclaration (String, String, Map) was added. Together with the fixes above, XMLWriter can now be used instead of the JAXP identity transformer to serialize XML signed documents (e.g. AS4/SOAP messages), as long as setUseExistingNamespaceDeclarations (true) is enabled - the namespace prefixes are part of the canonicalized form and must therefore be retained as-is.
  • AbstractXMLSerializer.NamespaceStack.addNamespaceMapping (String, String) no longer requires a non-empty namespace URI, because the empty namespace URI is needed to undeclare a default namespace.

v12.3.4 - 2026-08-04

  • Extended EHttpMethod with the new QUERY method according to RFC 10008. QUERY is idempotent (isIdempodent ()) and carries a payload in the request body (isPayloadInBody ()).
  • Added new constants in CHttpHeader for X-Forwarded-*
  • ConfigWithFallback no longer logs a "please rename" warning for outdated configuration keys that were resolved from a system property or an environment variable, as these sources usually cannot be renamed as easily as e.g. a configuration file.
  • Added iteration to the cache API. The new method ICache.iterateCacheKey (Consumer) invokes the provided consumer for each non-expired cache key, and ICache.iterateCache (BiConsumer) does the same for each non-expired key and value combination. Both are implemented in AbstractMapBasedCache (and therefore in ManualCache) as well as in ProviderCache and Cache. Cache implementations that map the cache key to a different storage key (MappedKeyManualCache, MappedKeyProviderCache and MappedCache) throw an UnsupportedOperationException, because they don't retain the original keys - MappedKeyManualCache.iterateStorageCacheKey (Consumer) and MappedKeyManualCache.iterateStorageCache (BiConsumer) were added to iterate the storage keys instead. Note: this is a breaking change for classes implementing ICache outside of ph-commons.
  • Added the two convenience methods getAllCacheKeys () (returning a copy of all non-expired cache keys) and removeFromCacheIf (Predicate) (removing all entries with a matching key in one go) to AbstractMapBasedCache. All key iteration happens under the write lock, because the iterators of the underlying soft maps are not thread-safe. Therefore the provided consumer or predicate must not modify the cache.

v12.3.3 - 2026-07-15

  • Updated to BouncyCastle 1.85 (fixing a myriad of CVEs)
  • JSON writing now escapes all control characters (U+0000-U+001F) as \u00XX per RFC 8259. Previously control characters like 0x01 were written raw, producing output that strict JSON parsers reject.
  • parsing a JSON number with a huge positive exponent like 1e999999999 no longer lets an ArithmeticException escape the parser; it is now a regular, recoverable parse error.
  • added the new parser setting maxExponent (default 100000, aligned with Jackson's MAX_BIGINT_SCALE_MAGNITUDE) that limits the absolute value of a numeric exponent, to bound the memory a single number token can force to be allocated. Configurable via JsonReader.builder ().maxExponent (int).
  • JsonEscapeHelper.jsonUnescape now throws a documented IllegalArgumentException for malformed input (a trailing escape char or an incomplete \uXXXX sequence) instead of an ArrayIndexOutOfBoundsException or StringIndexOutOfBoundsException.
  • reading a JSON object with a duplicate key now logs a warning (the last value still wins, as before).
  • fixed JsonStringBuilder.backup (int) to invalidate the cached String, so getAsString () no longer returns a stale value after a backup.

v12.3.2 - 2026-07-05

  • Made the soft maps AbstractSoftMap, SoftHashMap and SoftLinkedHashMap thread-safe to avoid weird effects in cache eviction. Previously the maps were completely unsynchronized, although none of their operations is truly read-only: get() removes garbage collected entries, size() drains the internal ReferenceQueue, and SoftLinkedHashMap uses access order, so every read reorders the internal linked list. Concurrent get() calls (e.g. by multiple threads holding only a shared read lock, as in the ph-cache module) could therefore corrupt the internal map - for SoftLinkedHashMap typically by creating a cycle in the internal doubly linked list, so that a later iteration (like evictExpired()) never terminated while holding the cache write lock, blocking all other cache access.
    • All map operations are now internally synchronized. Note that even seemingly read-only operations like get() and size() acquire the internal write lock, for the reasons outlined above.
    • Iterators and the collection views (entrySet(), keySet(), values()) remain unsynchronized - as with Collections.synchronizedMap() the caller must ensure that the map is not modified concurrently while iterating.
    • containsKey() is now O(1) and consistent with get(): entries whose value was garbage collected count as "not contained". The same applies to the new containsValue() implementation.
    • Fixed entrySet().contains() and entrySet().remove() which always returned false because they compared the internal SoftValue wrappers by identity. Additionally each such call registered a temporary SoftValue with the internal ReferenceQueue, which could silently remove a live map entry once the probe value was garbage collected.
    • entrySet().add() and addAll() now throw an explicit UnsupportedOperationException, in line with the Map.entrySet() contract. They never worked before either - the JDK entry set already rejected the addition.
    • The callbacks AbstractSoftMap.onEntryRemoved() and SoftLinkedHashMap.onRemoveEldestEntry() are now invoked while the internal write lock is held.
  • AbstractMapBasedCache.evictExpired() no longer throws a NullPointerException when a cached value was garbage collected from the internal soft map but the stale entry was not yet cleaned up. Such stale entries are now dropped during the sweep, but are deliberately not counted as expired (neither in the return value nor in the $expired statistics counter).
  • The map returned by AbstractMapBasedCache.createCache() MUST be thread-safe, because it may be accessed by multiple threads concurrently holding only the cache's read lock. The default soft maps fulfill this requirement; custom overrides need to be checked.
  • Security by default in the external XML resource resolvers: remote URL schemes are no longer resolved unless explicitly allowed, to prevent Server Side Request Forgery (SSRF). Class path and file based resolution is unaffected, so setups where all XML Schemas and XSLT documents reside locally (the common case) keep working without any change.
    • Added the new helper class com.helger.xml.XMLResourceSchemeHelper that decides whether a resolved resource may be accessed, based on its URL scheme. The schemes http, https, ftp and ftps are considered remote network schemes and are blocked by default; local schemes (file, jar, classpath, OSGi bundle, ...) and non-URL based resources are always considered safe.
    • SimpleLSResourceResolver now blocks resolved resources with a remote URL scheme by default, preventing SSRF via XML Schema xs:import/xs:include or external entities. Use the new method setAllowedRemoteSchemes(String...) (plus getAllAllowedRemoteSchemes()) to explicitly allow specific remote schemes. A blocked resolution is logged as a warning and returns null, so the parser applies its own (restricted) default resolution.
    • DefaultTransformURIResolver applies the same check to prevent SSRF via XSLT document(), xsl:import or xsl:include, with the same new setAllowedRemoteSchemes(String...)/getAllAllowedRemoteSchemes() methods. The scheme is checked before exists() is called, because exists() may already open a remote connection.
    • XMLTransformerFactory.makeTransformerFactorySecure() now always sets the ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_STYLESHEET attributes - previously they were left untouched when no allowed scheme was provided. Providing no scheme now denies all external DTD and stylesheet access. TransformerFactory implementations that don't support these attributes no longer fail - the IllegalArgumentException is caught and logged as a warning instead.
    • Added a security warning to the Javadoc of DefaultEntityResolver: it resolves the passed system ID without restrictions and must not be installed when parsing untrusted XML. With the default (secure) parser configuration of XMLFactory, DOCTYPE declarations and external entities are disallowed, so this resolver is not invoked for external entities.
  • XMLEmitter.onProcessingInstruction() now throws an IllegalArgumentException if the processing instruction target or data contains the PI end marker ?>, as that would allow breaking out of the processing instruction (XML injection).
  • Deprecated PasswordHashCreatorSHA512 - it performs a single, unsalted SHA512 pass and is therefore vulnerable to brute force and rainbow table attacks. Use PasswordHashCreatorPBKDF2_SHA256_600000_48 or PasswordHashCreatorBCrypt for hashing new passwords; the class is kept only to verify password hashes that were created with it in the past.

v12.3.1 - 2026-07-01

  • Added a builder for TrustedCAChecker with a new synchronizedRevocationCheck option and deprecated the existing constructors for removal
  • Removed ph-telemetry again - resides now in a separate top-level project https://github.com/phax/ph-telemetry/

v12.3.0 - 2026-06-10

  • Extended IJsonObject with a new replaceKey (String, IJson) method (and an Object overload) that replaces the value of an existing key while preserving the original insertion order of the keys. Returns EChange.CHANGED when an existing key was replaced and EChange.UNCHANGED when the key was not present (no implicit insert). Useful e.g. to replace a nested IJsonObject with a plain IJsonValue without losing the key's position in the surrounding object.
  • Added time-based expiration to ph-cache. Each cache may now be configured with a java.time.Duration time-to-live; entries past their TTL are treated as a cache miss on the next read, removed under the write lock, and refetched via the value provider. A new cache:<name>$expired statistics counter tracks the number of expired entries that were dropped (distinct from $remove and $clear). Caches without a TTL behave exactly as before.
    • New class com.helger.cache.impl.CacheEntry<V> — immutable value+expiration holder used as the internal storage type, replacing Wrapper<V>. A null expiration means "never expires". Provides ofNoExpiration, ofExpirationDateTime and ofTimeToLive factories. Mirrors the shape of ExpiringObject but lives in ph-cache to avoid a circular dependency on ph-datetime.
    • MappedCache gained a new constructor overload that takes a @Nullable Duration aTimeToLive. Existing constructors delegate with null (no behavior change). New accessors getTimeToLive(), hasTimeToLive(), setClockSupplier(Supplier<LocalDateTime>) and getClockSupplier(). The clock supplier defaults to LocalDateTime.now(ZoneOffset.UTC) and can be replaced by tests for deterministic expiration assertions.
    • Cache gained a corresponding constructor overload accepting a @Nullable Duration aTimeToLive.
    • Common configuration (name, maxSize, allowNullValues, expireAfterWrite(Duration), evictionInterval(Duration), clockSupplier(Supplier<LocalDateTime>)) was lifted into the new package-private base class com.helger.cache.impl.CacheBuilderBase (extending IGenericImplTrait). CacheBuilder (for Cache), the new ProviderCacheBuilder (for ProviderCache) and the new ManualCacheBuilder (for ManualCache) all extend this base and only contribute their type-specific bits (e.g. valueProvider(Function) for the provider-driven variants). Each build() rejects configurations where an eviction interval is set without a positive TTL (there would be nothing to evict). Zero or negative durations are treated as "disabled".
    • ManualCache.builder() was added and returns a ManualCacheBuilder. ProviderCache.builder() now returns a ProviderCacheBuilder (previously a generic CacheBuilder). The previously available CacheBuilder.buildManualCache() and CacheBuilder.buildProviderCache() convenience methods were removed in favor of the dedicated builders; callers should switch to ManualCache.builder() / ProviderCache.builder() (or to new ManualCacheBuilder<>() / new ProviderCacheBuilder<>() directly).
    • Added IMutableCache.evictExpired() returning the number of removed expired entries. For caches without a TTL this is a no-op returning 0.
    • CRLCache was migrated off ExpiringObject<CRL> and now stores CRL directly in a ManualCache<String, CRL> configured with the caching duration. The half-duration fallback ("re-fetch failed, keep the previous CRL for cachingDuration/2") is now expressed via the new putInCache(K, V, Duration) overload. Public API of CRLCache is unchanged.
    • Breaking change for subclasses of MappedCache: the storage type of the protected methods getFromCacheNoStats(...), getFromCacheNoStatsNotLocked(...), putInCacheNotLocked(...) and createCache() changed from Wrapper<VALUETYPE> to CacheEntry<VALUETYPE>. External subclasses need to recompile against the new signatures. The public IMutableCache / Cache / CacheBuilder API stays source-compatible.
  • CertificateRevocationCheckerDefaults gained freezeDefaults() and isDefaultsFrozen(). After freezeDefaults() is called, every setter on the class (setDefaultCRLCache, setRevocationCheckMode, setExceptionHdl, setSoftFailExceptionHdl, setAllowSoftFail, setExecuteInSynchronizedBlock, setCacheRevocationCheckResults) throws IllegalStateException. This is a defence-in-depth trust-boundary harden: applications can call freezeDefaults() once during startup, after all legitimate configuration, to refuse any later (possibly malicious or accidental) attempt to swap the process-wide CRL cache or alter the revocation defaults. The freeze is irreversible by design. Note: this protects the defaults registry; it does not freeze a CRLCache instance whose reference is already shared - the new Javadoc on CRLCache.setCRLOfURL(String, CRL) explicitly calls out that method as a privileged API.
    • Added the singleton com.helger.cache.eviction.CacheEvictionScheduler providing opt-in shared background eviction. One process-wide daemon thread (ph-cache-evictor-%d) serves all registered caches; the underlying ScheduledExecutorService is started lazily on the first register(IMutableCache, Duration) call and shut down automatically when the last cache is unregistered. Per-cache intervals are supported. A failing evictExpired() of one cache is caught and logged so it cannot stop the other caches. CacheCleanUpRegistrarSPI now also calls CacheEvictionScheduler.shutdown() during library cleanup.
  • Relaxed ExpiringObject to accept a @Nullable LocalDateTime expiration in its constructor. A null expiration means "never expires", which aligns the implementation with the contract already documented on IExpirable.getExpirationDateTime(). Existing code that passes a non-null expiration continues to work unchanged
  • Added IMutableCache.putInCache as an explicit method

v12.2.6 - 2026-05-18

  • Updated JAXB to 4.0.8
  • Deprecated EErrorLevel.SUCCESS (and SingleError.builderSuccess()) - success is not really an error level. Use INFORMATION instead. Marked as forRemoval = true, since = "12.2.6".
  • Added new submodule ph-telemetry providing a vendor-neutral tracing abstraction. Exposes Telemetry (static facade), ITelemetrySpan, ITelemetryTracerSPI and ETelemetrySpanKind under com.helger.telemetry. Resolves the registered ITelemetryTracerSPI via ServiceLoader on first use and falls back to a built-in no-op tracer if none is on the classpath, so callers can write tracing code unconditionally. Span kinds mirror OpenTelemetry's SpanKind so an OTel-backed implementation can translate one-to-one. Convenience helpers Telemetry.withSpan (name, kind, Function) and Telemetry.withSpanVoid (name, kind, Consumer) start a span, record exceptions on it, and end it in a finally block.

v12.2.5 - 2026-04-30

  • Added IConfig.getAsConfigDuration (String) and IConfig.getAsConfigDuration (String, Consumer<String>) for reading configuration values directly as java.time.Duration. The optional Consumer<String> is invoked once with a descriptive message on parse failure (so it can e.g. be logged); missing or blank values return null without invoking it.
  • Added the reusable parser com.helger.config.value.parser.ConfigDurationParser accepting human-friendly compound expressions like 5ms, 2d5m23ms, or 3d 4h 22m 5s. Supported units are ns, us, ms, s, m, h, d. Each segment may carry its own optional sign (e.g. 5h -10m = 4h 50m). Whitespace between segments, between sign and number, and between number and unit is permitted but not required. Unit suffixes are matched case-insensitively. Decimal values are not accepted. Inputs longer than ConfigDurationParser.MAX_VALUE_LENGTH (100) characters are rejected without further processing to bound the parser's work and mitigate denial-of-service / overflow attacks via overly long configuration values. The parser never throws — failures are reported via the error handler and a null return value.

v12.2.4 - 2026-04-29

  • Added new entries to EMessageDigestAlgorithm for the message digest algorithms guaranteed to be available on every Java 17+ runtime via the SUN provider: SHA_512_224 (SHA-512/224), SHA_512_256 (SHA-512/256), SHA3_224 (SHA3-224), SHA3_256 (SHA3-256), SHA3_384 (SHA3-384) and SHA3_512 (SHA3-512).
  • Hardened the CRL download path used by AbstractRevocationCheckBuilder:
    • IURLDownloader.createDefault() now sets a connect timeout of 10 seconds and a read timeout of 60 seconds. Previously no timeouts were configured, so a slow or unreachable CRL distribution point could block revocation checks indefinitely.
    • Added IURLDownloader.createDefault(int nConnectTimeoutMS, int nReadTimeoutMS) to override the defaults, plus the new constants DEFAULT_CONNECT_TIMEOUT_MS and DEFAULT_READ_TIMEOUT_MS.
    • Added new class CRLAllowList with case-insensitive prefix matching to restrict which CRL distribution point URLs may be downloaded. Mitigates SSRF and unbounded-download risk against attacker-controlled certificates. An empty allow list keeps the legacy behavior of allowing every HTTP(S) URL.
    • CRLDownloader now exposes allowList() and consults it before each download. Refused URLs are logged with a warning. Non-HTTP/HTTPS URLs are now also logged with a warning instead of being dropped silently.
  • AbstractRevocationCheckBuilder.build() no longer returns ERevoked.REVOKED when CRL retrieval fails. Previously a missing CRL (e.g. unreachable distribution point) was indistinguishable from a real revocation, which could wrongly block valid certificates during a CRL endpoint outage. The check now returns the new ERevoked.UNKNOWN value instead. The detection covers both directly observable CRL download failures (every distribution point of the certificate returned null) and the JDK-level CertPathValidatorException with reason UNDETERMINED_REVOCATION_STATUS.
  • Added new enum value ERevoked.UNKNOWN with isRevoked() returning false (so existing callers do not start treating unverified certificates as revoked) and a new isUnknown() accessor.
  • Added default methods IRevokedIndicator.isUnknown() and IRevokedIndicator.isKnown() so callers can distinguish "verified not revoked" from "could not be verified".
  • Propagated the UNKNOWN revocation state through the higher-level certificate check API. Previously a CRL download failure would silently surface as ECertificateCheckResult.VALID when revocation caching was enabled, because the cache only exposed a boolean isRevoked view.
    • Added new enum value ECertificateCheckResult.REVOCATION_STATUS_UNKNOWN with isValid() returning false.
    • Added new method RevocationCheckResultCache.getRevocationStatus(X509Certificate) returning the full ERevoked status. The existing isRevoked(X509Certificate) is preserved and now delegates to it.
    • CertificateHelper.checkCertificate and TrustedCAChecker.checkCertificate now return REVOCATION_STATUS_UNKNOWN whenever the underlying revocation check could not determine the certificate status.

v12.2.3 - 2026-04-27

  • Fixed a regression from 12.2.0 that configuration properties resolved via IConfigWithFallback.getAs...OrFallback did not get their variables replaced. See phoss-smp#478 - thx @RohiNof

v12.2.2 - 2026-04-26

  • Added new setting XMLWriterSettings.setUseExistingNamespaceDeclarations(boolean) to preserve existing xmlns: attributes from the DOM as-is during serialization instead of filtering and rebuilding them via the namespace stack. This is important for documents like XSLT where namespace prefixes are referenced inside attribute values (e.g. xs:boolean, u:gln) and would otherwise be silently dropped. Default is false (backwards compatible). Supported by both XMLWriter (W3C DOM) and MicroWriter (Micro DOM).
  • Added new IMicroReaderSettings accepting boolean bSaveNamespaceDeclarations to preserve xmlns: attributes as regular attributes on IMicroElement during SAX parsing. Use in combination with XMLWriterSettings.setUseExistingNamespaceDeclarations(true) for round-trip fidelity of namespace declarations.
  • Added new method MicroSAXHandler.setSaveNamespaceDeclarations(boolean) to control whether namespace declarations are stored as attributes during SAX parsing.
  • Removed OSGI bundling

v12.2.1 - 2026-04-21

  • ERevocationCheckMode now implements IHasID<String> and provides static lookup methods
  • Fixed XXE vulnerability in XMLSchemaCache.createXSDSchemaFactory() - now sets ACCESS_EXTERNAL_DTD to empty and ACCESS_EXTERNAL_SCHEMA to "file" only
  • Fixed potential denial-of-service in StreamHelper.readSafeUTF() by adding a maximum allocation size check (MAX_SAFE_UTF_BYTES = 64 MB)
  • Added new class PasswordHashCreatorPBKDF2_SHA256_600000_48 with 600000 iterations (OWASP 2023 recommendation)
  • Deprecated PasswordHashCreatorPBKDF2_SHA256_1000_48 - use PasswordHashCreatorPBKDF2_SHA256_600000_48 for new password hashing
  • Added new overload SerializationHelper.getDeserializedObject(byte[], ObjectInputFilter) accepting an ObjectInputFilter
  • Deprecated SerializationHelper.getDeserializedObject(byte[]) without a filter
  • Extended AbstractConfigurationSource.isSecretKey() to also detect keys containing "secret", "token", "apikey", "api_key", "api-key" and "credential"
  • Fixed potential resource leak in AbstractSimpleDAO and AbstractWALDAO when getXMLWriterSettings() throws before MicroWriter.writeToStream is called
  • Improved XML comment formatting

v12.2.0 - 2026-04-19

  • Updated to BouncyCastle 1.84 (fixing CVE-2026-5588, CVE-2025-14813 and CVE-2026-5598)
  • Added support for Java 26 in EJavaVersion
  • Added SHA-256 and SHA-256-sess algorithm support to HttpDigestAuth per RFC 7616
    • New constants ALGORITHM_SHA_256 and ALGORITHM_SHA_256_SESS
    • New method isSupportedAlgorithm(String) to check for supported algorithms
    • DigestAuthClientCredentials now accepts both 32-char (MD5) and 64-char (SHA-256) response hashes
    • MD5 remains the default algorithm for backwards compatibility
  • Added new method Config.getValue (ConfiguredValue)
  • Added new method IConfig.containsConfiguredValue (String) and IConfigurationValueProvider.containsConfigurationValue (String) to check for configuration property existence without retrieving the value.
  • Added new method IConfigWithFallback.getAsBooleanOrFallback (String, boolean, String...) for boolean fallback resolution
  • Added new classes ConfigSubset and ConfigSubsetWithFallback to pass on only a limited subset of configuration properties
  • Changed IConfigKeyOutdatedNotifier.onOutdatedConfigurationKey to also receive the IConfigurationSource that matched the outdated key
  • Simplified IConfigWithFallback.getAsIntOrFallback and getAsLongOrFallback — removed the bogus sentinel parameter; now only takes primary key, default value, and fallback keys
  • Refactored ConfigWithFallback fallback methods (getAsStringOrFallback, getAsBigDecimalOrFallback, getAsCharArrayOrFallback) to delegate through getConfiguredValueOrFallback for consistent behavior

v12.1.5 - 2026-03-16

  • Deprecated IToBooleanFunction in favour of Predicate
  • Added new method ConfigFactory.addProfilePropertiesSources which enables the loading of properties using the Spring profile pattern. See #40
  • Added new constant DoNothingJsonParserHandler.INSTANCE
  • Added new overload Wrapper.get(Predicate)
  • Updated ph-http constants to align with RFC 9110 (HTTP Semantics, 2022) and related specs:
    • Added new HTTP status codes: 102 Processing, 207 Multi-Status, 208 Already Reported, 226 IM Used, 423 Locked, 424 Failed Dependency, 425 Too Early
    • Renamed status codes per RFC 9110: 302 Found (HTTP_FOUND), 413 Content Too Large (HTTP_CONTENT_TOO_LARGE), 414 URI Too Long (HTTP_URI_TOO_LONG), 416 Range Not Satisfiable (HTTP_RANGE_NOT_SATISFIABLE) — old constant names are deprecated
    • Deprecated status codes 305 Use Proxy and 306 Switch Proxy per RFC 9110
    • Fixed getHttpResponseMessage() reason phrases to match RFC 9110 text (including 422 Unprocessable Content)
    • Added missing RFC 9110 standard headers: Accept-Ranges, Content-Range, Expect, If-Range, Max-Forwards, Proxy-Authenticate, Range, TE, Trailer, Upgrade, Via
    • Added modern security headers: Permissions-Policy, Cross-Origin-Embedder-Policy, Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy, Alt-Svc, Priority
    • Deprecated obsolete headers: Warning (removed in RFC 9111), Pragma (deprecated in RFC 9111), DNT, X-UA-Compatible, PICS-Label, Content-Script-Type, Content-Style-Type, Window-target, Ext-cache, UA, x-device-user-agent
    • Added HTTP/3.0 to EHttpVersion (RFC 9114)
    • Updated Javadoc references from obsolete RFCs to RFC 9110

v12.1.4 - 2026-03-10

  • Added constant CHttp.HTTP_UNPROCESSABLE_CONTENT and deprecated CHttp.HTTP_UNPROCESSABLE_ENTITY
  • Deprecated old CSP HTTP headers starting with X-
  • Added interface method IConfig.getConfigurationValueProvider ()
  • Added enum EConfigSourceTypeName and EConfigSourceType now has a getDisplayText() method
  • TrustedCAChecker.checkCertificate now always uses the revocation cache if instructed to do so - there is no dependency on the check date
  • TrustedCAChecker got a new constructor that provides more configuration flexibility
  • Added some missing JavaDocs for public methods

v12.1.3 - 2026-02-20

  • Added new class UUID5Helper to create UUID v5 objects
  • Classes AbstractPersisting(Int|Long)IDFactory got the possibility to modify the reserve count
  • Classes File(Int|Long)IDFactory will now try to resolve inconsistencies automatically on init
  • Added new constant CMimeType.APPLICATION_DNS_MESSAGE

v12.1.2 - 2026-01-27

  • Added static Wrapper helper methods empty and of
  • The PDTWebDateHelper XSD based formatting methods, can now print up to nanoseconds (fraction digits) precision
  • Extended class Wrapper with simple get methods to access data of the wrapped object
  • If the CRLCache is re-fetching a CRL which is invalid, but the previous value is valid, the previous CRL is kept for some more time
  • Changed the default CertificateRevocationCheckerDefaults.DEFAULT_REVOCATION_CHECK_MODE to use CRL_BEFORE_OCSP instead of only CRL

v12.1.1 - 2025-12-16

  • Updated to BouncyCastle 1.83
  • Added methods CertificateHelper.getPrincipalTypeValueOrNull
  • Added additional CertificateHelper.getPrincipalTypeValue overload
  • Added methods StringHex.getHexEncodedByteArray
  • Deprecated the usage of XML 1.1 in EXMLVersion and EXMLSerializeVersion - see https://github.com/w3ctag/obsoletion/issues/6 for details
  • Added IMissingLocaleHandler.NULL_INSTANCE as a constant
  • Added new class CertificateDecodeHelper to help decode certificates more safely.

v12.1.0 - 2025-11-02

  • Changed from Jakarta Nullable annotations to JSpecify. See #54 - thx @vlsi. Backward incompatible change.
  • Extracted submodule ph-csv containing the CSV handling. This also changed the package of the classes from com.helger.commons.csv to com.helger.csv. Backward incompatible change.
  • SafeXMLStreamWriter now correctly honours XMLWriterSettings.SerializeXMLDeclaration setting

v12.0.4 - 2025-10-19

  • Reverted back from Map.entry to new MapEntry<> due to null-issues

v12.0.3 - 2025-10-03

v12.0.2 - 2025-09-22

  • Updated to BouncyCastle 1.82
  • Made method BigHelper.equalValues null-safe
  • Added overloads of GenericReflection.newInstance with a custom Exception consumer

v12.0.1 - 2025-09-19

  • Added overloads SimpleUrl.add (String, int|long)
  • Added possibility to customize GenericJAXBMarshaller.xmlWriterSettings

v12.0.0 - 2025-08-24

  • Extracted new submodule ph-url
  • Added new annotation UsedInGeneratedCode
  • Added new methods to JAXBHelper to handle JAXB xs:any mappings
  • Renamed all methods in class TestHelper so that it uses an uppercase C in hashCode or HashCode
  • Renamed class URLCodec to RFC3986Codec
  • Renamed interface IPrimitiveConverterTo to ITypeConverterTo
  • Renamed interface IHasPrimitiveConverter to IHasTypeConverterTo and renamed method to getTypeConverterTo()
  • Added new trait interface IGenericMapAdderTrait
  • Renamed ICommonsMap.addAll to putAllIfNotNull
  • Added new class TypeConverterToAny
  • Renamed class PrimitiveConvererToIJson to TypeConverterToIJson
  • Renamed package com.helger.base.traits to com.helger.base.trait
  • Renamed ICommonsIterable.getCount methods to size
  • Interface ICommonsIterable already implements IHasSize
  • Extracted class URLCleanser and moved URLHelper to ph-base
  • Moved class URNHelper to ph-base
  • Added new class URLBuilder to build ISimpleURL objects
  • Added new interface IMutableURLData to capture mutable URL data
  • Added new class ReadOnlyURL as a read-only implementation of ISimpleURL
  • Deleted classes IMutableURLParameterList, IURLParameterList and URLParameterList in favour of ICommonsList <URLParameter>

v12.0.0-rc1 - 2025-08-20

  • The baseline is now Java 17 - older Java versions are no longer supported
  • Uses parent-pom v3.0.0
  • Completely restructured the libraries, so that smaller, functional JARs are created instead of one big ph-commons JAR
    • Added new submodule ph-annotations including the contents of JSR305
      • Only Nonnull and Nullable are taken from the jakarta.annotation package instead
    • Extracted new submodules ph-base, ph-unittest-support, ph-typeconvert, ph-statistics, ph-cache, ph-io, ph-unittest-support-ext, ph-text, ph-diagnostics, ph-config-json, ph-mime and ph-http
    • Removed submodule ph-less-commons - the remainders ended up in ph-commons
    • Integrated ph-web/ph-http module content into this repository
    • If you are using JSON for configuration, make sure to include the new submodule ph-config-json as well
  • Movings
    • Moved all annotations from package com.helger.commons.annotation to submodule ph-annotations
    • Moved basically all classes back and forth between the modules - re-organizing your imports should do 95% of the work
    • The ArrayHelper.EMPTY_* constants were moved to class CGlobal
    • Moved constant INITIAL_HASHCODE from HashCodeGenerator to HashCodeCalculator
    • Moved methods CollectionHelper.new* to CollectionHelperExt.create*
  • Removals
    • Removed classes SecurityManagerHelper, ReflectionSecurityManager, IPrivilegedAction and AccessControllerHelper because the Java SecurityManager is deprecated for removal
    • Removed deprecated package com.helger.jaxb.builder
    • Removed all methods marked as deprecated for removal
    • Removed class IJsonParserCustomizeCallback
    • Removed method ABNF.isHexDigitCaseInsensitive in favour of isHexDigit (was misreading the RFC)
  • Renamings
    • Renamed class SingleError.AbstractBuilder to AbstractSingleErrorBuilder
    • Renamed class SingleError.Builder to SingleErrorBuilder
    • Renamed class Option.Builder to OptionBuilder
    • Renamed class KeyStoreAndKeyDescriptor.KeyStoreAndKeyDescriptorBuilder to KeyStoreAndKeyDescriptorBuilder
    • Renamed class KeyStoreDescriptor.KeyStoreDescriptorBuilder to KeyStoreDescriptorBuilder
    • Renamed class TrustStoreDescriptor.TrustStoreDescriptorBuilder to TrustStoreDescriptorBuilder
    • Renamed class BasicThreadFactory.Builder to BasicThreadFactoryBuilder
    • Renamed class JsonReader.Builder to JsonReader.JsonBuilder
    • Renamed methods IMicroNode.append* to add*
    • Renamed class ABNF to RFC5234Helper
    • Renamed class ByteBuffersInputStream to MultiByteBufferInputStream
    • Renamed class CommonsTestHelper to TestHelper
  • Additions
    • Added classes (I)JsonParserSettings
    • Added new class CacheBuilder
    • Added new constants
      • CMimeType.APPLICATION_EDIFACT
      • CMimeType.APPLICATION_EDI_X12
    • Via FileHelper.setWarnOnIssues the warnings can be enabled or disabled
    • Added new interface IWriteToWriter
    • Extended IAppendable and HashCodeCalculator with overloads that take arrays with offset and length
  • Incompatible changes
    • EqualsHelper and HashCodeGenerator no longer work based on the SPI based registration. Instead the non-default cases need to be handled manually
    • By default the global debug mode (GlobalDebug) is disabled
    • Extended the JsonReader builder to include all the settings directly
    • Extracted all collection related methods from EqualsHelper to CollectionEqualsHelper
    • Extracted functionality from StringHelper into new classes: StringHex, StringImplode, StringRemove, StringReplace
    • Extracted the BigDecimal and BigInteger functionality from MathHelper to BigHelper
    • Extracted functionality from CollectionHelper into new classes: CollectionFind, CollectionSort
    • The following SPI interfaces were changed:
      • com.helger.commons.thirdparty.IThirdPartyModuleProviderSPI -> com.helger.base.thirdparty.IThirdPartyModuleProviderSPI
    • The methods IJsonObject.addJson where renamed to add only
  • Deprecations
    • StringHelper.hasText was deprecated in favour of StringHelper.isNotEmpty
    • StringHelper.hasNoText was deprecated in favour of StringHelper.isEmpty

v11.2.7 - 2026-07-17 (backport)

  • Updated to BouncyCastle 1.85
  • Updated to JAXB 4.0.9

v11.2.6 - 2025-06-10

  • Updated to BouncyCastle 1.81

v11.2.5 - 2025-05-19

  • Fixed a bug in ConfigWithFallback.getAsCharArrayOrFallback so that fallbacks were performed in the wrong scenario

v11.2.4 - 2025-05-14

  • Increased maximum string length for IDs created by GlobalIDFactory. See #45 - thx @andreasa-winenet
  • Added new class StringIDFromUUIDFactory using random UUIDs as String IDs

v11.2.3 - 2025-05-13

  • Added support for Java 24
  • The default XML entity expansion limit for Java 24+ is now correctly identified as 2500
  • All tests are now also running on Java 24

v11.2.2 - 2025-05-13

  • Using the correct locale in LoadedKey.getLoadError and LoadedKeyStore.getLoadError

v11.2.1 - 2025-04-11

  • Added method AbstractMemoryReadableResource.setPath to define a path different from the empty string
  • Added new enum ECertificateCheckResult as an enumeration contain X.509 certification validation results
  • Added new method CertificateHelper.checkCertificate to verify if an X.509 certificate is valid in several aspects
  • Added new class TrustedCAChecker to check if a certificate is based on one of certain CAs
  • Added new methods to CertificateHelper to easily access the CN and the O part of a certificate principal

v11.2.0 - 2025-02-03

  • Extended ISAXReaderSettings to include the possibility to provide a custom SAXParserFactory
  • Extended the class EmailAddressHelper with a method isValidForSimplePattern to test for email addresses that eventually contain Unicode characters
  • Added HasInputStream.create overload with byte[] parameter
  • Added method IExpirable.isExpiredIn
  • Added interface IURLDownloader to ph-commons
  • Added class ExpiringObject to ph-datetime
  • Added classes TrustedCACertificates, CRLCache, CRLDownloader, CRLHelper, AbstractRevocationCheckBuilder, CertificateRevocationCheckerDefaults, ERevocationCheckMode, ERevoked, IRevokedIndicator and RevocationCheckResultCache to ph-security
  • Added method KeyStoreHelper.getAllTrustedCertificates

v11.1.12 - 2025-01-21

  • Updated to BouncyCastle 1.80
  • Made sure, that the XML "Secure processing" flag is set anyway in XMLFactory.createDefaultDocumentBuilderFactory in case an external XML parser is in the classpath
  • Extracted the methods XMLFactory.defaultCustomize(DocumentBuilder|SAXParser|Transformer)Factory to allow external factories to be secured as well

v11.1.11 - 2024-12-05

  • Removed bcprov-ext-jdk18on from the parent pom, as seems to be included in bcprov-jdk18on instead
  • Added support for configuration variable default values when used in the form ${property:default}
  • Added additional IMicroNode.appendText overloads for boolean, int and long
  • Deprecated EXMLSerializeIndent.INDENT_ONLY as well as .getWithIndent() and .getWithoutAlign()

v11.1.10 - 2024-11-08

  • Added new method IConfigWithFallback.getAsCharArrayOrFallback
  • Added new interfaces IKeyStoreDescriptor, IKeyStoreAndKeyDescriptor and ITrustStoreDescriptor in ph-security
  • Added new classes KeyStoreDescriptor, KeyStoreAndKeyDescriptor and TrustStoreDescriptor in ph-security
  • Added new method KeyStoreHelper.iterateKeyStore

v11.1.9 - 2024-10-30

  • Updated to BouncyCastle 1.79.0
  • Added new annotation ChangeNextMajorRelease
  • Deprecated KeyStoreHelper.loadKeyStoreDirect methods with String password in favour of versions with char[] password
  • Added KeyStoreHelper.loadKeyStore methods with char[] as password type
  • Deprecated KeyStoreHelper.loadKeyStore methods with String password in favour of versions with char[] password
  • Added support for JDK 22 and JDK 23 in EJavaVersion

v11.1.8 - 2024-09-10

  • Made sure that HttpHeaderMap.getUnifiedValue unified values combine all whitespaces into a single space

v11.1.7 - 2024-09-10

  • Updated to BouncyCastle 1.78.1
  • Added method CertificateHelper.isCA
  • Added additional Commons...Map constructor overloads
  • Added method EqualsHelper.identityDifferent
  • Made sure that HttpHeaderMap.getUnifiedValue unified values combine all \r, \n and \t into a single space
  • The method EnvVarHelper.getUnifiedSysEnvName can now also remove invalid characters on demand

v11.1.6 - 2024-04-09

  • Updated to BouncyCastle 1.78. This fixes CVE-2024-29857, CVE-2024-30171, CVE-2024-30172 and CVE-2024-301XX. See PR #43 - thx @problemzebra2

v11.1.5 - 2024-03-27

  • Added new interface IHasSizeLong
  • Added new interface methods IHasInputStream.withInputStreamDo and IHasInputStream.withBufferedInputStreamDo
  • Added new interface method IHasByteArray.isPartialArray
  • Added build compatibility with Java 21
  • Deprecated method ICommonsList.getFirst() in favour of ICommonsList.getFirstOrNull() because of clash with JDK 21 API extension. See issue #42
  • Deprecated method ICommonsList.getLast() in favour of ICommonsList.getLastOrNull() because of clash with JDK 21 API extension. See issue #42
  • Deprecated method ICommonsList.removeFirst() in favour of ICommonsList.removeFirstOrNull() because of clash with JDK 21 API extension. See issue #42
  • Deprecated method ICommonsList.removeLast() in favour of ICommonsList.removeLastOrNull() because of clash with JDK 21 API extension. See issue #42

v11.1.4 - 2024-02-15

  • Added support to detect Java 21. See PR #39 - thx @janwytze
  • Added "LTS" flag on the EJavaVersion enum entries
  • The default ErrorTextProvider was slightly changed to put the error field in brackets as well
  • Class ErrorTextProvider.FormattableItem is no longer final
  • Added new interface method IError.getAsStringLocaleIndepdent ()
  • Added new interface IConditionalLogger

v11.1.3 - 2023-11-15

  • Updated to parent POM 2.0.5
  • Updated to SLF4J 2.0.9
  • Updated to BouncyCastle 1.77. See PR #38 - thx @problemzebra2
  • Fixed spelling error in EXMLParserProperty.JAXP_SCHEMA_SORUCE
  • Removed final from class Version
  • Added new method IJsonArray.addIfNotEmpty
  • Added new method IJsonObject.addIfNotEmpty

v11.1.2 - 2023-08-16

  • Added new keystore type BKS to support the BouncyCastle internal keystore format

v11.1.1 - 2023-08-10

  • Updated to BouncyCastle 1.76
  • Extended KeyStoreHelper APIs to be able to provide custom security Provider in it.
  • Renamed CertificateHelper.getWithPEMHeader to getCertificateWithPEMHeader
  • Added overload of CertificateHelper.convertStringToCertficate

v11.1.0 - 2023-07-31

  • Removed the explicit SuppressFBWarnings class in favour of an optional include of spotbugs-annotations. See issue #36
  • Changed the constructor parameter of CollectingSAXErrorHandler from Supplier <ErrorList> to Supplier <? extends ErrorList>
  • Added new interface IObjectPoolFactory to extend the functionality of the ObjectPool class

v11.0.6 - 2023-07-10

  • Updated to BouncyCastle 1.75
  • Extended ObjectPool API
  • Improved DAO debug logging

v11.0.5 - 2023-06-18

  • Updated resilience in WALListener to correct handle activities, even if the ExecutorService is already shutdown
  • Logging warnings when a configuration value contains a trailing whitespace character
  • Fixed a potential stack overflow when handling too deeply nested JSON objects. See issue #35
  • Added support to detect Java 20

v11.0.4 - 2023-04-29

  • Extended the class JAXBContextCacheKey to support multiple packages as well
  • Deprecated a lot of methods from JAXBContextCache in favour of the JAXBContextCacheKey factory method
  • Fixed an error in Codepoint.isLowSurrogate and Codepoint.isHighSurrogate
  • Added support for writing Surrogate pairs in the XML writer
  • XMLFactory.createDefaultTransformerFactory no longer emits warnings of unsupported features
  • Added classes ConditionalLogger and IHasConditionalLogger

v11.0.3 - 2023-04-16

  • Updated to BouncyCastle 1.73
  • Deprecated classes AbstractJAXBBuilder and AbstractWritingJAXBBuilder for removal
  • Classes LoggingJAXBReadExceptionHandler and LoggingJAXBWriteExceptionHandler received a singleton accessor field
  • Extended IKeyStoreType interface with method isKeyStorePathRequired
  • Added new enum entry EKeyStoreType.PKCS11 for support of PKCS11 - see PR #34 - thx @sopgreg
  • Deprecated classes JAXBDocumentType and IJAXBDocumentType
  • The GenericJAXBMarshaller now has an API to disable the usage of XML Schema that applies for reading, writing and validation
  • Added an optional progress callback to the StreamHelper.copy(Byte|Char)Stream builders

v11.0.2 - 2023-02-24

  • Updated to parent POM 2.0.1
  • Updated to JAXB 4.0.2
  • Updated to JAX-WS 4.0.1
  • Updated to SLF4J 2.0.6
  • Added missing MicroType converter for the XMLOffset(Date|Time) data types and others
  • Added additional MathHelper.getDividedBigDecimal overload
  • Added additional method IJAXBWriter.getAsElement
  • Added additional ArrayHelper.forEach overload
  • Using BouncyCastle dependency org.bouncycastle:bcjmail-jdk18on for Jakarta usage
  • Fixed an ArrayIndexOutOfBoundsException when a single $ character is contained in a configuration property with variable resolution enabled - see issue SMP #234
  • Variable resolution in configuration files is now enabled by default

v11.0.1 - 2023-01-08

  • Updated to BouncyCastle 1.72
  • Improved the Java Version number parser to not throw exceptions on unsupported versions
  • Added support to detect Java 18 and 19
  • Added new class PathToNodeBuilder to be used to customize the building of a path from a DOM node - see issue #31
  • Catching Throwable in classes ConcurrentCollectorSingle and ConcurrentCollectorMultiple to avoid unnoticed errors

v11.0.0 - 2022-09-11

  • Requires Java 11 as the baseline
  • Updated to BouncyCastle 1.71.1
  • Updated to JAXB 4.0.0
  • Updated to JAX-WS 4.0.0
  • Updated to SLF4J 2.0.0
  • Removed all classes and methods marked as deprecated
  • By default all XML processing disables DTD processing and disallows all external entities
  • Renamed IConfigurationValueProviderWithPriorityCallback method onConfigurationSource to onConfigurationValueProvider
  • Added additional overloads of XMLOffset(Date|Time|DateTime).of without ZoneOffset
  • Renamed JAXBMarshallerHelper.(is|get|set)Sun to (is|get|set)Jakarta - this is an backwards incompatible change, even though that part should not be used externally anyway
  • Added new interface IIterableConfigurationSource to enumerate all available configuration items
  • The default TransformerFactory created in XMLTransformerFactory uses now the secure reading
  • Made silent mode in class SystemProperties customizable
  • Class GenericJAXBMarshaller now works on ValidationEventHandler directly instead of the factory
  • Class GenericJAXBMarhsaller now also implements IJAXBValidator

v10.2.5 - 2023-06-18

  • Fixed a potential stack overflow when handling too deeply nested JSON objects. See issue #35 (backport from 11.0.5)
  • Added support to detect Java 20 (backport from 11.0.5)
  • Updated to BouncyCastle 1.73 (backport from 11.0.3)

v10.2.4 - 2023-04-29

  • Fixed an error in Codepoint.isLowSurrogate and Codepoint.isHighSurrogate (backport from 11.0.4)
  • Added support for writing Surrogate pairs in the XML writer (backport from 11.0.4)

v10.2.3 - 2023-02-15

  • Fixed an ArrayIndexOutOfBoundsException when a single $ character is contained in a configuration property with variable resolution enabled - see issue SMP #234 (backport from 11.0.2)

v10.2.2 - 2022-11-17

  • Added new class PathToNodeBuilder to be used to customize the building of a path from a DOM node - see issue #31 (backport from 11.0.1)

v10.2.1 - 2022-10-18

  • Updated to BouncyCastle 1.72 (backport from 11.0.1)
  • Improved the Java Version number parser to not throw exceptions on unsupported versions (backport from 11.0.1)
  • Added support to detect Java 18 (backport from 11.0.1)

v10.2.0 - 2022-08-24

  • Updated to BouncyCastle 1.71
  • Added StringHelper.getNot(Null|Empty) overloads using a Supplier
  • Added new class TextVariableHelper that can be used to replace ${bla} like variables
  • Added new class ConfigWithFallback that can deal with resolving configuration items with different keys
  • Added support for variable resolution in class Config. Use setReplaceVariables(true) to enable this functionality

v10.1.8 - 2022-07-13

  • Added StringHelper.isEmpty and StringHelper.isNotEmpty for more consistent naming
  • Fixed JAXB formatting which partially indented wrong

v10.1.7 - 2022-06-24

  • Extended IError with an optional error date time
  • The algorithm name in PasswordHash may not exceed 100 characters
  • Added CMimeType.APPLICATION_X509_USER_CERT
  • Extended IJsonObject API slightly
  • Added new methods XMLHelper.iterateChildren and XMLHelper.recursiveIterateChildren
  • Added new enum entries EXMLParserFeature.ACCESS_EXTERNAL_*
  • Added new class NaturalNumericOrderComparator
  • Added new class RecursiveNodeIterator and deprecated class RecursiveChildNodeIterator
  • Added a factory method to class MicroRecursiveIterator

v10.1.6 - 2022-01-28

  • Updated to BouncyCastle 1.70
  • Changed CommonsAssert.FLOAT_ALLOWED_ROUNDING_DIFFERENCE from 1e-5 to 1e-4
  • Fixed a potential ConcurrentModificationException in AnnotationUsageCache in Java 11+ - see issue #27
  • Allowed country codes to follow the scheme [0-9A-Z] to support the country code for Kosovo used by the EC Publication Office (1A)

v10.1.5 - 2021-11-21

  • Updated to JAXB 2.3.5
  • Updated to JAXWS 2.3.5
  • Added factory method StringInputStream.utf8
  • Added new method WatchDir.runAsyncAndReturn
  • Ensuring unique resource ID in ReadableResourceByteArray (see https://github.com/phax/ph-schematron/issues/118)
  • Added new methods getAndInc and incAndGet to the Mutable* classes
  • IConfig.forEachConfigurationValueProvider now iterates the priorities correctly when a MultiConfigurationValueProvider is used.
  • Added support for JDK 15, 16 and 17 in class EJavaVersion

v10.1.4 - 2021-10-30

  • Made AbstractReadOnlyMapBasedMultilingualText implement Serializable
  • Added special ReadableResourceString factory methods for UTF-8
  • Class PasswordSalt now preferring factory methods over the constructors
  • The default password salt length was reduced from 512 to 32
  • GlobalIDFactory now limits String based IDs to a maximum length of 20 for easy DB usage
  • Fixed an issue, that XMLOffset(Date|Time|DateTime).parse did not work without the timezone

v10.1.3 - 2021-09-19

  • Made XMLOffset(Date|Time|DateTime) implement Serializable (see issue #26)
  • Updated to BouncyCastle 1.69
  • Honouring the default value in CollectionHelper.findFirst
  • AnnotationUsageCache is no longer thread-safe for performance reasons, as the number of read operation is so much higher
  • Added new ArrayHelper.startsWith overloads
  • IHasByteArray.getAllBytes now honours offset and size
  • Added new method IHasByteArray.getBytesAsString to convert it to a String
  • The time formatter for XSD no longer prints a mandatory fractional second (see https://github.com/phax/ph-ubl/issues/40)

v10.1.2 - 2021-05-13

  • Added type converter for destination type XMLOffsetDateTime
  • Avoid an NoClassDefFoundError when using a different JAXB implementation
  • Fixed an error that PDTToString with an OffsetDate would try to use a time formatter
  • PDTToString now handles ZoneOffset and ZoneId better
  • Added XMLHelper.getChildElementOfNames as a sanity method
  • Favouring XMLOffset*.toString over the getAsString variant for better interoperability

v10.1.1 - 2021-05-02

  • Build with Java 1.8 instead of Java 11 because of binary incompatibility with ByteBuffer.flip() signature

v10.1.0 - 2021-05-02

  • Started the explicit Wiki
  • Added CHttpHeader.HOST
  • Extended Copy*StreamBuilder with limit (Long)
  • Added Predicates.and and Predicates.or
  • Create new classes XMLOffsetDate and AdapterXMLOffsetDate similar to OffsetDate but with an optional zone offset
  • Create new classes XMLOffsetTime and AdapterXMLOffsetTime similar to OffsetTime but with an optional zone offset
  • Create new classes XMLOffsetDateTime and AdapterXMLOffsetDateTime similar to OffsetDateTime but with an optional zone offset
  • Added method Version.hasQualifier
  • Changed Version.parse to use the new format by default. Added Version.parseDotOnly for the old version.
  • Added missing PDTToString.getAsString overloads
  • Avoid the inclusion of JAXB and JAX-WS implementation artefacts. The JAXB implementation must now explicitly be added to an application pom.xml e.g. like this:
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-impl</artifactId>
    </dependency>

v10.0.0 - 2021-03-21

  • Changed Maven groupId from com.helger to com.helger.commons
  • The submodule ph-xml no longer depends on ph-collection
  • Separated the JAXB adapter classes and JAXBHelper to new submodule ph-jaxb-adapter - the goal is to have less dependencies
  • Removed the submodule ph-charset - who needs UTF-7 nowadays....
  • Removed deprecated methods
  • Removed Serializable from base interfaces
  • Removed the serializable functional specializations (IFunction, ISupplier, IConsumer, IPredicate, IBiConsumer, IBiFunction, IBiPredicate, NamespaceContext)
  • GenericJAXBMarshaller now has a chaining API
  • Made MimeTypeParserException a checked Exception
  • Added CertificateHelper.getEncodedCertificate()
  • Fixed potential NPE in GenericJAXBMarshaller.toString()
  • Removed TimeValue in favour of Duration
  • Added StopWatch.getLapDuration ()
  • Removed ResourceStreamSource and ResourceStreamResult - see https://saxonica.plan.io/issues/4833 for the reasons
  • Changed JsonReader.Builder method names to not use set
  • The calling order of "useBufferedReader" and "dontCloseSource" compared to "source" in JsonReader.Builder is not longer of importance
  • Changed the SingleError.builder() to use method names without set
  • Added more SingleError builder errorLocation overloads
  • Removed the class ScriptHelper as Nashorn gets removed in JDK 15 (see JEP 335)
  • Added new interfaces IBuilder and IResettableBuilder
  • Extended HTTPHeaderMap API
  • Fixed the data type of the custom HTTP headers in WSClientConfig
  • Changed the default value DEFAULT_QUOTE_IF_NECESSARY from true to false
  • Deprecated all the "multi map" classes in ph-collection. With the computeIfAbsent functions, most of the simplifications can be achieved with runtime features. They will be removed in the next major version.
  • Extended ILocalDatePeriod based on issue #23
  • Added classes ILocalDateTimePeriod and LocalDateTimePeriod
  • Added class PasswordHashCreatorPBKDF2_SHA256_1000_48 for better PBKDF2 usage
  • Deprecated class PasswordHashCreatorPBKDF2_1000_48 because it uses the PBKDF2 with the SHA1 hash
  • Added new class StringHelper.ImploderBuilder that handles all the StringHelper.getImploded* stuff internally
  • Added new method ICommonsIterable.forEachThrowing
  • Added new class StreamHelper.CopyByteStreamBuilder
  • Added new class StreamHelper.CopyCharStreamBuilder
  • Added new method URLHelper.isValidURN to check RFC 2141 compliance
  • Deprecated some methods in StreamHelper that should be replaced with calls to the new builder
  • Added CommonsHashSet.createFiltered factory methods
  • Added new class AdapterOffsetTime
  • Added support for OffsetTime in PDT* classes
  • Made the JAXB adapters for AdapterOffsetDateTime and AdapterZonedDateTime more resilient to read data without time zone offsets as well
  • Added class OffsetDate from ThreeTen-Extra project for XML parsing
  • Added new methods in PDTFactory that deal with UTC time zones

v9.5.5 - 2021-03-18

  • Updated to BouncyCastle 1.68 (again with bcprov-ext-jdk15on)
  • Added new class AdapterOffsetDateTime

v9.5.4 - 2020-12-15

  • Updated to BouncyCastle 1.67 (no more bcprov-ext-jdk15on)
  • Removed "double locking" in AbstractCollector

v9.5.3 - 2020-10-22

  • Reverting the changes from 9.5.2
  • Made the JAXB DateTime adapter classes more resilient by trimming the input string

v9.5.2 - 2020-09-25

  • Experimental release that uses CommonsHashMap instead of CommonsWeakHashMap for all registries having Class<?> as the key

v9.5.1 - 2020-09-18

  • Build with Java 1.8 instead of Java 11 because of binary incompatibility with ByteBuffer.flip() signature

v9.5.0 - 2020-09-17

v9.4.8 - 2020-09-10

  • Added new JAXB Adapter class AdapterZonedDateTime
  • Added a new factory method in ConfigFactory.
  • Default configuration source loading is now more consistent and behaves identical for all predefined filenames.
  • Extended IConfig API to easily reload all resource based configuration files
  • New interface IAddableByTrait to be used as the constraint for the element type of IGenericAdderTrait

v9.4.7 - 2020-08-28

  • Extended IPrivilegedAction API for Security provider APIs
  • Extended IJsonArray API to iterate only child arrays, objects or values
  • Scope debugging no longer activates itself if the log level is set to debug
  • Extended PDTWebDateHelper to handle LocalTime values as well
  • Added predefined JAXB adapters in package com.helger.jaxb.adapter

v9.4.6 - 2020-07-15

  • Allow empty MIME type parameter values
  • MimeTypeParser.safeParseMimeType does an RFC 2616 decoding if necessary
  • Updated to BouncyCastle 1.66

v9.4.5 - 2020-06-29

  • Added missing methods in IMapBasedDAO
  • Added static syntactic sugar methods in HashCodeGenerator
  • The default ConfigFactory.getDefaultInstance() now also considers system properties config.resource, config.resources, config.file and config.url or the environment variable alternatives CONFIG_RESOURCE, CONFIG_RESOURCES, CONFIG_FILE and CONFIG_URL.
  • Added possibility to reload for resource-based configuration sources
  • Fixed a potential NPE in IJsonObject.getValue (String)
  • Added EqualsHelper.equalsCustom using a BiPredicate
  • Extended IConfig API to receive the IConfigurationSource AND the value to determine the source of the configuration value (backwards incompatible change)
  • Changed the handling of the Consumers in the Config implementation in a backward incompatible way (setters vs. constructor, new parameter type)

v9.4.4 - 2020-05-21

  • Fixed a backwards compatibility issue with JsonObject.add(String,IJson)

v9.4.3 - 2020-05-21

  • Extended tests - thanks to @dliang2000
  • Extended NonBlockingCharArrayWriter with non-throwing write overloads
  • Changed IJsonObject API to favour addJson instead of add because of different nullness
  • Deprecated IHasSchema
  • Added IConfigurationSourceResource.getAllConfigItems
  • URLResource.getAsFile() is now nullable

v9.4.2 - 2020-04-25

  • Reduced write locked section in ScopeManager.onGlobalEnd to reduce the possibility of a dead-lock
  • Made ThreadGroup of BasicThreadFactory customizable
  • Updated to BouncyCastle 1.65
  • The IMissingLocaleHandler is now also called in LocaleHelper.getLocale if the input strings are all empty
  • Improved the resolution rules for LocaleCache, LanguageCache and CountryCache on edge cases.
  • Extracted overridable GenericJAXBMarshaller.getJAXBContext
  • Added possibility to cache JAXBContext objects created via classes

v9.4.1 - 2020-03-30

  • Added SimpleLock.(read|write)LockedGet(Throwing)
  • The exception handling of URLHelper.urlDecode is now backwards compatible
  • Added URLHelper.urlDecodeOrNull and urlDecodeOrDefault

v9.4.0 - 2020-03-27

  • Added support for additional HTTP status codes (103, 308, 422, 425, 426, 428, 429, 431, 451, 506, 507, 508 and 511)
  • JAXBContextCache has now a method to switch silent mode on or off
  • Added new constant GlobalDebug.DEFAULT_SILENT_MODE for the default silent mode setting
  • Added new method CertificateHelper.convertByteArrayToCertficateOrNull
  • Added new class PDTDisplayHelper
  • Added new method CertificateHelper.convertStringToPrivateKey
  • Extended the JsonWriter API to also write to an OutputStream
  • Added new methods EmailAddress.createOnDemand
  • URLHelper.urlEncode and URLHelper.urlDecode now uses URLCodec
  • Deprecated ICommonsIterable.forEach in favour of findAll
  • Fixed a bug in the cloning of MapBasedNamespaceContext (see issue #17)
  • Added ArrayHelper.EMPTY_CLASS_ARRAY
  • Added new predefined licenses (GPL20CP, EPL20 and EDL10)
  • Updated license URLs to https where applicable
  • New parent POM 1.11.1 updates SLF4J to 1.7.30
  • PropertiesHelper got new APIs with Charset to read properties with character sets other than ISO-8859-1
  • Started new subproject ph-config with a more intelligent configuration handling
  • Added JDK 14 as a known version
  • Added silent mode to TypeConverter, CountryCache, LanguageCache, ObjectPool, LocaleCache
  • Added new JAXBDocumentType constructor for more flexible use
  • Changed names of SimpleReadWriteLock.(read|write)Locked with primitive suppliers
  • Changed names of SimpleLock.locked with primitive suppliers
  • Added SimpleReadWriteLock.(read|write)LockedGet(Throwing) suppliers

v9.3.9 - 2019-12-11

  • Made ClassLoaderHelper.getResource more robust
  • Updated "mime-type-info.xml" list with shared-mime-info-spec 1.15
  • Moved code from AbstractWALDAO down to AbstractDAO for later reuse.
  • Reworked FileIntIDFactory and FileLongIDFactory to be more error resistant.
  • Added support for the "jrt:" protocol
  • Added support for JDK 13
  • Extended LocaleCache with an API to specify what happens if a Locale is not present

v9.3.8 - 2019-11-07

  • Fixed method name in RFC2616Codec - getMaximumEncodedLength instead of getEncodedLength; added getMaximumDecodedLength
  • Avoid double quoting in HttpHeaderMap.getUnifiedValue if the value already seems to be quoted
  • Updated to BouncyCastle 1.64
  • Added new interface IBooleanConsumer
  • Added new method CertificateHelper.isCertificateValidPerNow
  • Improved performance of JsonParser when position tracking is disabled
  • Added possibility to read multiple JSON objects from a single source
  • Added new classes LoggingReader and LoggingWriter
  • Added new classes CountingReader and CountingWriter
  • JsonParser.parse now returns an enum indicating EOI or not (incompatible change)
  • Improved performance of JsonParser by reusing buffers internally
  • Added new class MappedCache that is a generalization of Cache. It adds a mapper to determine the cache key.
  • New parent POM 1.11.0 updates SLF4J to 1.7.29

v9.3.7 - 2019-09-25

  • Extended IJAXBValidator API to have a validate method that takes an outside ErrorList
  • Updated to BouncyCastle 1.63
  • Converted some methods in IMicroQName to default methods
  • Extended HttpHeaderMap API to make quote if necessary customizable

v9.3.6 - 2019-08-27

  • Extended the StreamHelper API with an even more flexible copyInputStreamToOutputStream method
  • StreamHelper.getCopy[WithLimit] can now return null if copying fails
  • Added new classes around com.helger.commons.codec.ICharArrayCodec
  • Added new class RFC2616Codec to correctly encode and decode HTTP header values
  • Added new option in HttpHeaderMap.getUnifiedValue to automatically quote the values if necessary
  • Added new overloads in StackTraceHelper to use a custom line separator
  • Added new methods CommonsAssert.assertNotEquals(boolean,boolean)

v9.3.5 - 2019-08-04

  • Updated to BouncyCastle 1.62
  • Added new EURLProtocol entries CID and MID from RFC 2392
  • Minor speed ups in several places
  • Added overload of PDTXMLConverter.getXMLCalendarDate with timezone offset in minutes
  • Added new JsonReader.Builer overloads
  • LocaleHelper.getValidCountryCode now convert ISO 3166 Alpha 3 codes to ALpha 2 codes where applicable
  • Made XML serialization settings on the XML declaration more fine grained

v9.3.4 - 2019-05-28

  • Added new overloads for JsonReader.Builder.setSource
  • Catching exception in VerySecureRandom initialization - setSeed may throw an Exception
  • Deprecated class RandomHelper - causes more problems than it solves
  • Added new method CertificateHelper.convertStringToCertficateOrNull
  • Added new method CertificateHelper.convertByteArrayToCertficateDirect
  • Added complete list of HTTP response codes constants to CHttp
  • Added new method Base64OutputStream.setNewLineBytes
  • Removed methods Base64.(encode|decode)Object for security reasons
  • Added new option Base64.DO_NEWLINE_CRLF to use \r\n as newline separator instead of \n

v9.3.3 - 2019-05-06

  • Added ICommonsIterable methods findFirstIndex and findLastIndex
  • Added support for Java 12
  • The default XML persistence for configuration files was changed. No more "class" attribute and no nested "value" element needed. The old layout can still be read, but only the new layout is written.
  • The class JsonReader now has an explicit JsonReader.Builder class to simplify the usage
  • New class SettingsPersistenceJson to be able to read and write settings in JSON format

v9.3.2 - 2019-03-28

  • Logging a warning in VerySecureRandom if initial seeding takes more than 500 milliseconds
  • If the system property ph.disable-securerandom with the value of true is present, the usage of SecureRandom in class RandomHelper is disabled by default. Respective logging was added.
  • The system property ph.securerandom-reseed-interval with a numeric value ≥ 0 can be used to set the default "re-seed interval" for class VerySecureRandom
  • VerySecureRandom uses NativePRNGNonBlocking as the initial SecureRandom for faster Linux initialization.

v9.3.1 - 2019-03-06

  • Made IJsonWriterSettings serializable
  • Updated to BouncyCastle 1.61
  • null values in settings can be serialized now
  • HttpHeaderMap methods forEachSingleHeader and forEachHeaderLine now use the unified values

v9.3.0 - 2019-02-07

  • Restored the Automatic-Module-Name of com.helger.scopes
  • Moved method exceptionCallbacks to base class AbstractJAXBBuilder
  • Exception handler in GenericJAXBMarshaller now based on ´CallbackList` - incompatible change
  • Fixed the conversion from String to Integer, Long and Short so that null is returned on error (therefore throwing a TypeConverterException)
  • IGetter*Trait getAs... methods now return null on error instead of throwing a TypeConverterException

v9.2.1 - 2019-01-23

  • Improved API of JsonParseException
  • Added additional default MicroTypeConverter registrations (File, Path, URL and URI)
  • Added special implementation of IHasInputStream for NonBlockingByteArrayOutputStream
  • Added enum entry EXMLSerializeXMLDeclaration.EMIT_NO_NEWLINE
  • Extended internal API of AbstractMapBasedWALDAO to allow for not invoking the callbacks
  • Added method ConfigFileBuilder.addPathFromEnvVar to get the configuration file path from an environment variable
  • Added new keystore type BCFKS - see issue #13
  • Added new constructor for MapEntry to take Map.Entry
  • Added new default methods to classes IHasDimension* (isLandscape, isPortrait and isQuadratic)
  • MimeTypeContent is now serializable
  • The OSGI export for submodule ph-scopes was corrected - see issue #14
  • Added static factory methods for ByteArrayWrapper

v9.2.0 - 2018-11-21

  • Undo deprecations of ValueEnforcer short and float methods.
  • Simplified the IMultilingualText interface and implementations (backwards incompatible)
  • Removed all deprecated, unused methods
  • ICommonsIterable is no longer Serializable. Only ICommonsCollection is serializable.
  • IHasDisplayText is no longer Serializable.
  • IDisplayTextProvider is no longer Serializable.
  • IHasText is no longer Serializable.
  • Changed return type of SystemProperties.setPropertyValue() to EChange
  • JAXBDocumentType takes List<ClassPathResource> instead of List<String> to avoid ClassLoader issues
  • Changed PBCProvider initialization to log a warning instead of throwing an exception
  • Added StringHelper methods getQuoted and appendQuoted
  • Improved Java 10/Java 11 support
  • Moved CloneHelper.getClonedJAXBElement to new class JAXBHelper in ph-jaxb subproject (Java 11 issue)
  • Moved class WSTestHelper to subproject ph-wsclient (Java 11 issue)
  • First version to compile with OracleJDK 11 and OpenJDK 11
  • Added methods in PDTFactory to remove microseconds and nanoseconds from (Zoned|Offset|Local)DateTime
  • Added support for silent mode in AbstractDAO
  • Changed DOMReader.readXMLDOM to not throw an Exception. Provide a suitable ErrorHandler instead.
  • WrappedCollectingSAXErrorHandler is now derived from CollectingSAXErrorHandler

v9.1.8 - 2018-10-24

  • Added special support for properties java.runtime.version and java.runtime.name in class SystemProperties
  • Class JavaVersionHelper now supports AdoptOpenJDK versions
  • HttpHeaderMap stores the value case sensitive internally and compares case sensitive instead (issue #11)
  • Added PDTConfig.getUTCTimeZone ()
  • Fixed a conversion error from GregorianCalendar to XMLGregorianCalendar if only the date part is used (issue #12)
  • Added TimeZone related methods in PDTFactory
  • Added method IHasInputStream.getBufferedInputStream(), IHasInputStreamAndReader.getBufferedReader() and IHasReader.getBufferedReader()
  • Added method IHasOutputStream.getBufferedOutputStream(), IHasOutputStreamAndWriter.getBufferedWriter() and IHasWriter.getBufferedWriter()
  • Opened JsonReader API to add the possibility to pass in an IJsonParserCustomizeCallback instance
  • Added IMultilingualText.texts ()
  • Fixed some SpotBugs errors
  • Added IJAXBWriter.getAsInputStream(...)
  • Added new marker interface IExplicitlyCloneable

v9.1.7 - 2018-10-11

  • Added new class IdentityByteArrayCodec
  • Added new classes MacInputStream and MacOutputStream
  • Deprecated some JSON APIs with byte, short and float
  • Overloaded WrappedOutputStream.write (byte[],int,int) for quicker pass-through. Please ensure that all derived classes also overload this method.
  • JSONValue handling for long values in the int range was changed to store int internally. This improves testability independent of the value range.
  • Added new StringHelper.contains(Any|No|Only) methods for CharSequence and String objects

v9.1.6 - 2018-10-01

  • Added CHttpHeader.X_CONTENT_SECURITY_POLICY_REPORT_ONLY
  • Added ValueEnforcer.isNE0 methods
  • Deprecated ValueEnforcer methods for short and float
  • Reworked the VerySecureRandom initialization to use a native PRNG for initial seeding
  • Improved customizability of AbstractWALDAO in case WAL recovery failed
  • Extended IHas...DateTime APIs
  • Fixed OSGI SPI configuration for ph-bc

v9.1.5 - 2018-09-09

  • Extended WSClientConfig API
  • Extended GenericJAXBMarshaller API
  • Class IJAXBReader now tries to set systemID for IReadableResource, File and Path parameters.
  • Extended PDTFactory slightly
  • Fixed potential NPE when an AbstractWALDAO is used without a backing file
  • DefaultTransformURIResolver got the possibility to provide a default base URI if none is present in the call
  • Improved internal API of AbstractMapBasedWALDAO
  • Updated stax-ex to 1.8

v9.1.4 - 2018-08-06

  • Added class XMLBracketModeDeterminatorXMLC14
  • Added XML write setting write CDATA as Text
  • Added XML write setting order attributes and namespaces lexicographically
  • XML entities are now emitted as Hexadecimal values instead of numeric (&#D; instead of &#13;)
  • Fixed error in HttpHeaderMap.addAllHeaders (was not doing what was expected)

v9.1.3 - 2018-07-19

  • Updated to BouncyCastle 1.60
  • Extended LogHelper to have overloads with Supplier<String>
  • Added new Commons...Map constructors with parameters Map, Function, Function
  • Added new class LanguageCache
  • Added new CommonsArrayList static factory methods
  • Deprecated all the ChangeLog classes - they will be moved to ph-less-commons in v9.2
  • Added new interface IHasByteArray
  • Implementing IHasByteArray in ReadableResourceByteArray, ByteArrayInputStreamProvider, MessageDigestValue
  • Added new class ByteArrayWrapper
  • Added new method NonBlockingByteArrayOutputStream.getBufferOrCopy() that copies only on demand
  • Added new ArrayHelper.startsWith overloads
  • Added static factory methods in CommonsCopyOnWriteArrayList
  • The internal logger name was changed from s_aLogger to LOGGER
  • Extended IPrivilegedAction with new static methods
  • Added new class Predicates with basic typed predicates for primitive types
  • Added some static IBooleanPredicate factory methods
  • Added ToStringGenerator.appendPasswordIf method
  • Added equals implementation to PasswordAuthentication

v9.1.2 - 2018-06-19

  • Made setters of WSClientConfig final
  • Changed method name in CharsetHelper from getCharsetFromNameOrNull to getCharsetFromNameOrDefault
  • Added new sub-project ph-bc with some common BouncyCastle helper methods
  • Added OCSP MIME type constants
  • Extended XMLTransformerFactory API to support creating secure instances
  • Improved code quality based on SonarQube analysis
  • Removed the Generic type from IConcurrentCollector
  • Added PropertiesHelper.expandProperties
  • Removed empty class AbstractTreeItemFactory

v9.1.1 - 2018-05-14

  • Really fixed OSGI ServiceProvider configuration

v9.1.0 - 2018-05-08

  • Fixed invalid call in ValueEnforcer.isEqual
  • AbstractJAXBBuilder got an explicit possibility to disable XML schema usage
  • Improved Java version identification by adding support for JEP 223 identifiers
  • Kicked Travis Java 9 integration - was unable to find a Maven configuration working locally, in Eclipse and in Travis :(
  • Added IMicroNode.appendChildren default methods
  • Extracted ph-wsclient project for later use with Java 9
  • Added ICommonsCollection.setAllMapped
  • Added class CommonsMock - a very simple mocking engine
  • Added EMimeContentType.FONT
  • Extended TreeXMLConverter API to be able to reuse existing trees for filling
  • Fixed OSGI ServiceProvider configuration

v9.0.2 - 2018-03-22

  • Made setter methods of JAXB*Builder final so that they can be called from derived constructors
  • Improved Java 9 compliance
  • EJavaVersion was changed incompatible to allow support for Java 10 and 11
  • Added ELockType.DEPENDS enum constant
  • Added some more MathHelper.toBig(Decimal|Integer) overloads so that it can be used without thinking
  • Different forbidden characters in filenames depending on OS - https://github.com/phax/as2-server/issues/20
  • Updated to parent POM 1.10.2

v9.0.1 - 2018-02-01

  • Minor API adoptions
  • Updated to BouncyCastle 1.59
  • XML validation now works with custom locales as well
  • Added XPathHelper.createXPathFactorySaxonFirst
  • Fixed typo in XPathHelper - createNewXPathExpression instead of createNewXPathExpresion
  • Updated to parent POM 1.10.0

v9.0.0 - 2017-11-05

  • Changed com.helger.commons.function package to com.helger.commons.functional
  • Replaced IFilter with IPredicate
  • Replaced IFilterWithParameter with IBiPredicate
  • Changed ManagedExecutorService to ExecutorServiceHelper
  • Removed class CCharset - use StandardCharsets instead
  • Added classes PathHelper and PathOperations
  • Moved class XMLResourceBundle to ph-xml
  • Removed some deprecated CharsetManager methods
  • Reworked format package
  • Removed deprecated 'Mutable*' constructors because of weird defaults
  • Removed deprecated methods that handle: greater than, greater or equals, lower than and lower or equals
  • Made MicroTypeConverter type-safe
  • Ensure all Predicate usages use ? super
  • Ensure all Consumer usages use ? super
  • Ensure all Function usages use ? super/? extends where applicable
  • Ensure all Supplier usages use ? extends
  • Moved ThreadHelper to package com.helger.commons.concurrent
  • Removed deprecated methods in SimpleLSResourceResolver
  • Removed package com.helger.commons.io.monitor
  • Removed package com.helger.commons.scope.singletons
  • @ReturnsMutableObject does not require a value anymore (but you can still pass one of course)
  • Extracted ph-scopes project to lower size of ph-commons slightly
  • Extracted ph-collection project to lower size of ph-commons slightly
  • Removed default methods from IAggregator
  • Added reverse interface ISplitter
  • Changed caching API to use a function instead of a protected methods
  • Integrated ph-cli here
  • Improved and extended traits API
  • JAXB components can now use a safe way to write XML with special chars
  • JAXB components can now read XML documents with a BOM
  • Extracted ph-oton DAO handling into new subproject ph-dao
  • Replaced SMap with StringMap
  • An Automatic-Module-Name was added after beta 1
  • Removed support for the application and session application scopes

v8.6.6 - 2017-07-12

  • Extended CSVWriter API
  • SimpleLSResourceResolver can now handle fat jars from Spring Boot (issue #8)
  • Extracted DefaultResourceResolver from SimpleLSResourceResolver and added in ph-commons
  • Added rudimentary support for Path based APIs
  • Added WatchService based WatchDir in favor of FileMonitor

v8.6.5 - 2017-05-19

  • Deprecated all default Mutable* constructors, because the default values were partially confusing
  • Added new class DefaultEntityResolver using a base URL for resolving.
  • Extracted and renamed classes PDTZoneID and PDTMask
  • Extended ILocalDatePeriod API
  • Added additional specialized type converters to BigDecimal
  • Unified naming for methods that handle: greater than, greater or equals, lower than and lower or equals
  • Added new type converters for Month, DayOfWeek and MonthDay
  • RuntimeExceptions during type conversion are encapsulated in TypeConverterExceptions.

v8.6.4 - 2017-04-12

  • Some performance improvements
  • Fixed error in StringHelper.replaceMultipleAsString
  • Extended StringHelper with encode/decode methods
  • Added new class NonBlockingCharArrayWriter
  • Deprecated some CharsetManager methods

v8.6.3 - 2017-03-28

  • Deprecated some String-based FileHelper APIs
  • Improved CertificateHelper parsing
  • Added IPredicate - a serializable Predicate interface
  • Added IBiPredicate - a serializable BiPredicate interface
  • Added IBiConsumer - a serializable BiConsumer interface
  • Added IBiFunction - a serializable BiFunction interface
  • Added IComparable - a serializable and extended Comparable interface
  • Extended StringHelper API
  • Extended MicroWriter API
  • Extended XMLWriter API
  • Extended PDTHelper API
  • Deprecated EMonth and EDayOfWeek in favour of JDK Month and DayOfWeek

v8.6.2 - 2017-02-15

  • Extended XMLSystemProperties API
  • Allowing JAXBDocumentType objects to not have an @XmlSchema annotation
  • Deprecated CCharset - use StandardCharsets instead
  • Deprecated ToStringGenerator toString() - use getToString() instead

v8.6.1 - 2017-01-23

  • *MultilingualText is now based on ICommonsOrderedMap
  • Extended GlobalDebug API slightly
  • JAXBDocumentType implements equals/hashCode
  • WSClientConfig not using chunked encoding by default

v8.6.0 - 2017-01-09

  • Removed deprecated methods
  • Minor API extensions

v8.5.6 - 2016-12-10

  • Extended APIs
  • Fixed a nasty bug with date/time formatting due to pattern modifications (introduced in 8.5.5)

v8.5.5 - 2016-11-25

  • Extended APIs

v8.5.4 - 2016-11-08

  • Fixed a nasty NPE

v8.5.3 - 2016-11-08

  • Added support for EntityResolver2 in MicroXML parsing
  • Extended some APIs

v8.5.2 - 2016-09-25

  • Fixed an error with JAXB context creation if @XMLRootElement was used
  • Improved consistency of IHasText(WithArgs) and IHasDisplayText(WithArgs) so that they can be used interchangeably
  • Extended collection API slightly

v8.5.1 - 2016-09-12

  • Fixed error text retrieval in Single Error; further API extensions and improvements

v8.5.0 - 2016-09-09

  • Reworked the error objects so that there is now a single error handling object. The old objects are retained for backwards compatibility.

v8.4.0 - 2016-08-21

  • Started adding JDK 9 compatibility
  • Added new interface IWriteToStream
  • Added support for new Message digest and Mac algorithms
  • Added new functional interfaces (IThrowingSupplier, IThrowingConsumer and IThrowingFunction) with customizable Exception type
  • Deprecated some legacy interfaces and adapters that may lead to a compiler error (!)

v8.3.0 - 2016-08-02

  • Moved the following sub-projects into this project: ph-datetime, ph-json, ph-charset, ph-graph, ph-matrix and ph-settings

v8.2.2 - 2016-07-22

v8.2.1 - 2016-07-15

v8.2.0 - 2016-07-10

  • Added new sub-project ph-security that contains MessageDigest, HMac, Keystore etc. stuff

v8.1.0 - 2016-06-26

  • Minor small API optimizations for JAXB.
  • ValueEnforcer supports Supplier` functional interface.
  • GZIP based readable and writable resources added.

v8.0.0 - 2016-06-08

  • It splits the old big ph-commons library into slightly smaller pieces: ph-commons, ph-xml, ph-jaxb, ph-tree and ph-less-commons.
  • The first version that requires JDK 8
  • Multiple API changes to better support functional style
  • Base32 codec added
⚠️ **GitHub.com Fallback** ⚠️