or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

auto-configuration.mdheader-theme-resolution.mdindex.mdservice-theme-resolution.mdtheme-resolution.mdtheme-sources.md

theme-sources.mddocs/

0

# Theme Sources

1

2

Theme source implementations that load and manage theme properties and resources from various locations.

3

4

## Capabilities

5

6

### DefaultCasThemeSource

7

8

Default theme source implementation that searches template prefixes for theme properties and supports hierarchical theme inheritance.

9

10

```java { .api }

11

/**

12

* Default theme source that extends ResourceBundleThemeSource with CAS-specific features

13

*/

14

public class DefaultCasThemeSource extends ResourceBundleThemeSource {

15

16

/**

17

* Constructor requiring CAS configuration properties

18

* @param casProperties CAS configuration containing template prefixes and theme settings

19

*/

20

public DefaultCasThemeSource(CasConfigurationProperties casProperties);

21

22

/**

23

* Creates message source for theme properties, searches template prefixes first

24

* @param basename Theme base name (e.g., "default", "custom")

25

* @return MessageSource containing theme properties and messages

26

*/

27

@Nonnull

28

@Override

29

protected MessageSource createMessageSource(@Nonnull String basename);

30

31

/**

32

* Creates hierarchical message source with custom and default theme support

33

* @param basename Theme base name

34

* @return MessageSource with parent-child hierarchy

35

*/

36

protected MessageSource createExtendedMessageSource(String basename);

37

38

/**

39

* Loads properties from specified path and creates static message source

40

* @param path Path to theme properties file

41

* @return StaticMessageSource with loaded properties

42

* @throws Exception if resource cannot be loaded

43

*/

44

protected StaticMessageSource loadMessageSourceFromPath(String path) throws Exception;

45

}

46

```

47

48

**Usage Examples:**

49

50

```java

51

import org.apereo.cas.services.web.DefaultCasThemeSource;

52

import org.apereo.cas.configuration.CasConfigurationProperties;

53

54

// Create default theme source

55

CasConfigurationProperties properties = // ... configured instance

56

DefaultCasThemeSource themeSource = new DefaultCasThemeSource(properties);

57

58

// Theme source will search for properties in configured template prefixes:

59

// /etc/cas/themes/mytheme.properties

60

// classpath:/themes/mytheme.properties

61

// Standard resource bundle locations

62

```

63

64

### AggregateCasThemeSource

65

66

Theme source that merges all theme resource bundles it can find across all configured template prefixes.

67

68

```java { .api }

69

/**

70

* Theme source that aggregates properties from multiple theme resource bundles

71

*/

72

public class AggregateCasThemeSource extends ResourceBundleThemeSource {

73

74

/**

75

* Constructor requiring CAS configuration properties

76

* @param casProperties CAS configuration containing template prefixes

77

*/

78

public AggregateCasThemeSource(CasConfigurationProperties casProperties);

79

80

/**

81

* Creates message source that aggregates properties from all template prefixes

82

* @param basename Theme base name to search for across all prefixes

83

* @return MessageSource containing merged properties from all found resources

84

*/

85

@Nonnull

86

@Override

87

protected MessageSource createMessageSource(@Nonnull String basename);

88

}

89

```

90

91

**Usage Examples:**

92

93

```java

94

import org.apereo.cas.services.web.AggregateCasThemeSource;

95

96

// Create aggregate theme source

97

AggregateCasThemeSource themeSource = new AggregateCasThemeSource(properties);

98

99

// Will merge properties from all matching files:

100

// /etc/cas/themes/mytheme.properties

101

// /var/cas/themes/mytheme.properties

102

// classpath:/themes/mytheme.properties

103

// All properties are combined into single MessageSource

104

```

105

106

### CasThemeResourceBundleMessageSource

107

108

Enhanced message source for theme resource bundles with improved error handling and validation.

109

110

