use of org.apache.sis.storage.DataStore in project sis by apache.
the class FolderStoreProvider method open.
/**
* Shared implementation of public {@code open(…)} methods.
* Note that this method may modify the given {@code options} set for its own purpose.
*
* @param connector information about the storage (URL, path, <i>etc</i>).
* @param format format name for directory content, or {@code null} if unspecified.
* @param options whether to create a new directory, overwrite existing content, <i>etc</i>.
*/
private DataStore open(final StorageConnector connector, final String format, final EnumSet<StandardOpenOption> options) throws DataStoreException {
/*
* Determine now the provider to use for directory content. We do that for determining if the component
* has write capability. If not, then the WRITE, CREATE and related options will be ignored. If we can
* not determine whether the component store has write capabilities (i.e. if canWrite(…) returns null),
* assume that the answer is "yes".
*/
final DataStoreProvider componentProvider;
if (format != null) {
componentProvider = StoreUtilities.providerByFormatName(format.trim());
if (Boolean.FALSE.equals(StoreUtilities.canWrite(componentProvider.getClass()))) {
// No write capability.
options.clear();
}
} else {
componentProvider = null;
// Can not write if we don't know the components format.
options.clear();
}
final Path path = connector.getStorageAs(Path.class);
final Store store;
try {
/*
* If the user asked to create a new directory, we need to perform this task before
* to create the Store (otherwise constructor will fail with NoSuchFileException).
* In the particular case of CREATE_NEW, we unconditionally attempt to create the
* directory in order to rely on the atomic check performed by Files.createDirectory(…).
*/
boolean isNew = false;
if (options.contains(StandardOpenOption.CREATE)) {
if (options.contains(StandardOpenOption.CREATE_NEW) || Files.notExists(path)) {
// IOException if the directory already exists.
Files.createDirectory(path);
isNew = true;
}
}
if (isNew || (options.contains(StandardOpenOption.WRITE) && Files.isWritable(path))) {
// May throw NoSuchFileException.
store = new WritableStore(this, connector, path, componentProvider);
} else {
// May throw NoSuchFileException.
store = new Store(this, connector, path, componentProvider);
}
/*
* If there is a destructive operation to perform (TRUNCATE_EXISTING), do it last only
* after we have successfully created the data store. The check for directory existence
* is also done after creation to be sure to check the path used by the store.
*/
if (!Files.isDirectory(path)) {
throw new DataStoreException(Resources.format(Resources.Keys.FileIsNotAResourceDirectory_1, path));
}
if (options.contains(StandardOpenOption.TRUNCATE_EXISTING)) {
WritableStore.deleteRecursively(path, false);
}
} catch (IOException e) {
/*
* In case of error, Java FileSystem implementation tries to throw a specific exception
* (NoSuchFileException or FileAlreadyExistsException), but this is not guaranteed.
*/
int isDirectory = 0;
final short errorKey;
if (e instanceof FileAlreadyExistsException) {
if (path != null && Files.isDirectory(path)) {
isDirectory = 1;
}
errorKey = Resources.Keys.FileAlreadyExists_2;
} else if (e instanceof NoSuchFileException) {
errorKey = Resources.Keys.NoSuchResourceDirectory_1;
} else {
errorKey = Resources.Keys.CanNotCreateFolderStore_1;
}
throw new DataStoreException(Resources.format(errorKey, (path != null) ? path : connector.getStorageName(), isDirectory), e);
}
return store;
}
use of org.apache.sis.storage.DataStore in project sis by apache.
the class Store method components.
/**
* Returns all resources found in the folder given at construction time.
* Only the resources recognized by a {@link DataStore} will be included.
* This includes sub-folders. Resources are in no particular order.
*/
@Override
@SuppressWarnings("ReturnOfCollectionOrArrayField")
public synchronized Collection<Resource> components() throws DataStoreException {
if (components == null) {
final List<DataStore> resources = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(location, this)) {
for (final Path candidate : stream) {
/*
* The candidate path may be a symbolic link to a file that we have previously read.
* In such case, use the existing data store. A use case is a directory containing
* hundred of GeoTIFF files all accompanied by ".prj" files having identical content.
* (Note: those ".prj" files should be invisible since they should be identified as
* GeoTIFF auxiliary files, but current Store implementation does not know that).
*/
final Path real = candidate.toRealPath();
DataStore next = children.get(real);
if (next instanceof Store) {
// Warn about directories only.
((Store) next).sharedRepository(real);
}
if (next == null) {
/*
* The candidate file has never been read before. Try to read it now.
* If the file format is unknown (UnsupportedStorageException), we will
* check if we can open it as a child folder store before to skip it.
*/
final StorageConnector connector = new StorageConnector(candidate);
connector.setOption(OptionKey.LOCALE, locale);
connector.setOption(OptionKey.TIMEZONE, timezone);
connector.setOption(OptionKey.ENCODING, encoding);
try {
if (componentProvider == null) {
// May throw UnsupportedStorageException.
next = DataStores.open(connector);
} else if (componentProvider.probeContent(connector).isSupported()) {
// Open a file of specified format.
next = componentProvider.open(connector);
} else if (Files.isDirectory(candidate)) {
// Open a sub-directory.
next = new Store(this, connector);
} else {
// Not the format specified at construction time.
connector.closeAllExcept(null);
continue;
}
} catch (UnsupportedStorageException ex) {
if (!Files.isDirectory(candidate)) {
connector.closeAllExcept(null);
listeners.warning(Level.FINE, null, ex);
continue;
}
next = new Store(this, connector);
} catch (DataStoreException ex) {
try {
connector.closeAllExcept(null);
} catch (DataStoreException s) {
ex.addSuppressed(s);
}
throw ex;
}
/*
* At this point we got the data store. It could happen that a store for
* the same file has been added concurrently, so we need to check again.
*/
final DataStore existing = children.putIfAbsent(real, next);
if (existing != null) {
next.close();
next = existing;
if (next instanceof Store) {
// Warn about directories only.
((Store) next).sharedRepository(real);
}
}
}
resources.add(next);
}
} catch (DirectoryIteratorException | UncheckedIOException ex) {
// The cause is an IOException (no other type allowed).
throw new DataStoreException(canNotRead(), ex.getCause());
} catch (IOException ex) {
throw new DataStoreException(canNotRead(), ex);
} catch (BackingStoreException ex) {
throw ex.unwrapOrRethrow(DataStoreException.class);
}
components = UnmodifiableArrayList.wrap(resources.toArray(new Resource[resources.size()]));
}
// Safe because unmodifiable list.
return components;
}
use of org.apache.sis.storage.DataStore in project sis by apache.
the class Store method close.
/**
* Closes all children resources.
*/
@Override
public synchronized void close() throws DataStoreException {
final Collection<Resource> resources = components;
if (resources != null) {
// Clear first in case of failure.
components = null;
DataStoreException failure = null;
for (final Resource r : resources) {
if (r instanceof DataStore)
try {
((DataStore) r).close();
} catch (DataStoreException ex) {
if (failure == null) {
failure = ex;
} else {
failure.addSuppressed(ex);
}
}
}
if (failure != null) {
throw failure;
}
}
}
use of org.apache.sis.storage.DataStore in project sis by apache.
the class WritableStore method remove.
/**
* Removes a {@code Resource} from this store. The resource must be a part of this {@code Aggregate}.
* For a folder store, this means that the resource must be a direct children of the directory managed
* by this store.
*
* This operation is destructive: the {@link Resource} and it's related files will be deleted.
*/
@Override
public synchronized void remove(final Resource resource) throws DataStoreException {
if (resource instanceof DataStore)
try {
if (resource instanceof Store) {
final Path path = ((Store) resource).location;
if (Files.isSameFile(path.getParent(), location)) {
((Store) resource).close();
deleteRecursively(path, true);
children.remove(path);
return;
}
} else if (resource instanceof ResourceOnFileSystem) {
final Path[] componentPaths = ((ResourceOnFileSystem) resource).getComponentFiles().clone();
for (Path root : componentPaths) {
root = root.getParent();
if (Files.isSameFile(root, location)) {
/*
* If we enter in this block, we have determined that at least one file is located in the
* directory managed by this store - NOT in a subdirectory since they could be managed by
* different folder stores. We assume that this root file is the "main" file. Other files
* could be in subdirectories, but we need to verify - we do not delete files outside.
*/
for (final Path path : componentPaths) {
if (path.startsWith(root)) {
Files.delete(path);
}
}
children.values().removeIf((e) -> e == resource);
// Clear cache. TODO: we should do something more efficient.
components = null;
return;
}
}
}
} catch (IOException e) {
throw new DataStoreException(messages().getString(Resources.Keys.CanNotRemoveResource_2, getDisplayName(), ((DataStore) resource).getDisplayName()), e);
}
throw new DataStoreException(messages().getString(Resources.Keys.NoSuchResourceInAggregate_2, getDisplayName(), StoreUtilities.getLabel(resource)));
}
use of org.apache.sis.storage.DataStore in project tika by apache.
the class GeographicInformationParser method parse.
@Override
public void parse(InputStream inputStream, ContentHandler contentHandler, Metadata metadata, ParseContext parseContext) throws IOException, SAXException, TikaException {
metadata.set(Metadata.CONTENT_TYPE, geoInfoType);
DataStore dataStore = null;
DefaultMetadata defaultMetadata = null;
XHTMLContentHandler xhtmlContentHandler = new XHTMLContentHandler(contentHandler, metadata);
TemporaryResources tmp = TikaInputStream.isTikaInputStream(inputStream) ? null : new TemporaryResources();
try {
TikaInputStream tikaInputStream = TikaInputStream.get(inputStream, tmp);
File file = tikaInputStream.getFile();
dataStore = DataStores.open(file);
defaultMetadata = new DefaultMetadata(dataStore.getMetadata());
if (defaultMetadata != null)
extract(xhtmlContentHandler, metadata, defaultMetadata);
} catch (UnsupportedStorageException e) {
throw new TikaException("UnsupportedStorageException", e);
} catch (DataStoreException e) {
throw new TikaException("DataStoreException", e);
} finally {
if (tmp != null) {
tmp.dispose();
}
}
}
Aggregations