Interface DataStore
- All Known Implementing Classes:
JsonStore,MysqlDataStore,SQLiteDataStore
-
Method Summary
Modifier and TypeMethodDescriptiondefault voidcheckOwnership(UltiToolsPlugin plugin, Class<?> dataEntity) Shared ownership check for thegetOperator(UltiToolsPlugin, Class)legacy overload (D-14/D-18/02-12), the counterpart tocheckOwnership(java.io.File, Class)above for the overload that already carries aUltiToolsPluginidentity directly rather than aFileto reverse-resolve.default voidcheckOwnership(File dataFolder, Class<?> dataEntity) Shared ownership check for thegetOperator(java.io.File, Class)legacy overload (D-14/D-18/02-12).voidSave all possible caches and destroy all data operation classes.default DataSourcegetDataSource(DataScope scope) Get the JDBCDataSourcebacking this store for the given scope, needing no entity class up front (a connection pool needs only a JDBC URL).<T extends BaseDataEntity<String>>
DataOperator<T> getOperator(UltiToolsPlugin plugin, Class<T> dataEntity) Deprecated, for removal: This API element is subject to removal in a future version.default <T extends BaseDataEntity<String>>
DataOperator<T> getOperator(DataScope scope, Class<T> dataEntity) Get a data operator for the entityscopeowns, refusing outright when it does not (D-14).default <T extends BaseDataEntity<String>>
DataOperator<T> getOperator(File dataFolder, Class<T> dataEntity) Deprecated, for removal: This API element is subject to removal in a future version.Enforces D-18's ownership check viacheckOwnership(java.io.File, Class)as its own first statement -- aDataStoreimplementation that overrides this method directly must call the same helper to get the refusal; the three backends shipped by this framework all do (02-12).default <T extends BaseDataEntity<String>>
DataOperator<T> getOperatorUnchecked(DataScope scope, Class<T> dataEntity) Internal, unchecked construction path used ONLY bygetOperator(DataScope, Class), called after its ownscope.owns(...)check has already passed (CR-01, 02-13).Get the type of data storage.
-
Method Details
-
getStoreType
String getStoreType()Get the type of data storage.- Returns:
- Data storage type
-
getOperator
@Deprecated(since="6.3.0", forRemoval=true) <T extends BaseDataEntity<String>> DataOperator<T> getOperator(UltiToolsPlugin plugin, Class<T> dataEntity) Deprecated, for removal: This API element is subject to removal in a future version.Carries no ownership check of its own (D-14/D-18) -- aDataStoreimplementation that overrides this method directly must callcheckOwnership(UltiToolsPlugin, Class)as its own first statement to get the refusal; the three backends shipped by this framework all do (02-12). Framework- internal callers (UltiToolsPlugin.getDataOperator) already check ownership themselves before calling this. UsegetOperator(DataScope, Class).Get data operation entity class.- Type Parameters:
T- Must inheritBaseDataEntity- Parameters:
plugin- PlugindataEntity- Data entity class- Returns:
- Data operation entity
- Scheduled removal version:
- 6.4.0
-
getOperator
@Deprecated(since="6.3.0", forRemoval=true) default <T extends BaseDataEntity<String>> DataOperator<T> getOperator(File dataFolder, Class<T> dataEntity) Deprecated, for removal: This API element is subject to removal in a future version.Enforces D-18's ownership check viacheckOwnership(java.io.File, Class)as its own first statement -- aDataStoreimplementation that overrides this method directly must call the same helper to get the refusal; the three backends shipped by this framework all do (02-12). Framework-internal callers (UltiToolsAPI.getDataOperator) already check ownership themselves before calling this. UsegetOperator(DataScope, Class).Get data operator for an external plugin, scoped to the plugin's own data folder. Refuses outright (D-18) whendataFolderresolves to a registered external plugin's scope that does not owndataEntity, or whendataFoldermatches no registered scope at all -- an unresolvable folder fails closed rather than proceeding unchecked (D-15). ADataStorethat overrides this method directly (as every backend shipped by this framework does) does not inherit this check; see the@deprecatednote.- Type Parameters:
T- entity type- Parameters:
dataFolder- the external plugin's data folder (e.g., plugins/MyPlugin/)dataEntity- data entity class- Returns:
- data operator
- Throws:
DataAccessException- ifdataFoldermatches no registered scope, or matches one that does not owndataEntity- Since:
- 6.2.2
- Scheduled removal version:
- 6.4.0
-
checkOwnership
Shared ownership check for thegetOperator(java.io.File, Class)legacy overload (D-14/D-18/02-12). Called both by this interface's owndefaultbody above and, as the first statement (before any path resolution, cache lookup, or connection-pool creation), by thegetOperator(File, Class)override of every backend this framework ships -- so a refused call has not created a pool, a file, or a cache entry as a side effect.The reverse lookup only ever registers EXTERNAL scopes (D-18) -- every internal plugin shares the framework's own data folder (
DataScope.forPlugin), so that one folder can never be attributed to a single owner by folder alone, and any call reaching here with the framework's own core data folder is refused exactly like any other unregistered folder. Before 02-13 this method exempted the framework's own core data folder from the reverse-lookup refusal, on the reasoning thatgetOperator(DataScope, Class)needed to reach an INTERNAL scope's owngetOperator(File, Class)without being refused a second time. CR-01 (02-REVIEW.md) found that exemption was keyed purely on the value ofdataFolder-- andUltiTools#getDataFolder()ispublicin the published jar, the exact fact D-17's own javadoc names as the reasonDataScopehad to be unforgeable -- not on any credential or caller identity, so any code sharing the JVM could reach it. OnMysqlDataStorethis was a genuine, unauthenticated read/write bypass onto another module's real table (there is exactly one globalDataSourcefor the whole server). 02-13's fix:getOperator(DataScope, Class)no longer routes an INTERNAL scope through this method at all -- it resolves directly via an internal, unchecked construction path (seegetOperatorUncheckedon the framework's three shipped backends) that never touches this check, so no exemption is needed here anymore.- Parameters:
dataFolder- the external plugin's data folderdataEntity- data entity class- Throws:
DataAccessException- ifdataFoldermatches no registered scope, or matches one that does not owndataEntity- Since:
- 6.3.0
-
checkOwnership
Shared ownership check for thegetOperator(UltiToolsPlugin, Class)legacy overload (D-14/D-18/02-12), the counterpart tocheckOwnership(java.io.File, Class)above for the overload that already carries aUltiToolsPluginidentity directly rather than aFileto reverse-resolve. Called by every backend this framework ships as the first statement of their owngetOperator(UltiToolsPlugin, Class)override, before any path resolution, cache lookup, or connection-pool creation.UltiToolsPluginexposes no accessor for theDataScopePluginManagermints for it -- onlyUltiToolsPlugin.setDataScope(com.ultikits.ultitools.manager.DataScope), the injection point, is public -- so this cannot callplugin's ownDataScope#owns(Class)directly. It instead consults the samePluginManager#findOwningPlugin(Class)registryDataScope.refusalFor(Class)itself already treats as authoritative for message-building: every scope's owned-entity set is recorded there at minting time (D-19), first-registration- wins on a collision. This project's measured, zero-collision entity population across 21@Tableclasses / 17 repositories (02-CONTEXT.md) means "the registry's recorded owner equals the requester's own name" and "the requester's own scope owns the entity" agree in every case this codebase has ever produced; a genuine collision would needUltiToolsPluginto expose its ownDataScopeto close fully, which is out of this change's scope (02-12-PLAN.md's file boundary excludesUltiToolsPlugin.java).- Parameters:
plugin- the requesting plugindataEntity- data entity class- Throws:
DataAccessException- ifplugindoes not owndataEntityper the registry above- Since:
- 6.3.0
-
getDataSource
Get the JDBCDataSourcebacking this store for the given scope, needing no entity class up front (a connection pool needs only a JDBC URL).- Parameters:
scope- the requesting scope- Returns:
- the JDBC data source for that scope
- Since:
- 6.3.0
-
getOperator
default <T extends BaseDataEntity<String>> DataOperator<T> getOperator(DataScope scope, Class<T> dataEntity) Get a data operator for the entityscopeowns, refusing outright when it does not (D-14). The credential is framework-minted and unforgeable (DataScope's constructor and static factories are package-private tomanager), so this is the supported path: unlikegetOperator(UltiToolsPlugin, Class)andgetOperator(java.io.File, Class), it cannot be reached without a scope only the framework can issue, so a caller reachingUltiTools#getDataStore()directly --publicin the published jar -- still cannot obtain an operator for an entity it does not own.As of 02-12, the two legacy overloads also refuse an unowned entity --
checkOwnership(UltiToolsPlugin, Class)andcheckOwnership(java.io.File, Class)run as the first statement of every backend this framework ships. The distinction this paragraph draws is narrower than it once was, but still real: this method's credential is unforgeable by construction, so calling it correctly is impossible to get wrong. The legacy overloads instead resolve the caller after the fact -- a reverse folder lookup, or an entity-ownership registry consult -- which only protects a caller when theDataStoreimplementation it reaches has actually wired that resolution in; a hypothetical fourth implementation that overridesgetOperator(UltiToolsPlugin, Class)directly without callingcheckOwnership(UltiToolsPlugin, Class)would reopen the bypass for that one overload, with nothing but convention (and this javadoc) stopping it. No such gap exists for this method: there is no credential to skip checking, because there is no way to obtain one that was not already checked at minting time.02-13 (CR-01): the check above used to delegate to
getOperator(java.io.File, Class)for every scope, internal or external -- which for an INTERNAL scope meant reachingcheckOwnership(java.io.File, Class)'s now-removed core-folder exemption. It now delegates togetOperatorUnchecked(DataScope, Class)instead, an internal construction path with no ownership check of its own, reachable only after this method's ownscope.owns(...)check has already passed -- so the unforgeability guarantee above is no longer contingent on a second method's exemption logic agreeing with it.- Type Parameters:
T- Must inheritBaseDataEntity- Parameters:
scope- the requesting scopedataEntity- data entity class- Returns:
- data operator for that entity
- Throws:
DataAccessException- ifscopedoes not owndataEntity- Since:
- 6.3.0
-
getOperatorUnchecked
default <T extends BaseDataEntity<String>> DataOperator<T> getOperatorUnchecked(DataScope scope, Class<T> dataEntity) Internal, unchecked construction path used ONLY bygetOperator(DataScope, Class), called after its ownscope.owns(...)check has already passed (CR-01, 02-13). Building the actual operator -- path/identity resolution, connection-pool cache, operator cache,transactionManagerFor(...)wiring -- is exactly what the legacy overloads have always done for the internal/external shapescoperesolves to; what changed is thatgetOperator(DataScope, Class)no longer reaches that construction logic via the public, previously ownership-exemptgetOperator(java.io.File, Class)overload.This member is technically
public-- Java gives interface members no narrower visibility -- but it is not reachable as a bypass: nothing outside themanagerpackage can construct aDataScopeto pass to it (the same unforgeabilitygetOperator(DataScope, Class)itself relies on), so a caller able to invoke this method at all already holds a scope it could just as validly pass to the checked entry point instead. It is not part of the officially-extensibleDataStorecontract in the same sense the other members are; the default throws, matching the same "backend does not support this by default" posturegetDataSource(DataScope)already uses. The three backends this framework ships each override it.- Type Parameters:
T- Must inheritBaseDataEntity- Parameters:
scope- the requesting scope, already verified to owndataEntitydataEntity- data entity class- Returns:
- data operator for that entity
- Since:
- 6.3.0
-
destroyAllOperators
void destroyAllOperators()Save all possible caches and destroy all data operation classes.
-
DataStoreimplementation that overrides this method directly must callcheckOwnership(UltiToolsPlugin, Class)as its own first statement to get the refusal; the three backends shipped by this framework all do (02-12).