You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2013/06/04 23:26:01 UTC
svn commit: r1489620 -
/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
Author: desruisseaux
Date: Tue Jun 4 21:25:50 2013
New Revision: 1489620
URL: http://svn.apache.org/r1489620
Log:
First draft of NetcdfStoreProvider. Not yet completed: missing public API and test cases.
Added:
sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java (with props)
Added: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java?rev=1489620&view=auto
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java (added)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java [UTF-8] Tue Jun 4 21:25:50 2013
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.netcdf;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
+import org.apache.sis.internal.netcdf.Decoder;
+import org.apache.sis.internal.netcdf.impl.ChannelDecoder;
+import org.apache.sis.internal.netcdf.ucar.DecoderWrapper;
+import org.apache.sis.internal.storage.ChannelDataInput;
+import org.apache.sis.internal.storage.WarningProducer;
+import org.apache.sis.storage.DataStoreConnection;
+import org.apache.sis.storage.DataStoreException;
+
+
+/**
+ * The provider of {@link NetcdfStore} instances. Given an {@link DataStoreConnection} input,
+ * this class tries to instantiate a {@code NetcdfStore} using the embedded NetCDF decoder.
+ * If the embedded decoder can not decode the given input and the UCAR library is reachable
+ * on the classpath, then this class tries to instantiate a {@code NetcdfStore} backed by
+ * the UCAR library.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @since 0.3
+ * @version 0.3
+ * @module
+ */
+public class NetcdfStoreProvider {
+ /**
+ * The {@link ucar.nc2.NetcdfFile} class, or {@code null} if not found. An attempt to load this class
+ * will be performed when first needed since the UCAR library is optional. If not found, then this field
+ * will be assigned the {@link Void#TYPE} sentinel value, meaning "No UCAR library on the classpath".
+ */
+ private static Class<?> netcdfFileClass;
+
+ /**
+ * If the {@link #netcdfFileClass} has been found, then the {@link DecoderWrapper} constructor receiving
+ * in argument a UCAR {@code NetcdfFile} object. Otherwise {@code null}.
+ */
+ private static volatile Constructor<? extends Decoder> fromUCAR;
+
+ /**
+ * If the {@link #netcdfFileClass} has been found, then the {@link DecoderWrapper} constructor receiving
+ * in argument the name of the NetCDF file as a {@link String} object. Otherwise {@code null}.
+ */
+ private static volatile Constructor<? extends Decoder> fromFilename;
+
+ /**
+ * Creates a new provider.
+ */
+ public NetcdfStoreProvider() {
+ }
+
+ /**
+ * Creates a decoder for the given input.
+ *
+ * @param sink Where to send the warnings, or {@code null} if none.
+ * @param connection Information about the input (file, input stream, <i>etc.</i>)
+ * @return The decoder for the given input.
+ * @throws IOException If an error occurred while opening the NetCDF file.
+ * @throws DataStoreException If a logical error (other than I/O) occurred.
+ */
+ static Decoder decoder(final WarningProducer sink, final DataStoreConnection connection)
+ throws IOException, DataStoreException
+ {
+ final ChannelDataInput input = connection.getStorageAs(ChannelDataInput.class);
+ if (input != null) try {
+ return new ChannelDecoder(sink, input);
+ } catch (DataStoreException e) {
+ final String path = connection.getStorageAs(String.class);
+ if (path != null) try {
+ return createByReflection(sink, path, false);
+ } catch (IOException | DataStoreException s) {
+ e.addSuppressed(s);
+ }
+ throw e;
+ }
+ return createByReflection(sink, connection, true);
+ }
+
+ /**
+ * Creates a new NetCDF decoder as a wrapper around the UCAR library. This decoder is used only when we can
+ * not create our embedded NetCDF decoder. This method uses reflection for creating the wrapper, in order
+ * to keep the UCAR dependency optional.
+ *
+ * @param sink Where to send the warnings, or {@code null} if none.
+ * @param input The NetCDF file object of filename string from which to read data.
+ * @param isUCAR {@code true} if {@code input} is an instance of the UCAR {@link ucar.nc2.NetcdfFile} object,
+ * or {@code false} if it is the filename as a {@code String}.
+ * @return The {@link DecoderWrapper} instance for the given input.
+ * @throws IOException If an error occurred while opening the NetCDF file.
+ * @throws DataStoreException If a logical error (other than I/O) occurred.
+ */
+ private static Decoder createByReflection(final WarningProducer sink, final Object input, final boolean isUCAR)
+ throws IOException, DataStoreException
+ {
+ /*
+ * Get the java.lang.Class that represent the ucar.nc2.NetcdfFile type. We do not synchronize since it
+ * is not a big deal if Class.forName(…) is invoked twice. The Class.forName(…) method performs itself
+ * the required synchronization for returning the same singleton Class instance.
+ */
+ if (netcdfFileClass == null) {
+ try {
+ netcdfFileClass = Class.forName("ucar.nc2.NetcdfFile");
+ } catch (ClassNotFoundException e) {
+ netcdfFileClass = Void.TYPE;
+ return null;
+ }
+ try {
+ final Class<? extends Decoder> wrapper =
+ Class.forName("org.apache.sis.internal.netcdf.ucar.DecoderWrapper").asSubclass(Decoder.class);
+ final Class<?>[] parameterTypes = new Class<?>[] {WarningProducer.class, netcdfFileClass};
+ fromUCAR = wrapper.getConstructor(parameterTypes);
+ parameterTypes[1] = String.class;
+ fromFilename = wrapper.getConstructor(parameterTypes);
+ } catch (ReflectiveOperationException e) {
+ throw new AssertionError(e); // Should never happen (shall be verified by the JUnit tests).
+ }
+ }
+ /*
+ * Get the appropriate constructor for the isUCAR argument. This constructor will be null
+ * if the above code failed to load the UCAR library. Otherwise, instantiate the wrapper.
+ */
+ final Constructor<? extends Decoder> constructor;
+ final Class<?> expectedType;
+ if (isUCAR) {
+ constructor = fromUCAR;
+ expectedType = netcdfFileClass;
+ } else {
+ constructor = fromFilename;
+ expectedType = String.class;
+ }
+ if (constructor == null || !expectedType.isInstance(input)) {
+ return null;
+ }
+ try {
+ return constructor.newInstance(sink, input);
+ } catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof IOException) throw (IOException) cause;
+ if (cause instanceof DataStoreException) throw (DataStoreException) cause;
+ if (cause instanceof RuntimeException) throw (RuntimeException) cause;
+ if (cause instanceof Error) throw (Error) cause;
+ throw new UndeclaredThrowableException(cause); // Should never happen actually.
+ } catch (ReflectiveOperationException e) {
+ throw new AssertionError(e); // Should never happen (shall be verified by the JUnit tests).
+ }
+ }
+}
Propchange: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
------------------------------------------------------------------------------
svn:mime-type = text/plain;charset=UTF-8