EmbeddedSearchService.java
/*******************************************************************************
* Copyright (c) 2025 Carsten Hammer.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Carsten Hammer
*******************************************************************************/
package org.sandbox.jdt.internal.ui.search.gitindex;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
/**
* Singleton service that manages the {@link SemanticSearchClient} connecting to
* the {@code sandbox-jgit-server-webapp} REST backend.
*
* <h2>Architecture</h2>
*
* <pre>
* Eclipse Plugin (sandbox_extra_search)
* └── EmbeddedSearchService (this class — lazy singleton)
* └── SemanticSearchClient → REST HTTP calls → sandbox-jgit-server-webapp
* ├── GitSearchView → searchBySymbol / searchByType / ...
* ├── JavaTypeHistoryView → getFileHistory()
* └── CommitAnalyticsView → getAuthorStatistics()
* </pre>
*
* <p>
* No dependency on Hibernate, DJL, Lucene, HSQLDB, or Jakarta Persistence.
* Start the backend with: {@code cd sandbox-jgit-server-webapp && mvn spring-boot:run}
* </p>
*
* @see SemanticSearchClient
* @see RepositoryIndexService
*/
public class EmbeddedSearchService {
private static final ILog LOG= Platform.getLog(EmbeddedSearchService.class);
private static EmbeddedSearchService instance;
private boolean initialized;
private EmbeddedSearchService() {
// singleton
}
/**
* Returns the singleton instance, creating it on first access.
*
* @return the embedded search service instance
*/
public static synchronized EmbeddedSearchService getInstance() {
if (instance == null) {
instance= new EmbeddedSearchService();
}
return instance;
}
/**
* Initializes the REST search client. Safe to call multiple times —
* subsequent calls are no-ops.
*
* @param stateLocation the Eclipse plugin state location (unused, kept for
* API compatibility)
*/
public void initialize(IPath stateLocation) {
if (initialized) {
return;
}
SemanticSearchClient.getInstance();
LOG.info("Git Search: REST client initialized (backend: " //$NON-NLS-1$
+ SemanticSearchClient.DEFAULT_BASE_URL + ")"); //$NON-NLS-1$
initialized= true;
}
/**
* Returns whether the service has been initialized.
*
* @return {@code true} if initialized
*/
public boolean isInitialized() {
return initialized;
}
/**
* Returns whether the REST backend is reachable.
*
* @return {@code true} if the health endpoint responds with HTTP 200
*/
public boolean isAvailable() {
return initialized && SemanticSearchClient.getInstance().isAvailable();
}
/**
* Shuts down the service and releases resources. Called when the plugin is
* stopped.
*/
public void shutdown() {
if (!initialized) {
return;
}
initialized= false;
LOG.info("Git Search: REST search service shut down"); //$NON-NLS-1$
}
/**
* Returns the REST search client, lazily initializing the service on first
* access if necessary.
*
* @return the {@link SemanticSearchClient} instance
*/
public SemanticSearchClient getSearchClient() {
if (!initialized) {
initialize(null);
}
return SemanticSearchClient.getInstance();
}
}