keycloak
公開メンバ関数 | 静的公開メンバ関数 | 静的公開変数類 | 限定公開メンバ関数 | 非公開メンバ関数 | 非公開変数類 | 静的非公開変数類 | 全メンバ一覧
org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider クラス
org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider の継承関係図
Inheritance graph
org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider 連携図
Collaboration graph

公開メンバ関数

 LiquibaseJpaUpdaterProvider (KeycloakSession session)
 
void update (Connection connection, String defaultSchema)
 
void export (Connection connection, String defaultSchema, File file)
 
Status validate (Connection connection, String defaultSchema)
 
void close ()
 

静的公開メンバ関数

static String getTable (String table, String defaultSchema)
 

静的公開変数類

static final String CHANGELOG = "META-INF/jpa-changelog-master.xml"
 
static final String DEPLOYMENT_ID_COLUMN = "DEPLOYMENT_ID"
 

限定公開メンバ関数

void updateChangeSet (Liquibase liquibase, Connection connection, Writer exportWriter) throws LiquibaseException, SQLException
 
Status validateChangeSet (Liquibase liquibase, String changelog) throws LiquibaseException
 

非公開メンバ関数

void update (Connection connection, File file, String defaultSchema)
 
void outputChangeLogTableCreationScript (Liquibase liquibase, final Writer exportWriter) throws DatabaseException
 
void resetLiquibaseServices (Liquibase liquibase)
 
List< ChangeSet > getLiquibaseUnrunChangeSets (Liquibase liquibase)
 
Liquibase getLiquibaseForKeycloakUpdate (Connection connection, String defaultSchema) throws LiquibaseException
 
Liquibase getLiquibaseForCustomProviderUpdate (Connection connection, String defaultSchema, String changelogLocation, ClassLoader classloader, String changelogTableName) throws LiquibaseException
 

非公開変数類

final KeycloakSession session
 

静的非公開変数類

static final Logger logger = Logger.getLogger(LiquibaseJpaUpdaterProvider.class)
 

詳解

著者
Stian Thorgersen

構築子と解体子

◆ LiquibaseJpaUpdaterProvider()

org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.LiquibaseJpaUpdaterProvider ( KeycloakSession  session)
inline
75  {
76  this.session = session;
77  }
final KeycloakSession session
Definition: LiquibaseJpaUpdaterProvider.java:73

関数詳解

◆ close()

void org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.close ( )
inline

org.keycloak.provider.Providerを実装しています。

298  {
299  }

◆ export()

void org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.export ( Connection  connection,
String  defaultSchema,
File  file 
)
inline

org.keycloak.connections.jpa.updater.JpaUpdaterProviderを実装しています。

85  {
86  update(connection, file, defaultSchema);
87  }
void update(Connection connection, String defaultSchema)
Definition: LiquibaseJpaUpdaterProvider.java:80

◆ getLiquibaseForCustomProviderUpdate()

Liquibase org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.getLiquibaseForCustomProviderUpdate ( Connection  connection,
String  defaultSchema,
String  changelogLocation,
ClassLoader  classloader,
String  changelogTableName 
) throws LiquibaseException
inlineprivate
292  {
293  LiquibaseConnectionProvider liquibaseProvider = session.getProvider(LiquibaseConnectionProvider.class);
294  return liquibaseProvider.getLiquibaseForCustomUpdate(connection, defaultSchema, changelogLocation, classloader, changelogTableName);
295  }
< T extends Provider > T getProvider(Class< T > clazz)
final KeycloakSession session
Definition: LiquibaseJpaUpdaterProvider.java:73

◆ getLiquibaseForKeycloakUpdate()

Liquibase org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.getLiquibaseForKeycloakUpdate ( Connection  connection,
String  defaultSchema 
) throws LiquibaseException
inlineprivate
287  {
288  LiquibaseConnectionProvider liquibaseProvider = session.getProvider(LiquibaseConnectionProvider.class);
289  return liquibaseProvider.getLiquibase(connection, defaultSchema);
290  }
< T extends Provider > T getProvider(Class< T > clazz)
final KeycloakSession session
Definition: LiquibaseJpaUpdaterProvider.java:73

◆ getLiquibaseUnrunChangeSets()