```java { .api }

111

/**

112

* Custom message source for theme resource bundles with enhanced error handling

113

* Validates that resource bundles are not empty before returning them

114

*/

115

public class CasThemeResourceBundleMessageSource extends ResourceBundleMessageSource {

116

117

/**

118

* Gets resource bundle with null-safe error handling and validation

119

* Returns null if bundle is not found, empty, or an exception occurs

120

* @param basename Base name of the resource bundle

121

* @param locale Locale for the bundle

122

* @return ResourceBundle if found and non-empty, null otherwise for graceful fallback

123

*/

124

@Override

125

protected ResourceBundle doGetBundle(String basename, Locale locale);

126

}

127

```

128

129

**Usage Examples:**

130

131

```java

132

import org.apereo.cas.services.web.CasThemeResourceBundleMessageSource;

133

134

// Create enhanced message source for theme validation

135

CasThemeResourceBundleMessageSource messageSource = new CasThemeResourceBundleMessageSource();

136

messageSource.setBasename("mytheme");

137

138

// The message source will validate bundle existence and content

139

// Returns null for missing or empty bundles, allowing graceful fallback

140

ResourceBundle bundle = messageSource.doGetBundle("mytheme", Locale.ENGLISH);

141

if (bundle != null) {

142

// Bundle exists and has content

143

String message = bundle.getString("login.welcome");

144

}

145

```

146

147

## Theme Property File Format

148

149

Theme properties files use standard Java properties format:

150

151

```properties

152

# Theme metadata

153

theme.name=My Custom Theme

154

theme.description=A beautiful custom theme for CAS

155

156

# CSS and JavaScript resources

157

theme.css.file=css/custom.css

158

theme.js.file=js/custom.js

159

160

# Localized messages

161

login.welcome=Welcome to CAS

162

login.instructions=Please enter your credentials

163

error.authentication.failed=Authentication failed

164

```

165

166

## Theme Search Strategy

167

168

### DefaultCasThemeSource Search Order

169

170

1. **Template Prefixes**: Searches configured template prefixes in order

171

- Example: `/etc/cas/themes/mytheme.properties`

172

- Example: `classpath:/themes/mytheme.properties`

173

174

2. **Hierarchical Support**: Creates parent-child message source hierarchy

175

- Custom theme inherits from default theme

176

- Replaces `-default` with `-custom` in basename

177

178

3. **Fallback**: Uses standard ResourceBundle mechanism if not found in prefixes

179

180

### AggregateCasThemeSource Merging

181

182

1. **Collect All**: Finds all matching property files across all template prefixes

183

2. **Merge Properties**: Combines all properties into single MessageSource

184

3. **Parent Chain**: Sets standard ResourceBundle as parent for fallback

185

186

## Resource Loading

187

188

Both theme sources support loading from:

189

190

- **File System**: `file:/path/to/themes/`

191

- **Classpath**: `classpath:/themes/`

192

- **HTTP URLs**: `http://example.com/themes/` (via ResourceUtils)

193

- **Custom Resources**: Any Spring Resource implementation

194

195

```java

196

// Example template prefix configurations

197

cas.view.template-prefixes[0]=file:/etc/cas/themes/

198

cas.view.template-prefixes[1]=classpath:/themes/

199

cas.view.template-prefixes[2]=http://cdn.example.com/cas-themes/

200

```

201

202

## Locale Support

203

204

Theme sources support internationalization:

205

206

```java

207

// DefaultCasThemeSource loads properties for multiple locales

208

List.of(Locale.US, Locale.CANADA, Locale.ENGLISH).forEach(locale -> {

209

source.addMessage(key.toString(), locale, value.toString());

210

});

211

212

// AggregateCasThemeSource uses English locale by default

213

source.addMessage(key.toString(), Locale.ENGLISH, value.toString());

214

```

215

216

## Error Handling

217

218

- **Resource Not Found**: Gracefully falls back to parent message sources

219

- **IO Exceptions**: Logged as warnings, theme loading continues

220

- **Invalid Properties**: Individual property errors don't stop theme loading

221

- **Bundle Validation**: CasThemeResourceBundleMessageSource validates bundle contents