001package co.codewizards.cloudstore.core.repo.local; 002 003import java.lang.reflect.InvocationHandler; 004import java.net.URL; 005import java.util.Map; 006import java.util.UUID; 007import java.util.concurrent.locks.Lock; 008 009import co.codewizards.cloudstore.core.appid.AppIdRegistry; 010import co.codewizards.cloudstore.core.oio.File; 011import co.codewizards.cloudstore.core.progress.ProgressMonitor; 012 013public interface LocalRepoManager extends AutoCloseable { 014 String APP_ID_SIMPLE_ID = AppIdRegistry.getInstance().getAppIdOrFail().getSimpleId(); 015 016 String SYSTEM_PROPERTY_KEY_SIZE = APP_ID_SIMPLE_ID + ".repository.asymmetricKey.size"; 017 int DEFAULT_KEY_SIZE = 4096; 018 019 String SYSTEM_PROPERTY_CLOSE_DEFERRED_MILLIS = APP_ID_SIMPLE_ID + ".localRepoManager.closeDeferredMillis"; 020 long DEFAULT_CLOSE_DEFERRED_MILLIS = 20000; 021 022 String META_DIR_NAME = "." + APP_ID_SIMPLE_ID + "-repo"; 023 String TEMP_DIR_NAME = "." + APP_ID_SIMPLE_ID + "-tmp"; 024 String TEMP_NEW_FILE_PREFIX = "." + APP_ID_SIMPLE_ID + "-new_"; 025 026 String REPOSITORY_LOCK_FILE_NAME = APP_ID_SIMPLE_ID + "-repository.lock"; 027 String REPOSITORY_PROPERTIES_FILE_NAME = APP_ID_SIMPLE_ID + "-repository.properties"; 028 String PROP_REPOSITORY_ID = "repository.id"; 029 String PROP_VERSION = "repository.version"; 030 /** 031 * Aliases separated by '/' (because '/' is an illegal character for an alias). 032 * <p> 033 * To make scripting easier (e.g. using grep), the aliases start and end with a 034 * '/'. For example: "/alias1/alias2/alias3/" 035 */ 036 String PROP_REPOSITORY_ALIASES = "repository.aliases"; 037 038 String PERSISTENCE_PROPERTIES_FILE_NAME = APP_ID_SIMPLE_ID + "-persistence.properties"; 039 040 String VAR_REPOSITORY_ID = "repository.id"; 041 String VAR_LOCAL_ROOT = "repository.localRoot"; 042 String VAR_META_DIR = "repository.metaDir"; 043 044 /** 045 * Gets the repository's local root directory. 046 * <p> 047 * This file is canonical (absolute and symbolic links resolved). 048 * @return the repository's local root directory. Never <code>null</code>. 049 */ 050 File getLocalRoot(); 051 052 /** 053 * Gets the local repository's unique ID. 054 * <p> 055 * This is {@link LocalRepository#getEntityID() LocalRepository.entityID} in the local repository database. 056 * @return the local repository's unique ID. Never <code>null</code>. 057 */ 058 UUID getRepositoryId(); 059 060 /** 061 * Gets the local repository's private key. 062 * <p> 063 * This is always an RSA key - other key types are not (yet) supported. 064 * @return the local repository's private key. Never <code>null</code>. 065 */ 066 byte[] getPrivateKey(); 067 068 /** 069 * Gets the local repository's public key. 070 * <p> 071 * This is always an RSA key - other key types are not (yet) supported. 072 * @return the local repository's public key. Never <code>null</code>. 073 */ 074 byte[] getPublicKey(); 075 076 /** 077 * Gets the remote repository's public key. 078 * <p> 079 * This is always an RSA key - other key types are not (yet) supported. 080 * @param repositoryId the remote repository's unique ID. Must not be <code>null</code>. 081 * @return the remote repository's public key. Never <code>null</code>. 082 * @throws IllegalArgumentException if there is no remote-repository with the given {@code repositoryId}. 083 */ 084 byte[] getRemoteRepositoryPublicKeyOrFail(UUID repositoryId); 085 086 void addLocalRepoManagerCloseListener(LocalRepoManagerCloseListener listener); 087 088 void removeLocalRepoManagerCloseListener(LocalRepoManagerCloseListener listener); 089 090 /** 091 * Gets the <i>open</i> state. 092 * <p> 093 * If this is <code>false</code>, the {@link LocalRepoManager} instance cannot be used anymore. 094 * Due to the proxy-mechanism, this does, however, not mean that the backend is really shut down. 095 * @return the <i>open</i> state. 096 */ 097 boolean isOpen(); 098 099 /** 100 * Closes this {@link LocalRepoManager}. 101 * <p> 102 * <b>Important:</b> The {@link LocalRepoManagerFactory} always returns a proxy. It never returns 103 * the real backend-instance. Calling {@code close()} closes the proxy and thus renders it unusable. 104 * It decrements the real backend-instance's reference counter. As soon as this reaches 0, the backend 105 * is really closed - which may happen delayed (for performance reasons). 106 */ 107 @Override 108 void close(); 109 110 /** 111 * Begin a JDO transaction for read operations only in the underlying database. 112 * @return the transaction handle. Never <code>null</code>. 113 */ 114 LocalRepoTransaction beginReadTransaction(); 115 116 /** 117 * Begin a JDO transaction for read and write operations in the underlying database. 118 * @return the transaction handle. Never <code>null</code>. 119 */ 120 LocalRepoTransaction beginWriteTransaction(); 121 122 /** 123 * Synchronises the local file system with the local database. 124 * <p> 125 * Registers every directory and file in the repository's {@link #getLocalRoot() local root} and its 126 * sub-directories. 127 */ 128 void localSync(ProgressMonitor monitor); 129 130 /** 131 * Adds or relocates a remote repository. 132 * @param repositoryId the remote repository's unique ID. Must not be <code>null</code>. This is 133 * {@link LocalRepository#getEntityID() LocalRepository.entityID} in the remote database and will become 134 * {@link RemoteRepository#getEntityID() RemoteRepository.entityID} in the local database. 135 * @param remoteRoot the URL of the remote repository. May be <code>null</code> (in the server, a 136 * {@code RemoteRepository} never has a {@code remoteRoot}). 137 * @param localPathPrefix TODO 138 */ 139 void putRemoteRepository(UUID repositoryId, URL remoteRoot, byte[] publicKey, String localPathPrefix); 140 141 /** 142 * Deletes a remote repository from the local database. 143 * <p> 144 * Does nothing, if the specified repository does not exist. 145 * @param repositoryId the remote repository's unique ID. Must not be <code>null</code>. 146 */ 147 void deleteRemoteRepository(UUID repositoryId); 148 149 Map<UUID, URL> getRemoteRepositoryId2RemoteRootMap(); 150 151 /** 152 * Gets the local path-prefix (of the local repository managed by this {@code LocalRepoManager}) when syncing with 153 * the remote repository identified by the given {@code remoteRoot}. 154 * @param remoteRoot the remote repository's root-URL (not necessarily its real root, but the root URL connected 155 * to the local repository). Must not be <code>null</code>. 156 * @return the local path-prefix. Never <code>null</code>, but maybe empty. 157 * @throws IllegalArgumentException if there is no remote-repository with the given {@code remoteRoot}. 158 */ 159 String getLocalPathPrefixOrFail(URL remoteRoot); 160 161 /** 162 * Gets the local path-prefix (of the local repository managed by this {@code LocalRepoManager}) when syncing with 163 * the remote repository identified by the given {@code remoteRoot}. 164 * @param repositoryId the remote repository's unique ID. Must not be <code>null</code>. 165 * @return the local path-prefix. Never <code>null</code>, but maybe empty. 166 * @throws IllegalArgumentException if there is no remote-repository with the given {@code remoteRoot}. 167 */ 168 String getLocalPathPrefixOrFail(UUID repositoryId); 169 170 /** 171 * Gets the unique ID of the remote repository identified by the given {@code remoteRoot}. 172 * @param remoteRoot the remote repository's root-URL (not necessarily its real root, but the root URL connected 173 * to the local repository). Must not be <code>null</code>. 174 * @return the remote repository's unique ID. Never <code>null</code>. 175 * @throws IllegalArgumentException if there is no remote-repository with the given {@code remoteRoot}. 176 */ 177 UUID getRemoteRepositoryIdOrFail(URL remoteRoot); 178 179 Lock getLock(); 180 181 /** 182 * @deprecated <b>Do not invoke this method directly!</b> It is declared in this interface to make sure the 183 * proxy's {@link InvocationHandler} is invoked when the garbage-collector collects the proxy. 184 */ 185 @Deprecated 186 void finalize() throws Throwable; 187 188 void putRepositoryAlias(String repositoryAlias); 189 190 void removeRepositoryAlias(String repositoryAlias); 191 192 LocalRepoMetaData getLocalRepoMetaData(); 193}