List<ChangeSet> org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.getLiquibaseUnrunChangeSets ( Liquibase  liquibase)
inlineprivate
279  {
280  // TODO tracked as: https://issues.jboss.org/browse/KEYCLOAK-3730
281  // TODO: When https://liquibase.jira.com/browse/CORE-2919 is resolved, replace the following two lines with:
282  // List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression(), false);
283  Method listUnrunChangeSets = Reflections.findDeclaredMethod(Liquibase.class, "listUnrunChangeSets", Contexts.class, LabelExpression.class, boolean.class);
284  return Reflections.invokeMethod(true, listUnrunChangeSets, List.class, liquibase, (Contexts) null, new LabelExpression(), false);
285  }

◆ getTable()

static String org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.getTable ( String  table,
String  defaultSchema 
)
inlinestatic
301  {
302  return defaultSchema != null ? defaultSchema + "." + table : table;
303  }

◆ outputChangeLogTableCreationScript()

void org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.outputChangeLogTableCreationScript ( Liquibase  liquibase,
final Writer  exportWriter 
) throws DatabaseException
inlineprivate
195  {
196  Database database = liquibase.getDatabase();
197 
198  Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
199  LoggingExecutor executor = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), exportWriter, database);
200  ExecutorService.getInstance().setExecutor(database, executor);
201 
202  executor.comment("*********************************************************************");
203  executor.comment("* Keycloak database creation script - apply this script to empty DB *");
204  executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
205 
206  executor.execute(new CreateDatabaseChangeLogTableStatement());
207  // DatabaseChangeLogLockTable is created before this code is executed and recreated if it does not exist automatically
208  // in org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService.init() called indirectly from
209  // KeycloakApplication constructor (search for waitForLock() call). Hence it is not included in the creation script.
210 
211  executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
212 
213  ExecutorService.getInstance().setExecutor(database, oldTemplate);
214  }

◆ resetLiquibaseServices()

void org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.resetLiquibaseServices ( Liquibase  liquibase)
inlineprivate
273  {
274  Method resetServices = Reflections.findDeclaredMethod(Liquibase.class, "resetServices");
275  Reflections.invokeMethod(true, resetServices, liquibase);
276  }

◆ update() [1/2]

void org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.update ( Connection  connection,
String  defaultSchema 
)
inline

org.keycloak.connections.jpa.updater.JpaUpdaterProviderを実装しています。

80  {
81  update(connection, null, defaultSchema);
82  }
void update(Connection connection, String defaultSchema)
Definition: LiquibaseJpaUpdaterProvider.java:80

◆ update() [2/2]

void org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.update ( Connection  connection,
File  file,
String  defaultSchema 
)
inlineprivate
89  {
90  logger.debug("Starting database update");
91 
92  // Need ThreadLocal as liquibase doesn't seem to have API to inject custom objects into tasks
93  ThreadLocalSessionContext.setCurrentSession(session);
94 
95  Writer exportWriter = null;
96  try {
97  // Run update with keycloak master changelog first
98  Liquibase liquibase = getLiquibaseForKeycloakUpdate(connection, defaultSchema);
99  if (file != null) {
100  exportWriter = new FileWriter(file);
101  }
102  updateChangeSet(liquibase, connection, exportWriter);
103 
104  // Run update for each custom JpaEntityProvider
105  Set<JpaEntityProvider> jpaProviders = session.getAllProviders(JpaEntityProvider.class);
106  for (JpaEntityProvider jpaProvider : jpaProviders) {
107  String customChangelog = jpaProvider.getChangelogLocation();
108  if (customChangelog != null) {
109  String factoryId = jpaProvider.getFactoryId();
110  String changelogTableName = JpaUtils.getCustomChangelogTableName(factoryId);
111  liquibase = getLiquibaseForCustomProviderUpdate(connection, defaultSchema, customChangelog, jpaProvider.getClass().getClassLoader(), changelogTableName);
112  updateChangeSet(liquibase, connection, exportWriter);
113  }
114  }
115  } catch (LiquibaseException | IOException | SQLException e) {
116  throw new RuntimeException("Failed to update database", e);
117  } finally {
118  ThreadLocalSessionContext.removeCurrentSession();
119  if (exportWriter != null) {
120  try {
121  exportWriter.close();
122  } catch (IOException ioe) {
123  // ignore
124  }
125  }
126  }
127  }
Liquibase getLiquibaseForCustomProviderUpdate(Connection connection, String defaultSchema, String changelogLocation, ClassLoader classloader, String changelogTableName)
Definition: LiquibaseJpaUpdaterProvider.java:292
< T extends Provider > Set< T > getAllProviders(Class< T > clazz)
void updateChangeSet(Liquibase liquibase, Connection connection, Writer exportWriter)
Definition: LiquibaseJpaUpdaterProvider.java:129
final KeycloakSession session
Definition: LiquibaseJpaUpdaterProvider.java:73
static final Logger logger
Definition: LiquibaseJpaUpdaterProvider.java:67
Liquibase getLiquibaseForKeycloakUpdate(Connection connection, String defaultSchema)
Definition: LiquibaseJpaUpdaterProvider.java:287

