001: /*
002: * Copyright Aduna (http://www.aduna-software.com/) (c) 2007.
003: *
004: * Licensed under the Aduna BSD-style license.
005: */
006: package org.openrdf.repository.manager;
007:
008: import java.io.File;
009: import java.io.IOException;
010: import java.net.MalformedURLException;
011: import java.util.ArrayList;
012: import java.util.List;
013:
014: import info.aduna.io.FileUtil;
015:
016: import org.openrdf.repository.DelegatingRepository;
017: import org.openrdf.repository.Repository;
018: import org.openrdf.repository.RepositoryConnection;
019: import org.openrdf.repository.RepositoryException;
020: import org.openrdf.repository.config.DelegatingRepositoryImplConfig;
021: import org.openrdf.repository.config.RepositoryConfig;
022: import org.openrdf.repository.config.RepositoryConfigException;
023: import org.openrdf.repository.config.RepositoryConfigUtil;
024: import org.openrdf.repository.config.RepositoryFactory;
025: import org.openrdf.repository.config.RepositoryImplConfig;
026: import org.openrdf.repository.config.RepositoryRegistry;
027: import org.openrdf.repository.event.base.RepositoryConnectionListenerAdapter;
028:
029: /**
030: * An implementation of the {@link RepositoryManager} interface that operates
031: * directly on the repository data files in the local file system.
032: *
033: * @author Arjohn Kampman
034: */
035: public class LocalRepositoryManager extends RepositoryManager {
036:
037: /*-----------*
038: * Constants *
039: *-----------*/
040:
041: public static final String REPOSITORIES_DIR = "repositories";
042:
043: /*-----------*
044: * Variables *
045: *-----------*/
046:
047: /**
048: * The base dir to resolve any relative paths against.
049: */
050: private File baseDir;
051:
052: /*--------------*
053: * Constructors *
054: *--------------*/
055:
056: /**
057: * Creates a new RepositoryManager that operates on the specfified base
058: * directory.
059: *
060: * @param baseDir
061: * The base directory where data for repositories can be stored, among
062: * other things.
063: */
064: public LocalRepositoryManager(File baseDir) {
065: super ();
066:
067: this .baseDir = baseDir;
068: }
069:
070: /*---------*
071: * Methods *
072: *---------*/
073:
074: @Override
075: protected SystemRepository createSystemRepository()
076: throws RepositoryException {
077: File systemDir = getRepositoryDir(SystemRepository.ID);
078: SystemRepository systemRepos = new SystemRepository(systemDir);
079: systemRepos.initialize();
080:
081: systemRepos
082: .addRepositoryConnectionListener(new ConfigChangeListener());
083: return systemRepos;
084: }
085:
086: /**
087: * Gets the base dir against which to resolve relative paths.
088: */
089: public File getBaseDir() {
090: return baseDir;
091: }
092:
093: /**
094: * Resolves the specified path against the manager's base directory.
095: *
096: * @see #getDataDir
097: */
098: public File resolvePath(String path) {
099: return new File(getBaseDir(), path);
100: }
101:
102: public File getRepositoryDir(String repositoryID) {
103: File repositoriesDir = resolvePath(REPOSITORIES_DIR);
104: return new File(repositoriesDir, repositoryID);
105: }
106:
107: @Override
108: public SystemRepository getSystemRepository() {
109: return (SystemRepository) super .getSystemRepository();
110: }
111:
112: @Override
113: protected Repository createRepository(String id)
114: throws RepositoryConfigException, RepositoryException {
115: Repository systemRepository = getSystemRepository();
116:
117: RepositoryConnection con = systemRepository.getConnection();
118: try {
119: Repository repository = null;
120:
121: RepositoryConfig repConfig = RepositoryConfigUtil
122: .getRepositoryConfig(systemRepository, id);
123: if (repConfig != null) {
124: repConfig.validate();
125:
126: repository = createRepositoryStack(repConfig
127: .getRepositoryImplConfig());
128: repository.setDataDir(getRepositoryDir(id));
129: repository.initialize();
130: }
131:
132: return repository;
133: } finally {
134: con.close();
135: }
136: }
137:
138: /**
139: * Creates the stack of Repository objects for the repository represented by
140: * the specified <tt>repositoryImplNode</tt>.
141: *
142: * @param con
143: * A connection to the repository containing the repository
144: * configuration.
145: * @param repositoryImplNode
146: * The node representing the to-be-created repository in the
147: * configuration.
148: * @return The created repository, or <tt>null</tt> if no such repository
149: * exists.
150: * @throws RepositoryConfigException
151: * If no repository could be created due to invalid or incomplete
152: * configuration data.
153: */
154: private Repository createRepositoryStack(RepositoryImplConfig config)
155: throws RepositoryConfigException {
156: RepositoryFactory factory = RepositoryRegistry.getInstance()
157: .get(config.getType());
158: if (factory == null) {
159: throw new RepositoryConfigException(
160: "Unsupported repository type: " + config.getType());
161: }
162:
163: Repository repository = factory.getRepository(config);
164:
165: if (config instanceof DelegatingRepositoryImplConfig) {
166: RepositoryImplConfig delegateConfig = ((DelegatingRepositoryImplConfig) config)
167: .getDelegate();
168:
169: Repository delegate = createRepositoryStack(delegateConfig);
170:
171: try {
172: ((DelegatingRepository) repository)
173: .setDelegate(delegate);
174: } catch (ClassCastException e) {
175: throw new RepositoryConfigException(
176: "Delegate specified for repository that is not a DelegatingRepository: "
177: + delegate.getClass());
178: }
179: }
180:
181: return repository;
182: }
183:
184: @Override
185: public RepositoryInfo getRepositoryInfo(String id)
186: throws RepositoryException {
187: try {
188: RepositoryConfig config = null;
189: if (id.equals(SystemRepository.ID)) {
190: config = new RepositoryConfig(id,
191: new SystemRepositoryConfig());
192: } else {
193: config = getRepositoryConfig(id);
194: }
195:
196: RepositoryInfo repInfo = new RepositoryInfo();
197: repInfo.setId(id);
198: repInfo.setDescription(config.getTitle());
199: try {
200: repInfo.setLocation(getRepositoryDir(id).toURI()
201: .toURL());
202: } catch (MalformedURLException mue) {
203: throw new RepositoryException(
204: "Location of repository does not resolve to a valid URL",
205: mue);
206: }
207:
208: repInfo.setReadable(true);
209: repInfo.setWritable(true);
210:
211: return repInfo;
212: } catch (RepositoryConfigException rce) {
213: // FIXME: don't fetch info through config parsing
214: throw new RepositoryException(
215: "Unable to retrieve existing configurations", rce);
216: }
217: }
218:
219: @Override
220: public List<RepositoryInfo> getAllRepositoryInfos(
221: boolean skipSystemRepo) throws RepositoryException {
222: List<RepositoryInfo> result = new ArrayList<RepositoryInfo>();
223:
224: for (String id : getRepositoryIDs()) {
225: if (!skipSystemRepo || !id.equals(SystemRepository.ID)) {
226: result.add(getRepositoryInfo(id));
227: }
228: }
229:
230: return result;
231: }
232:
233: class ConfigChangeListener extends
234: RepositoryConnectionListenerAdapter {
235:
236: @Override
237: public void commit(RepositoryConnection con) {
238: refresh();
239: }
240: }
241:
242: @Override
243: protected void cleanUpRepository(String repositoryID)
244: throws IOException {
245: File dataDir = getRepositoryDir(repositoryID);
246:
247: if (dataDir.isDirectory()) {
248: logger.debug("Cleaning up data dir {} for repository {}",
249: dataDir.getAbsolutePath(), repositoryID);
250: FileUtil.deleteDir(dataDir);
251: }
252: }
253: }
|