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