◆ updateChangeSet()

void org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.updateChangeSet ( Liquibase  liquibase,
Connection  connection,
Writer  exportWriter 
) throws LiquibaseException, SQLException
inlineprotected
129  {
130  String changelog = liquibase.getChangeLogFile();
131  Database database = liquibase.getDatabase();
132  Table changelogTable = SnapshotGeneratorFactory.getInstance().getDatabaseChangeLogTable(new SnapshotControl(database, false, Table.class, Column.class), database);
133 
134  if (changelogTable != null) {
135  boolean hasDeploymentIdColumn = changelogTable.getColumn(DEPLOYMENT_ID_COLUMN) != null;
136 
137  // create DEPLOYMENT_ID column if it doesn't exist
138  if (!hasDeploymentIdColumn) {
139  ChangeLogHistoryService changelogHistoryService = ChangeLogHistoryServiceFactory.getInstance().getChangeLogService(database);
140  changelogHistoryService.generateDeploymentId();
141  String deploymentId = changelogHistoryService.getDeploymentId();
142 
143  logger.debugv("Adding missing column {0}={1} to {2} table", DEPLOYMENT_ID_COLUMN, deploymentId,changelogTable.getName());
144 
145  List<SqlStatement> statementsToExecute = new ArrayList<>();
146  statementsToExecute.add(new AddColumnStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(),
147  changelogTable.getName(), DEPLOYMENT_ID_COLUMN, "VARCHAR(10)", null));
148  statementsToExecute.add(new UpdateStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), changelogTable.getName())
149  .addNewColumnValue(DEPLOYMENT_ID_COLUMN, deploymentId));
150  statementsToExecute.add(new SetNullableStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(),
151  changelogTable.getName(), DEPLOYMENT_ID_COLUMN, "VARCHAR(10)", false));
152 
153  ExecutorService executorService = ExecutorService.getInstance();
154  Executor executor = executorService.getExecutor(liquibase.getDatabase());
155 
156  for (SqlStatement sql : statementsToExecute) {
157  executor.execute(sql);
158  database.commit();
159  }
160  }
161  }
162 
163  List<ChangeSet> changeSets = getLiquibaseUnrunChangeSets(liquibase);
164  if (!changeSets.isEmpty()) {
165  List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
166  if (ranChangeSets.isEmpty()) {
167  logger.infov("Initializing database schema. Using changelog {0}", changelog);
168  } else {
169  if (logger.isDebugEnabled()) {
170  logger.debugv("Updating database from {0} to {1}. Using changelog {2}", ranChangeSets.get(ranChangeSets.size() - 1).getId(), changeSets.get(changeSets.size() - 1).getId(), changelog);
171  } else {
172  logger.infov("Updating database. Using changelog {0}", changelog);
173  }
174  }
175 
176  if (exportWriter != null) {
177  if (ranChangeSets.isEmpty()) {
178  outputChangeLogTableCreationScript(liquibase, exportWriter);
179  }
180  liquibase.update((Contexts) null, new LabelExpression(), exportWriter, false);
181  } else {
182  liquibase.update((Contexts) null);
183  }
184 
185  logger.debugv("Completed database update for changelog {0}", changelog);
186  } else {
187  logger.debugv("Database is up to date for changelog {0}", changelog);
188  }
189 
190  // Needs to restart liquibase services to clear ChangeLogHistoryServiceFactory.getInstance().
191  // See https://issues.jboss.org/browse/KEYCLOAK-3769 for discussion relevant to why reset needs to be here
192  resetLiquibaseServices(liquibase);
193  }
static final String DEPLOYMENT_ID_COLUMN
Definition: LiquibaseJpaUpdaterProvider.java:71
void outputChangeLogTableCreationScript(Liquibase liquibase, final Writer exportWriter)
Definition: LiquibaseJpaUpdaterProvider.java:195
static final Logger logger
Definition: LiquibaseJpaUpdaterProvider.java:67
List< ChangeSet > getLiquibaseUnrunChangeSets(Liquibase liquibase)
Definition: LiquibaseJpaUpdaterProvider.java:279
void resetLiquibaseServices(Liquibase liquibase)
Definition: LiquibaseJpaUpdaterProvider.java:273

