package co.codewizards.cloudstore.core.repo.local;
import java.lang.reflect.InvocationHandler;
import java.net.URL;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import co.codewizards.cloudstore.core.appid.AppIdRegistry;
import co.codewizards.cloudstore.core.oio.File;
import co.codewizards.cloudstore.core.progress.ProgressMonitor;
public interface LocalRepoManager extends AutoCloseable {
String APP_ID_SIMPLE_ID = AppIdRegistry.getInstance().getAppIdOrFail().getSimpleId();
String SYSTEM_PROPERTY_KEY_SIZE = APP_ID_SIMPLE_ID + ".repository.asymmetricKey.size";
int DEFAULT_KEY_SIZE = 4096;
String SYSTEM_PROPERTY_CLOSE_DEFERRED_MILLIS = APP_ID_SIMPLE_ID + ".localRepoManager.closeDeferredMillis";
long DEFAULT_CLOSE_DEFERRED_MILLIS = 20000;
String META_DIR_NAME = "." + APP_ID_SIMPLE_ID + "-repo";
String TEMP_DIR_NAME = "." + APP_ID_SIMPLE_ID + "-tmp";
String TEMP_NEW_FILE_PREFIX = "." + APP_ID_SIMPLE_ID + "-new_";
String REPOSITORY_LOCK_FILE_NAME = APP_ID_SIMPLE_ID + "-repository.lock";
String REPOSITORY_PROPERTIES_FILE_NAME = APP_ID_SIMPLE_ID + "-repository.properties";
String PROP_REPOSITORY_ID = "repository.id";
String PROP_VERSION = "repository.version";
/**
* Aliases separated by '/' (because '/' is an illegal character for an alias).
* <p>
* To make scripting easier (e.g. using grep), the aliases start and end with a
* '/'. For example: "/alias1/alias2/alias3/"
*/
String PROP_REPOSITORY_ALIASES = "repository.aliases";
String PERSISTENCE_PROPERTIES_FILE_NAME = APP_ID_SIMPLE_ID + "-persistence.properties";
String VAR_REPOSITORY_ID = "repository.id";
String VAR_LOCAL_ROOT = "repository.localRoot";
String VAR_META_DIR = "repository.metaDir";
/**
* Gets the repository's local root directory.
* <p>
* This file is canonical (absolute and symbolic links resolved).
* @return the repository's local root directory. Never <code>null</code>.
*/
File getLocalRoot();
/**
* Gets the local repository's unique ID.
* <p>
* This is {@link LocalRepository#getEntityID() LocalRepository.entityID} in the local repository database.
* @return the local repository's unique ID. Never <code>null</code>.
*/
UUID getRepositoryId();
/**
* Gets the local repository's private key.
* <p>
* This is always an RSA key - other key types are not (yet) supported.
* @return the local repository's private key. Never <code>null</code>.
*/
byte[] getPrivateKey();
/**
* Gets the local repository's public key.
* <p>
* This is always an RSA key - other key types are not (yet) supported.
* @return the local repository's public key. Never <code>null</code>.
*/
byte[] getPublicKey();
/**
* Gets the remote repository's public key.
* <p>
* This is always an RSA key - other key types are not (yet) supported.
* @param repositoryId the remote repository's unique ID. Must not be <code>null</code>.
* @return the remote repository's public key. Never <code>null</code>.
* @throws IllegalArgumentException if there is no remote-repository with the given {@code repositoryId}.
*/
byte[] getRemoteRepositoryPublicKeyOrFail(UUID repositoryId);
void addLocalRepoManagerCloseListener(LocalRepoManagerCloseListener listener);
void removeLocalRepoManagerCloseListener(LocalRepoManagerCloseListener listener);
/**
* Gets the <i>open</i> state.
* <p>
* If this is <code>false</code>, the {@link LocalRepoManager} instance cannot be used anymore.
* Due to the proxy-mechanism, this does, however, not mean that the backend is really shut down.
* @return the <i>open</i> state.
*/
boolean isOpen();
/**
* Closes this {@link LocalRepoManager}.
* <p>
* <b>Important:</b> The {@link LocalRepoManagerFactory} always returns a proxy. It never returns
* the real backend-instance. Calling {@code close()} closes the proxy and thus renders it unusable.
* It decrements the real backend-instance's reference counter. As soon as this reaches 0, the backend
* is really closed - which may happen delayed (for performance reasons).
*/
@Override
void close();
/**
* Begin a JDO transaction for read operations only in the underlying database.
* @return the transaction handle. Never <code>null</code>.
*/
LocalRepoTransaction beginReadTransaction();
/**
* Begin a JDO transaction for read and write operations in the underlying database.
* @return the transaction handle. Never <code>null</code>.
*/
LocalRepoTransaction beginWriteTransaction();
/**
* Synchronises the local file system with the local database.
* <p>
* Registers every directory and file in the repository's {@link #getLocalRoot() local root} and its
* sub-directories.
*/
void localSync(ProgressMonitor monitor);
/**
* Adds or relocates a remote repository.
* @param repositoryId the remote repository's unique ID. Must not be <code>null</code>. This is
* {@link LocalRepository#getEntityID() LocalRepository.entityID} in the remote database and will become
* {@link RemoteRepository#getEntityID() RemoteRepository.entityID} in the local database.
* @param remoteRoot the URL of the remote repository. May be <code>null</code> (in the server, a
* {@code RemoteRepository} never has a {@code remoteRoot}).
* @param localPathPrefix TODO
*/
void putRemoteRepository(UUID repositoryId, URL remoteRoot, byte[] publicKey, String localPathPrefix);
/**
* Deletes a remote repository from the local database.
* <p>
* Does nothing, if the specified repository does not exist.
* @param repositoryId the remote repository's unique ID. Must not be <code>null</code>.
*/
void deleteRemoteRepository(UUID repositoryId);
Map<UUID, URL> getRemoteRepositoryId2RemoteRootMap();
/**
* Gets the local path-prefix (of the local repository managed by this {@code LocalRepoManager}) when syncing with
* the remote repository identified by the given {@code remoteRoot}.
* @param remoteRoot the remote repository's root-URL (not necessarily its real root, but the root URL connected
* to the local repository). Must not be <code>null</code>.
* @return the local path-prefix. Never <code>null</code>, but maybe empty.
* @throws IllegalArgumentException if there is no remote-repository with the given {@code remoteRoot}.
*/
String getLocalPathPrefixOrFail(URL remoteRoot);
/**
* Gets the local path-prefix (of the local repository managed by this {@code LocalRepoManager}) when syncing with
* the remote repository identified by the given {@code remoteRoot}.
* @param repositoryId the remote repository's unique ID. Must not be <code>null</code>.
* @return the local path-prefix. Never <code>null</code>, but maybe empty.
* @throws IllegalArgumentException if there is no remote-repository with the given {@code remoteRoot}.
*/
String getLocalPathPrefixOrFail(UUID repositoryId);
/**
* Gets the unique ID of the remote repository identified by the given {@code remoteRoot}.
* @param remoteRoot the remote repository's root-URL (not necessarily its real root, but the root URL connected
* to the local repository). Must not be <code>null</code>.
* @return the remote repository's unique ID. Never <code>null</code>.
* @throws IllegalArgumentException if there is no remote-repository with the given {@code remoteRoot}.
*/
UUID getRemoteRepositoryIdOrFail(URL remoteRoot);
Lock getLock();
/**
* @deprecated <b>Do not invoke this method directly!</b> It is declared in this interface to make sure the
* proxy's {@link InvocationHandler} is invoked when the garbage-collector collects the proxy.
*/
@Deprecated
void finalize() throws Throwable;
void putRepositoryAlias(String repositoryAlias);
void removeRepositoryAlias(String repositoryAlias);
LocalRepoMetaData getLocalRepoMetaData();
}