◆ validate()

Status org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.validate ( Connection  connection,
String  defaultSchema 
)
inline

org.keycloak.connections.jpa.updater.JpaUpdaterProviderを実装しています。

217  {
218  logger.debug("Validating if database is updated");
219  ThreadLocalSessionContext.setCurrentSession(session);
220 
221  try {
222  // Validate with keycloak master changelog first
223  Liquibase liquibase = getLiquibaseForKeycloakUpdate(connection, defaultSchema);
224 
225  Status status = validateChangeSet(liquibase, liquibase.getChangeLogFile());
226  if (status != Status.VALID) {
227  return status;
228  }
229 
230  // Validate each custom JpaEntityProvider
231  Set<JpaEntityProvider> jpaProviders = session.getAllProviders(JpaEntityProvider.class);
232  for (JpaEntityProvider jpaProvider : jpaProviders) {
233  String customChangelog = jpaProvider.getChangelogLocation();
234  if (customChangelog != null) {
235  String factoryId = jpaProvider.getFactoryId();
236  String changelogTableName = JpaUtils.getCustomChangelogTableName(factoryId);
237  liquibase = getLiquibaseForCustomProviderUpdate(connection, defaultSchema, customChangelog, jpaProvider.getClass().getClassLoader(), changelogTableName);
238  if (validateChangeSet(liquibase, liquibase.getChangeLogFile()) != Status.VALID) {
239  return Status.OUTDATED;
240  }
241  }
242  }
243  } catch (LiquibaseException e) {
244  throw new RuntimeException("Failed to validate database", e);
245  }
246 
247  return Status.VALID;
248  }
Liquibase getLiquibaseForCustomProviderUpdate(Connection connection, String defaultSchema, String changelogLocation, ClassLoader classloader, String changelogTableName)
Definition: LiquibaseJpaUpdaterProvider.java:292
< T extends Provider > Set< T > getAllProviders(Class< T > clazz)
final KeycloakSession session
Definition: LiquibaseJpaUpdaterProvider.java:73
static final Logger logger
Definition: LiquibaseJpaUpdaterProvider.java:67
Liquibase getLiquibaseForKeycloakUpdate(Connection connection, String defaultSchema)
Definition: LiquibaseJpaUpdaterProvider.java:287
Status validateChangeSet(Liquibase liquibase, String changelog)
Definition: LiquibaseJpaUpdaterProvider.java:250

◆ validateChangeSet()

Status org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.validateChangeSet ( Liquibase  liquibase,
String  changelog 
) throws LiquibaseException
inlineprotected
250  {
251  final Status result;
252  List<ChangeSet> changeSets = getLiquibaseUnrunChangeSets(liquibase);
253 
254  if (!changeSets.isEmpty()) {
255  if (changeSets.size() == liquibase.getDatabaseChangeLog().getChangeSets().size()) {
256  result = Status.EMPTY;
257  } else {
258  logger.debugf("Validation failed. Database is not up-to-date for changelog %s", changelog);
259  result = Status.OUTDATED;
260  }
261  } else {
262  logger.debugf("Validation passed. Database is up-to-date for changelog %s", changelog);
263  result = Status.VALID;
264  }
265 
266  // Needs to restart liquibase services to clear ChangeLogHistoryServiceFactory.getInstance().
267  // See https://issues.jboss.org/browse/KEYCLOAK-3769 for discussion relevant to why reset needs to be here
268  resetLiquibaseServices(liquibase);
269 
270  return result;
271  }
static final Logger logger
Definition: LiquibaseJpaUpdaterProvider.java:67
List< ChangeSet > getLiquibaseUnrunChangeSets(Liquibase liquibase)
Definition: LiquibaseJpaUpdaterProvider.java:279
void resetLiquibaseServices(Liquibase liquibase)
Definition: LiquibaseJpaUpdaterProvider.java:273

メンバ詳解

◆ CHANGELOG

final String org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.CHANGELOG = "META-INF/jpa-changelog-master.xml"
static

◆ DEPLOYMENT_ID_COLUMN

final String org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.DEPLOYMENT_ID_COLUMN = "DEPLOYMENT_ID"
static

◆ logger

final Logger org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.logger = Logger.getLogger(LiquibaseJpaUpdaterProvider.class)
staticprivate

◆ session

final KeycloakSession org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider.session
private

このクラス詳解は次のファイルから抽出されました: