METAMODEL-1099: Added ServiceLoader based registry of DataContexts. Fixes #113
Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/52c3dafc Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/52c3dafc Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/52c3dafc Branch: refs/heads/feature/5.x/swagger-docs Commit: 52c3dafcf0f1ca6256f8da82c9825c121f833a80 Parents: b4bfc5c Author: Kasper Sørensen <[email protected]> Authored: Sun Jul 10 21:18:34 2016 -0700 Committer: Kasper Sørensen <[email protected]> Committed: Sun Jul 10 21:18:34 2016 -0700 ---------------------------------------------------------------------- CHANGES.md | 1 + .../apache/metamodel/ConnectionException.java | 44 +++ .../factory/ClasspathResourceFactory.java | 36 +++ .../metamodel/factory/DataContextFactory.java | 30 ++ .../factory/DataContextFactoryRegistry.java | 41 +++ .../factory/DataContextFactoryRegistryImpl.java | 84 +++++ .../factory/DataContextProperties.java | 92 ++++++ .../factory/DataContextPropertiesImpl.java | 304 +++++++++++++++++++ .../metamodel/factory/FileResourceFactory.java | 38 +++ .../factory/InMemoryResourceFactory.java | 36 +++ .../metamodel/factory/ResourceFactory.java | 28 ++ .../factory/ResourceFactoryRegistry.java | 34 +++ .../factory/ResourceFactoryRegistryImpl.java | 80 +++++ .../metamodel/factory/ResourceProperties.java | 46 +++ .../factory/ResourcePropertiesImpl.java | 74 +++++ .../factory/SimpleResourceProperties.java | 60 ++++ ...supportedDataContextPropertiesException.java | 47 +++ .../UnsupportedResourcePropertiesException.java | 43 +++ .../metamodel/factory/UrlResourceFactory.java | 48 +++ .../apache/metamodel/util/ResourceUtils.java | 45 +++ ...org.apache.metamodel.factory.ResourceFactory | 4 + .../ResourceFactoryRegistryImplTest.java | 72 +++++ .../apache/metamodel/util/UrlResourceTest.java | 8 +- .../metamodel/csv/CsvDataContextFactory.java | 73 +++++ ....apache.metamodel.factory.DataContextFactory | 1 + .../csv/CsvDataContextFactoryTest.java | 57 ++++ .../metamodel/hadoop/HdfsResourceFactory.java | 46 +++ ...org.apache.metamodel.factory.ResourceFactory | 1 + .../metamodel/jdbc/JdbcDataContextFactory.java | 86 ++++++ ....apache.metamodel.factory.DataContextFactory | 1 + .../apache/metamodel/jdbc/H2databaseTest.java | 11 +- .../jdbc/JdbcDataContextFactoryTest.java | 45 +++ pom.xml | 1 + 33 files changed, 1609 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/CHANGES.md ---------------------------------------------------------------------- diff --git a/CHANGES.md b/CHANGES.md index 817893a..3ff4ca0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,6 @@ ### Apache MetaModel 4.5.4 (work in progress) + * [METAMODEL-1099] - Created a new DataContextFactory SPI and a extensible registry of implementations based on ServiceLoader. * [METAMODEL-1088] - Add support for aliases in MongoDB. * [METAMODEL-1086] - Fixed encoding issue when CsvDataContext is instantiated with InputStream. * [METAMODEL-1094] - Added support for Apache Cassandra version 3.x. http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/ConnectionException.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/ConnectionException.java b/core/src/main/java/org/apache/metamodel/ConnectionException.java new file mode 100644 index 0000000..5379f09 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/ConnectionException.java @@ -0,0 +1,44 @@ +/** + * 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.metamodel; + +/** + * Specialized {@link MetaModelException} thrown to indicate that establishing + * the connection to the underlying data store of an {@link DataContext} failed. + */ +public class ConnectionException extends MetaModelException { + + private static final long serialVersionUID = 1L; + + public ConnectionException() { + super(); + } + + public ConnectionException(Exception cause) { + super(cause); + } + + public ConnectionException(String message, Exception cause) { + super(message, cause); + } + + public ConnectionException(String message) { + super(message); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/ClasspathResourceFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/ClasspathResourceFactory.java b/core/src/main/java/org/apache/metamodel/factory/ClasspathResourceFactory.java new file mode 100644 index 0000000..526e5f3 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/ClasspathResourceFactory.java @@ -0,0 +1,36 @@ +/** + * 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.metamodel.factory; + +import org.apache.metamodel.util.ClasspathResource; +import org.apache.metamodel.util.Resource; + +public class ClasspathResourceFactory implements ResourceFactory { + + @Override + public boolean accepts(ResourceProperties properties) { + return "classpath".equals(properties.getUri().getScheme()); + } + + @Override + public Resource create(ResourceProperties properties) throws UnsupportedResourcePropertiesException { + assert accepts(properties); + return new ClasspathResource(properties.getUri().getPath()); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/DataContextFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/DataContextFactory.java b/core/src/main/java/org/apache/metamodel/factory/DataContextFactory.java new file mode 100644 index 0000000..b9f8e3e --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/DataContextFactory.java @@ -0,0 +1,30 @@ +/** + * 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.metamodel.factory; + +import org.apache.metamodel.ConnectionException; +import org.apache.metamodel.DataContext; + +public interface DataContextFactory { + + public boolean accepts(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry); + + public DataContext create(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) + throws UnsupportedDataContextPropertiesException, ConnectionException; +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/DataContextFactoryRegistry.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/DataContextFactoryRegistry.java b/core/src/main/java/org/apache/metamodel/factory/DataContextFactoryRegistry.java new file mode 100644 index 0000000..79af1ab --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/DataContextFactoryRegistry.java @@ -0,0 +1,41 @@ +/** + * 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.metamodel.factory; + +import java.util.Collection; + +import org.apache.metamodel.ConnectionException; +import org.apache.metamodel.DataContext; + +/** + * Represents a registry of {@link DataContextFactory} objects. This registry + * can be used to create {@link DataContext}s of varying types using the + * underlying factories. + */ +public interface DataContextFactoryRegistry { + + public void addFactory(DataContextFactory factory); + + public void clearFactories(); + + public Collection<DataContextFactory> getFactories(); + + public DataContext createDataContext(DataContextProperties properties) + throws UnsupportedDataContextPropertiesException, ConnectionException; +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/DataContextFactoryRegistryImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/DataContextFactoryRegistryImpl.java b/core/src/main/java/org/apache/metamodel/factory/DataContextFactoryRegistryImpl.java new file mode 100644 index 0000000..0dfb897 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/DataContextFactoryRegistryImpl.java @@ -0,0 +1,84 @@ +/** + * 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.metamodel.factory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; + +import org.apache.metamodel.DataContext; + +public class DataContextFactoryRegistryImpl implements DataContextFactoryRegistry { + + private static final DataContextFactoryRegistry DEFAULT_INSTANCE; + + static { + final ResourceFactoryRegistry resourceFactoryRegistry = ResourceFactoryRegistryImpl.getDefaultInstance(); + final DataContextFactoryRegistryImpl registry = new DataContextFactoryRegistryImpl(resourceFactoryRegistry); + registry.discoverFromClasspath(); + DEFAULT_INSTANCE = registry; + } + + public static DataContextFactoryRegistry getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private final List<DataContextFactory> factories; + private final ResourceFactoryRegistry resourceFactoryRegistry; + + public DataContextFactoryRegistryImpl(ResourceFactoryRegistry resourceFactoryRegistry) { + this.factories = new ArrayList<>(); + this.resourceFactoryRegistry = resourceFactoryRegistry; + } + + @Override + public void addFactory(DataContextFactory factory) { + factories.add(factory); + } + + @Override + public void clearFactories() { + factories.clear(); + } + + @Override + public Collection<DataContextFactory> getFactories() { + return Collections.unmodifiableList(factories); + } + + @Override + public DataContext createDataContext(DataContextProperties properties) + throws UnsupportedDataContextPropertiesException { + for (DataContextFactory factory : factories) { + if (factory.accepts(properties, resourceFactoryRegistry)) { + return factory.create(properties, resourceFactoryRegistry); + } + } + throw new UnsupportedDataContextPropertiesException(); + } + + public void discoverFromClasspath() { + final ServiceLoader<DataContextFactory> serviceLoader = ServiceLoader.load(DataContextFactory.class); + for (DataContextFactory factory : serviceLoader) { + addFactory(factory); + } + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/DataContextProperties.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/DataContextProperties.java b/core/src/main/java/org/apache/metamodel/factory/DataContextProperties.java new file mode 100644 index 0000000..5251726 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/DataContextProperties.java @@ -0,0 +1,92 @@ +/** + * 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.metamodel.factory; + +import java.io.Serializable; +import java.util.Map; + +import javax.sql.DataSource; + +import org.apache.metamodel.DataContext; +import org.apache.metamodel.schema.TableType; +import org.apache.metamodel.util.SimpleTableDef; + +/** + * Represents the {@link Serializable} properties used to fully describe and + * construct a {@link DataContext}. + */ +public interface DataContextProperties extends Serializable { + + /** + * Gets the type of {@link DataContext}, such as "csv" or "jdbc". + * + * @return + */ + String getDataContextType(); + + /** + * Gets all the properties represented as a {@link Map}. Note that any + * unstandardized properties may also be exposed via this map. + * + * @return + */ + Map<String, Object> toMap(); + + ResourceProperties getResourceProperties(); + + Integer getColumnNameLineNumber(); + + Boolean isSkipEmptyLines(); + + Boolean isSkipEmptyColumns(); + + String getEncoding(); + + Character getSeparatorChar(); + + Character getQuoteChar(); + + Character getEscapeChar(); + + Boolean isFailOnInconsistentRowLength(); + + Boolean isMultilineValuesEnabled(); + + TableType[] getTableTypes(); + + String getCatalogName(); + + String getUrl(); + + DataSource getDataSource(); + + String getUsername(); + + String getPassword(); + + String getDriverClassName(); + + String getHostname(); + + Integer getPort(); + + String getDatabaseName(); + + SimpleTableDef[] getTableDefs(); +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/DataContextPropertiesImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/DataContextPropertiesImpl.java b/core/src/main/java/org/apache/metamodel/factory/DataContextPropertiesImpl.java new file mode 100644 index 0000000..e66a811 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/DataContextPropertiesImpl.java @@ -0,0 +1,304 @@ +/** + * 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.metamodel.factory; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import javax.sql.DataSource; + +import org.apache.metamodel.schema.TableType; +import org.apache.metamodel.util.BooleanComparator; +import org.apache.metamodel.util.NumberComparator; +import org.apache.metamodel.util.SimpleTableDef; +import org.apache.metamodel.util.SimpleTableDefParser; + +public class DataContextPropertiesImpl implements DataContextProperties { + + private static final long serialVersionUID = 1L; + + public static final String PROPERTY_USERNAME = "username"; + public static final String PROPERTY_PASSWORD = "password"; + public static final String PROPERTY_DRIVER_CLASS = "driver-class"; + public static final String PROPERTY_HOSTNAME = "hostname"; + public static final String PROPERTY_PORT = "port"; + public static final String PROPERTY_DATABASE = "database"; + public static final String PROPERTY_URL = "url"; + public static final String PROPERTY_CATALOG_NAME = "catalog"; + public static final String PROPERTY_RESOURCE_PROPERTIES = "resource"; + public static final String PROPERTY_IS_MULTILINE_VALUES_ENABLED = "multiline-values"; + public static final String PROPERTY_IS_FAIL_ON_INCONSISTENT_ROW_LENGTH = "fail-on-inconsistent-row-length"; + public static final String PROPERTY_ESCAPE_CHAR = "escape-char"; + public static final String PROPERTY_QUOTE_CHAR = "quote-char"; + public static final String PROPERTY_SEPARATOR_CHAR = "separator-char"; + public static final String PROPERTY_ENCODING = "encoding"; + public static final String PROPERTY_SKIP_EMPTY_COLUMNS = "skip-empty-columns"; + public static final String PROPERTY_SKIP_EMPTY_LINES = "skip-empty-lines"; + public static final String PROPERTY_COLUMN_NAME_LINE_NUMBER = "column-name-line-number"; + public static final String PROPERTY_DATA_CONTEXT_TYPE = "type"; + public static final String PROPERTY_TABLE_TYPES = "table-types"; + public static final String PROPERTY_DATA_SOURCE = "data-source"; + public static final String PROPERTY_TABLE_DEFS = "table-defs"; + + private final Map<String, Object> map; + + public DataContextPropertiesImpl() { + this(new HashMap<String, Object>()); + } + + public DataContextPropertiesImpl(Properties properties) { + this(); + final Set<String> propertyNames = properties.stringPropertyNames(); + for (String key : propertyNames) { + put(key, properties.get(key)); + } + } + + public DataContextPropertiesImpl(Map<String, Object> map) { + this.map = map; + } + + public Object get(String key) { + return map.get(key); + } + + public Object put(String key, Object value) { + return map.put(key, value); + } + + public String getString(String key) { + final Object value = map.get(key); + if (value == null) { + return null; + } + return value.toString(); + } + + public Character getChar(String key) { + final String str = getString(key); + if (str == null || str.isEmpty()) { + return null; + } + return str.charAt(0); + } + + public Integer getInt(String key) { + final Object obj = get(key); + if (obj == null) { + return null; + } + return NumberComparator.toNumber(obj).intValue(); + } + + private Boolean getBoolean(String key) { + final Object obj = get(key); + if (obj == null) { + return null; + } + return BooleanComparator.toBoolean(obj); + } + + @SuppressWarnings("unchecked") + public Map<String, Object> getMap(String key) { + final Object obj = get(key); + if (obj == null) { + return null; + } + if (obj instanceof Map) { + return (Map<String, Object>) obj; + } + if (obj instanceof String) { + // TODO: Try parse as JSON + } + throw new IllegalStateException("Expected Map value for property '" + key + "'. Found " + obj.getClass() + .getName()); + } + + @Override + public String getDataContextType() { + return getString(PROPERTY_DATA_CONTEXT_TYPE); + } + + public void setDataContextType(String type) { + put(PROPERTY_DATA_CONTEXT_TYPE, type); + } + + @Override + public Map<String, Object> toMap() { + return map; + } + + @Override + public ResourceProperties getResourceProperties() { + final Object resourceValue = get(PROPERTY_RESOURCE_PROPERTIES); + if (resourceValue == null) { + return null; + } + if (resourceValue instanceof String) { + return new SimpleResourceProperties((String) resourceValue); + } + if (resourceValue instanceof URI) { + return new SimpleResourceProperties((URI) resourceValue); + } + if (resourceValue instanceof Map) { + @SuppressWarnings("unchecked") + final Map<String, Object> resourceMap = (Map<String, Object>) resourceValue; + return new ResourcePropertiesImpl(resourceMap); + } + throw new IllegalStateException("Expected String, URI or Map value for property 'resource'. Found: " + + resourceValue); + } + + @Override + public Integer getColumnNameLineNumber() { + return getInt(PROPERTY_COLUMN_NAME_LINE_NUMBER); + } + + @Override + public Boolean isSkipEmptyLines() { + return getBoolean(PROPERTY_SKIP_EMPTY_LINES); + } + + @Override + public Boolean isSkipEmptyColumns() { + return getBoolean(PROPERTY_SKIP_EMPTY_COLUMNS); + } + + @Override + public String getEncoding() { + return getString(PROPERTY_ENCODING); + } + + @Override + public Character getSeparatorChar() { + return getChar(PROPERTY_SEPARATOR_CHAR); + } + + @Override + public Character getQuoteChar() { + return getChar(PROPERTY_QUOTE_CHAR); + } + + @Override + public Character getEscapeChar() { + return getChar(PROPERTY_ESCAPE_CHAR); + } + + @Override + public Boolean isFailOnInconsistentRowLength() { + return getBoolean(PROPERTY_IS_FAIL_ON_INCONSISTENT_ROW_LENGTH); + } + + @Override + public Boolean isMultilineValuesEnabled() { + return getBoolean(PROPERTY_IS_MULTILINE_VALUES_ENABLED); + } + + @Override + public TableType[] getTableTypes() { + final Object obj = get(PROPERTY_TABLE_TYPES); + if (obj == null) { + return null; + } + if (obj instanceof TableType[]) { + return (TableType[]) obj; + } + if (obj instanceof TableType) { + return new TableType[] { (TableType) obj }; + } + if (obj instanceof String) { + String str = (String) obj; + if (str.startsWith("[") && str.endsWith("]")) { + str = str.substring(1, str.length() - 2); + } + final String[] tokens = str.split(","); + final TableType[] tableTypes = new TableType[tokens.length]; + for (int i = 0; i < tableTypes.length; i++) { + tableTypes[i] = TableType.getTableType(tokens[i]); + } + } + throw new IllegalStateException("Expected TableType[] value for property '" + PROPERTY_TABLE_TYPES + "'. Found " + + obj.getClass().getName()); + } + + @Override + public String getCatalogName() { + return getString(PROPERTY_CATALOG_NAME); + } + + @Override + public String getUrl() { + return getString(PROPERTY_URL); + } + + @Override + public DataSource getDataSource() { + return (DataSource) get(PROPERTY_DATA_SOURCE); + } + + @Override + public String getUsername() { + return getString(PROPERTY_USERNAME); + } + + @Override + public String getPassword() { + return getString(PROPERTY_PASSWORD); + } + + @Override + public String getDriverClassName() { + return getString(PROPERTY_DRIVER_CLASS); + } + + @Override + public String getHostname() { + return getString(PROPERTY_HOSTNAME); + } + + @Override + public Integer getPort() { + return getInt(PROPERTY_PORT); + } + + @Override + public String getDatabaseName() { + return getString(PROPERTY_DATABASE); + } + + @Override + public SimpleTableDef[] getTableDefs() { + final Object obj = get(PROPERTY_TABLE_DEFS); + if (obj instanceof SimpleTableDef[]) { + return (SimpleTableDef[]) obj; + } + if (obj instanceof SimpleTableDef) { + return new SimpleTableDef[] { (SimpleTableDef) obj }; + } + if (obj instanceof String) { + return SimpleTableDefParser.parseTableDefs((String) obj); + } + throw new IllegalStateException("Expected SimpleTableDef[] value for property '" + PROPERTY_TABLE_DEFS + + "'. Found " + obj.getClass().getName()); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/FileResourceFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/FileResourceFactory.java b/core/src/main/java/org/apache/metamodel/factory/FileResourceFactory.java new file mode 100644 index 0000000..8da1815 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/FileResourceFactory.java @@ -0,0 +1,38 @@ +/** + * 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.metamodel.factory; + +import org.apache.metamodel.util.FileResource; +import org.apache.metamodel.util.Resource; + +public class FileResourceFactory implements ResourceFactory { + + @Override + public boolean accepts(ResourceProperties properties) { + final String scheme = properties.getUri().getScheme(); + return scheme == null || "file".equals(scheme); + } + + @Override + public Resource create(ResourceProperties properties) throws UnsupportedResourcePropertiesException { + assert accepts(properties); + final String path = properties.getUri().getPath(); + return new FileResource(path); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/InMemoryResourceFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/InMemoryResourceFactory.java b/core/src/main/java/org/apache/metamodel/factory/InMemoryResourceFactory.java new file mode 100644 index 0000000..8726441 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/InMemoryResourceFactory.java @@ -0,0 +1,36 @@ +/** + * 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.metamodel.factory; + +import org.apache.metamodel.util.InMemoryResource; +import org.apache.metamodel.util.Resource; + +public class InMemoryResourceFactory implements ResourceFactory { + + @Override + public boolean accepts(ResourceProperties properties) { + return "mem".equals(properties.getUri().getScheme()); + } + + @Override + public Resource create(ResourceProperties properties) throws UnsupportedResourcePropertiesException { + assert accepts(properties); + return new InMemoryResource(properties.getUri().getPath()); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/ResourceFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/ResourceFactory.java b/core/src/main/java/org/apache/metamodel/factory/ResourceFactory.java new file mode 100644 index 0000000..f128596 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/ResourceFactory.java @@ -0,0 +1,28 @@ +/** + * 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.metamodel.factory; + +import org.apache.metamodel.util.Resource; + +public interface ResourceFactory { + + public boolean accepts(ResourceProperties properties); + + public Resource create(ResourceProperties properties) throws UnsupportedResourcePropertiesException; +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/ResourceFactoryRegistry.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/ResourceFactoryRegistry.java b/core/src/main/java/org/apache/metamodel/factory/ResourceFactoryRegistry.java new file mode 100644 index 0000000..2815787 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/ResourceFactoryRegistry.java @@ -0,0 +1,34 @@ +/** + * 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.metamodel.factory; + +import java.util.Collection; + +import org.apache.metamodel.util.Resource; + +public interface ResourceFactoryRegistry { + + public void addFactory(ResourceFactory factory); + + public void clearFactories(); + + public Collection<ResourceFactory> getFactories(); + + public Resource createResource(ResourceProperties properties) throws UnsupportedResourcePropertiesException; +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/ResourceFactoryRegistryImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/ResourceFactoryRegistryImpl.java b/core/src/main/java/org/apache/metamodel/factory/ResourceFactoryRegistryImpl.java new file mode 100644 index 0000000..b8fae41 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/ResourceFactoryRegistryImpl.java @@ -0,0 +1,80 @@ +/** + * 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.metamodel.factory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; + +import org.apache.metamodel.util.Resource; + +public class ResourceFactoryRegistryImpl implements ResourceFactoryRegistry { + + private static final ResourceFactoryRegistry DEFAULT_INSTANCE; + + static { + final ResourceFactoryRegistryImpl registry = new ResourceFactoryRegistryImpl(); + registry.discoverFromClasspath(); + DEFAULT_INSTANCE = registry; + } + + public static ResourceFactoryRegistry getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private final List<ResourceFactory> factories; + + public ResourceFactoryRegistryImpl() { + factories = new ArrayList<>(); + } + + @Override + public void addFactory(ResourceFactory factory) { + factories.add(factory); + } + + @Override + public void clearFactories() { + factories.clear(); + } + + @Override + public Collection<ResourceFactory> getFactories() { + return Collections.unmodifiableList(factories); + } + + @Override + public Resource createResource(ResourceProperties properties) { + for (ResourceFactory factory : factories) { + if (factory.accepts(properties)) { + return factory.create(properties); + } + } + throw new UnsupportedResourcePropertiesException(); + } + + public void discoverFromClasspath() { + final ServiceLoader<ResourceFactory> serviceLoader = ServiceLoader.load(ResourceFactory.class); + for (ResourceFactory factory : serviceLoader) { + addFactory(factory); + } + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/ResourceProperties.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/ResourceProperties.java b/core/src/main/java/org/apache/metamodel/factory/ResourceProperties.java new file mode 100644 index 0000000..ab56036 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/ResourceProperties.java @@ -0,0 +1,46 @@ +/** + * 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.metamodel.factory; + +import java.io.Serializable; +import java.net.URI; +import java.util.Map; + +import org.apache.metamodel.util.Resource; + +/** + * Represents the {@link Serializable} properties used to fully describe and + * construct a {@link Resource}. + */ +public interface ResourceProperties extends Serializable { + + URI getUri(); + + /** + * Gets all the properties represented as a {@link Map}. Note that any + * unstandardized properties may also be exposed via this map. + * + * @return + */ + Map<String, Object> toMap(); + + String getUsername(); + + String getPassword(); +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/ResourcePropertiesImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/ResourcePropertiesImpl.java b/core/src/main/java/org/apache/metamodel/factory/ResourcePropertiesImpl.java new file mode 100644 index 0000000..c27bd4f --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/ResourcePropertiesImpl.java @@ -0,0 +1,74 @@ +/** + * 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.metamodel.factory; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +public class ResourcePropertiesImpl implements ResourceProperties { + + private static final long serialVersionUID = 1L; + + private final Map<String, Object> map; + + public ResourcePropertiesImpl() { + this(new HashMap<String, Object>()); + } + + public ResourcePropertiesImpl(Map<String, Object> map) { + this.map = map; + } + + private String getString(String key) { + final Object value = map.get(key); + if (value == null) { + return null; + } + return value.toString(); + } + + @Override + public URI getUri() { + final Object uri = map.get("uri"); + if (uri == null) { + return null; + } + if (uri instanceof URI) { + return (URI) uri; + } + return URI.create(uri.toString()); + } + + @Override + public Map<String, Object> toMap() { + return map; + } + + @Override + public String getUsername() { + return getString("username"); + } + + @Override + public String getPassword() { + return getString("password"); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/SimpleResourceProperties.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/SimpleResourceProperties.java b/core/src/main/java/org/apache/metamodel/factory/SimpleResourceProperties.java new file mode 100644 index 0000000..7298454 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/SimpleResourceProperties.java @@ -0,0 +1,60 @@ +/** + * 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.metamodel.factory; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +public class SimpleResourceProperties implements ResourceProperties { + + private static final long serialVersionUID = 1L; + private final URI uri; + + public SimpleResourceProperties(URI uri) { + this.uri = uri; + } + + public SimpleResourceProperties(String uri) { + this.uri = URI.create(uri); + } + + @Override + public URI getUri() { + return uri; + } + + @Override + public Map<String, Object> toMap() { + final Map<String, Object> map = new HashMap<>(); + map.put("uri", uri); + return map; + } + + @Override + public String getUsername() { + return null; + } + + @Override + public String getPassword() { + return null; + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/UnsupportedDataContextPropertiesException.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/UnsupportedDataContextPropertiesException.java b/core/src/main/java/org/apache/metamodel/factory/UnsupportedDataContextPropertiesException.java new file mode 100644 index 0000000..225fa72 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/UnsupportedDataContextPropertiesException.java @@ -0,0 +1,47 @@ +/** + * 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.metamodel.factory; + +import org.apache.metamodel.MetaModelException; + +/** + * Exception thrown if a {@link DataContextFactory} or + * {@link DataContextFactoryRegistry} is being invoked with + * {@link DataContextProperties} that are not supported by the implementation. + */ +public class UnsupportedDataContextPropertiesException extends MetaModelException { + + private static final long serialVersionUID = 1L; + + public UnsupportedDataContextPropertiesException() { + super(); + } + + public UnsupportedDataContextPropertiesException(Exception cause) { + super(cause); + } + + public UnsupportedDataContextPropertiesException(String message, Exception cause) { + super(message, cause); + } + + public UnsupportedDataContextPropertiesException(String message) { + super(message); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/UnsupportedResourcePropertiesException.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/UnsupportedResourcePropertiesException.java b/core/src/main/java/org/apache/metamodel/factory/UnsupportedResourcePropertiesException.java new file mode 100644 index 0000000..abf51bb --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/UnsupportedResourcePropertiesException.java @@ -0,0 +1,43 @@ +/** + * 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.metamodel.factory; + +import org.apache.metamodel.MetaModelException; + +public class UnsupportedResourcePropertiesException extends MetaModelException { + + private static final long serialVersionUID = 1L; + + public UnsupportedResourcePropertiesException() { + super(); + } + + public UnsupportedResourcePropertiesException(Exception cause) { + super(cause); + } + + public UnsupportedResourcePropertiesException(String message, Exception cause) { + super(message, cause); + } + + public UnsupportedResourcePropertiesException(String message) { + super(message); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/factory/UrlResourceFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/factory/UrlResourceFactory.java b/core/src/main/java/org/apache/metamodel/factory/UrlResourceFactory.java new file mode 100644 index 0000000..fbca8f1 --- /dev/null +++ b/core/src/main/java/org/apache/metamodel/factory/UrlResourceFactory.java @@ -0,0 +1,48 @@ +/** + * 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.metamodel.factory; + +import java.net.MalformedURLException; +import java.net.URI; + +import org.apache.metamodel.util.Resource; +import org.apache.metamodel.util.UrlResource; + +public class UrlResourceFactory implements ResourceFactory { + + @Override + public boolean accepts(ResourceProperties properties) { + final URI uri = properties.getUri(); + switch (uri.getScheme()) { + case "http": + case "https": + return true; + } + return false; + } + + @Override + public Resource create(ResourceProperties properties) throws UnsupportedResourcePropertiesException { + try { + return new UrlResource(properties.getUri().toURL()); + } catch (MalformedURLException e) { + throw new UnsupportedResourcePropertiesException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/java/org/apache/metamodel/util/ResourceUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/metamodel/util/ResourceUtils.java b/core/src/main/java/org/apache/metamodel/util/ResourceUtils.java index ad3426a..9e2faea 100644 --- a/core/src/main/java/org/apache/metamodel/util/ResourceUtils.java +++ b/core/src/main/java/org/apache/metamodel/util/ResourceUtils.java @@ -18,12 +18,57 @@ */ package org.apache.metamodel.util; +import java.net.URI; + +import org.apache.metamodel.factory.ResourceFactoryRegistryImpl; +import org.apache.metamodel.factory.ResourceProperties; +import org.apache.metamodel.factory.SimpleResourceProperties; +import org.apache.metamodel.factory.UnsupportedResourcePropertiesException; + /** * Static utility methods for handling {@link Resource}s. */ public class ResourceUtils { /** + * Creates a Resource based on a URI + * + * @param uri + * @return + * @throws UnsupportedResourcePropertiesException + * if the scheme or other part of the URI is unsupported. + */ + public static Resource toResource(URI uri) throws UnsupportedResourcePropertiesException { + return toResource(new SimpleResourceProperties(uri)); + } + + /** + * Creates a Resource based on a path or URI (represented by a String) + * + * @param uri + * @return + * @throws UnsupportedResourcePropertiesException + * if the scheme or other part of the string is unsupported. + */ + public static Resource toResource(String uri) throws UnsupportedResourcePropertiesException { + return toResource(new SimpleResourceProperties(uri)); + } + + /** + * Creates a Resource based on the {@link ResourceProperties} definition. + * + * @param resourceProperties + * @return + * @throws UnsupportedResourcePropertiesException + * if the provided properties cannot be handled in creation of a + * resource. + */ + public static Resource toResource(ResourceProperties resourceProperties) + throws UnsupportedResourcePropertiesException { + return ResourceFactoryRegistryImpl.getDefaultInstance().createResource(resourceProperties); + } + + /** * Gets the parent name of a resource. For example, if the resource's * qualified path is /foo/bar/baz, this method will return "bar". * http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/main/resources/META-INF/services/org.apache.metamodel.factory.ResourceFactory ---------------------------------------------------------------------- diff --git a/core/src/main/resources/META-INF/services/org.apache.metamodel.factory.ResourceFactory b/core/src/main/resources/META-INF/services/org.apache.metamodel.factory.ResourceFactory new file mode 100644 index 0000000..5bb0b9e --- /dev/null +++ b/core/src/main/resources/META-INF/services/org.apache.metamodel.factory.ResourceFactory @@ -0,0 +1,4 @@ +org.apache.metamodel.factory.FileResourceFactory +org.apache.metamodel.factory.ClasspathResourceFactory +org.apache.metamodel.factory.UrlResourceFactory +org.apache.metamodel.factory.InMemoryResourceFactory http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/test/java/org/apache/metamodel/factory/ResourceFactoryRegistryImplTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/metamodel/factory/ResourceFactoryRegistryImplTest.java b/core/src/test/java/org/apache/metamodel/factory/ResourceFactoryRegistryImplTest.java new file mode 100644 index 0000000..0122253 --- /dev/null +++ b/core/src/test/java/org/apache/metamodel/factory/ResourceFactoryRegistryImplTest.java @@ -0,0 +1,72 @@ +/** + * 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.metamodel.factory; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.apache.metamodel.util.ClasspathResource; +import org.apache.metamodel.util.InMemoryResource; +import org.apache.metamodel.util.Resource; +import org.apache.metamodel.util.UrlResource; +import org.junit.Test; + +public class ResourceFactoryRegistryImplTest { + + private final ResourceFactoryRegistry registry = ResourceFactoryRegistryImpl.getDefaultInstance(); + + @Test + public void testGetQualifiedFileResource() throws Exception { + final File file = new File("src/test/resources/unicode-text-utf8.txt"); + final Resource res = registry.createResource(new SimpleResourceProperties("file:///" + file.getAbsolutePath())); + assertTrue(res.isExists()); + assertEquals("unicode-text-utf8.txt", res.getName()); + } + + @Test + public void testGetUnqualifiedRelativeFileResource() throws Exception { + final Resource res = registry.createResource(new SimpleResourceProperties( + "src/test/resources/unicode-text-utf8.txt")); + assertTrue(res.isExists()); + assertEquals("unicode-text-utf8.txt", res.getName()); + } + + @Test + public void testGetInMemoryResource() throws Exception { + final Resource res = registry.createResource(new SimpleResourceProperties("mem:///foo.bar.txt")); + assertTrue(res instanceof InMemoryResource); + } + + @Test + public void testGetClasspathResource() throws Exception { + final Resource res = registry.createResource(new SimpleResourceProperties("classpath:///folder/foo")); + assertTrue(res.isExists()); + assertTrue(res instanceof ClasspathResource); + } + + @Test + public void testGetUrlResource() throws Exception { + final Resource res = registry.createResource(new SimpleResourceProperties( + "http://metamodel.apache.org/robots.txt")); + assertTrue(res.isExists()); + assertTrue(res instanceof UrlResource); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/core/src/test/java/org/apache/metamodel/util/UrlResourceTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/metamodel/util/UrlResourceTest.java b/core/src/test/java/org/apache/metamodel/util/UrlResourceTest.java index 8478253..8054d8d 100644 --- a/core/src/test/java/org/apache/metamodel/util/UrlResourceTest.java +++ b/core/src/test/java/org/apache/metamodel/util/UrlResourceTest.java @@ -23,10 +23,10 @@ import junit.framework.TestCase; public class UrlResourceTest extends TestCase { public void testGetName() throws Exception { - UrlResource resource = new UrlResource("http://eobjects.org/foo.txt"); - assertEquals("foo.txt", resource.getName()); + UrlResource resource = new UrlResource("http://metamodel.apache.org/robots.txt"); + assertEquals("robots.txt", resource.getName()); - resource = new UrlResource("http://eobjects.org/"); - assertEquals("http://eobjects.org/", resource.getName()); + resource = new UrlResource("http://metamodel.apache.org/"); + assertEquals("http://metamodel.apache.org/", resource.getName()); } } http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/csv/src/main/java/org/apache/metamodel/csv/CsvDataContextFactory.java ---------------------------------------------------------------------- diff --git a/csv/src/main/java/org/apache/metamodel/csv/CsvDataContextFactory.java b/csv/src/main/java/org/apache/metamodel/csv/CsvDataContextFactory.java new file mode 100644 index 0000000..105fd5b --- /dev/null +++ b/csv/src/main/java/org/apache/metamodel/csv/CsvDataContextFactory.java @@ -0,0 +1,73 @@ +/** + * 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.metamodel.csv; + +import org.apache.metamodel.DataContext; +import org.apache.metamodel.factory.DataContextFactory; +import org.apache.metamodel.factory.DataContextProperties; +import org.apache.metamodel.factory.ResourceFactoryRegistry; +import org.apache.metamodel.util.FileHelper; +import org.apache.metamodel.util.Resource; + +public class CsvDataContextFactory implements DataContextFactory { + + public static final String PROPERTY_TYPE = "csv"; + + @Override + public boolean accepts(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) { + return PROPERTY_TYPE.equals(properties.getDataContextType()); + } + + @Override + public DataContext create(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) { + assert accepts(properties, resourceFactoryRegistry); + + final Resource resource = resourceFactoryRegistry.createResource(properties.getResourceProperties()); + + final int columnNameLineNumber = getInt(properties.getColumnNameLineNumber(), + CsvConfiguration.DEFAULT_COLUMN_NAME_LINE); + final String encoding = getString(properties.getEncoding(), FileHelper.DEFAULT_ENCODING); + final char separatorChar = getChar(properties.getSeparatorChar(), CsvConfiguration.DEFAULT_SEPARATOR_CHAR); + final char quoteChar = getChar(properties.getQuoteChar(), CsvConfiguration.DEFAULT_QUOTE_CHAR); + final char escapeChar = getChar(properties.getEscapeChar(), CsvConfiguration.DEFAULT_ESCAPE_CHAR); + final boolean failOnInconsistentRowLength = getBoolean(properties.isFailOnInconsistentRowLength(), false); + final boolean multilineValuesEnabled = getBoolean(properties.isMultilineValuesEnabled(), true); + + final CsvConfiguration configuration = new CsvConfiguration(columnNameLineNumber, encoding, separatorChar, + quoteChar, escapeChar, failOnInconsistentRowLength, multilineValuesEnabled); + return new CsvDataContext(resource, configuration); + } + + private String getString(String value, String ifNull) { + return value == null ? ifNull : value; + } + + private int getInt(Integer value, int ifNull) { + return value == null ? ifNull : value; + } + + private boolean getBoolean(Boolean value, boolean ifNull) { + return value == null ? ifNull : value; + } + + private char getChar(Character value, char ifNull) { + return value == null ? ifNull : value; + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/csv/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory ---------------------------------------------------------------------- diff --git a/csv/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory b/csv/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory new file mode 100644 index 0000000..28857ad --- /dev/null +++ b/csv/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory @@ -0,0 +1 @@ +org.apache.metamodel.csv.CsvDataContextFactory \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/csv/src/test/java/org/apache/metamodel/csv/CsvDataContextFactoryTest.java ---------------------------------------------------------------------- diff --git a/csv/src/test/java/org/apache/metamodel/csv/CsvDataContextFactoryTest.java b/csv/src/test/java/org/apache/metamodel/csv/CsvDataContextFactoryTest.java new file mode 100644 index 0000000..bd92a73 --- /dev/null +++ b/csv/src/test/java/org/apache/metamodel/csv/CsvDataContextFactoryTest.java @@ -0,0 +1,57 @@ +/** + * 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.metamodel.csv; + +import java.util.Collection; + +import org.apache.metamodel.factory.DataContextFactory; +import org.apache.metamodel.factory.DataContextFactoryRegistryImpl; +import org.apache.metamodel.factory.DataContextPropertiesImpl; +import org.junit.Assert; +import org.junit.Test; + +public class CsvDataContextFactoryTest { + + @Test + public void testDiscovery() throws Exception { + final Collection<DataContextFactory> factories = DataContextFactoryRegistryImpl.getDefaultInstance() + .getFactories(); + + boolean found = false; + for (DataContextFactory factory : factories) { + if (factory instanceof CsvDataContextFactory) { + found = true; + break; + } + } + + if (!found) { + Assert.fail("Expected to find CsvDataContextFactory. Found: " + factories); + } + } + + @Test + public void testCreateDataContext() throws Exception { + final DataContextPropertiesImpl properties = new DataContextPropertiesImpl(); + properties.put("type", "csv"); + properties.put("resource", "src/test/resources/csv_people.csv"); + + DataContextFactoryRegistryImpl.getDefaultInstance().createDataContext(properties); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/hadoop/src/main/java/org/apache/metamodel/hadoop/HdfsResourceFactory.java ---------------------------------------------------------------------- diff --git a/hadoop/src/main/java/org/apache/metamodel/hadoop/HdfsResourceFactory.java b/hadoop/src/main/java/org/apache/metamodel/hadoop/HdfsResourceFactory.java new file mode 100644 index 0000000..767937d --- /dev/null +++ b/hadoop/src/main/java/org/apache/metamodel/hadoop/HdfsResourceFactory.java @@ -0,0 +1,46 @@ +/** + * 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.metamodel.hadoop; + +import org.apache.metamodel.factory.ResourceFactory; +import org.apache.metamodel.factory.ResourceProperties; +import org.apache.metamodel.factory.UnsupportedResourcePropertiesException; +import org.apache.metamodel.util.HdfsResource; +import org.apache.metamodel.util.Resource; + +public class HdfsResourceFactory implements ResourceFactory { + + /** + * Property that can be used + */ + public static final String PROPERTY_HADOOP_CONF_DIR = "hadoop-conf-dir"; + + @Override + public boolean accepts(ResourceProperties properties) { + return "hdfs".equals(properties.getUri().getScheme()); + } + + @Override + public Resource create(ResourceProperties properties) throws UnsupportedResourcePropertiesException { + final Object hadoopConfDirProperty = properties.toMap().get(PROPERTY_HADOOP_CONF_DIR); + final String hadoopConfDir = hadoopConfDirProperty == null ? null : hadoopConfDirProperty.toString(); + return new HdfsResource(properties.getUri().toString(), hadoopConfDir); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/hadoop/src/main/resources/META-INF/services/org.apache.metamodel.factory.ResourceFactory ---------------------------------------------------------------------- diff --git a/hadoop/src/main/resources/META-INF/services/org.apache.metamodel.factory.ResourceFactory b/hadoop/src/main/resources/META-INF/services/org.apache.metamodel.factory.ResourceFactory new file mode 100644 index 0000000..a66dba0 --- /dev/null +++ b/hadoop/src/main/resources/META-INF/services/org.apache.metamodel.factory.ResourceFactory @@ -0,0 +1 @@ +org.apache.metamodel.hadoop.HdfsResourceFactory http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContextFactory.java ---------------------------------------------------------------------- diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContextFactory.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContextFactory.java new file mode 100644 index 0000000..2dfe81d --- /dev/null +++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContextFactory.java @@ -0,0 +1,86 @@ +/** + * 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.metamodel.jdbc; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.apache.metamodel.ConnectionException; +import org.apache.metamodel.DataContext; +import org.apache.metamodel.factory.DataContextFactory; +import org.apache.metamodel.factory.DataContextProperties; +import org.apache.metamodel.factory.ResourceFactoryRegistry; +import org.apache.metamodel.schema.TableType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JdbcDataContextFactory implements DataContextFactory { + + private static final Logger logger = LoggerFactory.getLogger(JdbcDataContextFactory.class); + + public static final String PROPERTY_TYPE = "jdbc"; + + @Override + public boolean accepts(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) { + return PROPERTY_TYPE.equals(properties.getDataContextType()); + } + + @Override + public DataContext create(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) + throws ConnectionException { + final String driverClassName = properties.getDriverClassName(); + if (driverClassName != null) { + try { + Class.forName(driverClassName); + } catch (ClassNotFoundException e) { + logger.warn("Failed to initialize driver class: {}", driverClassName, e); + } + } + + final TableType[] tableTypes = properties.getTableTypes() == null ? TableType.DEFAULT_TABLE_TYPES + : properties.getTableTypes(); + final String catalogName = properties.getCatalogName(); + + final DataSource dataSource = properties.getDataSource(); + if (dataSource != null) { + return new JdbcDataContext(dataSource, tableTypes, catalogName); + } + + final String url = properties.getUrl(); + final String username = properties.getUsername(); + final String password = properties.getPassword(); + + final Connection connection; + try { + if (username != null) { + connection = DriverManager.getConnection(url, username, password); + } else { + connection = DriverManager.getConnection(url); + } + } catch (SQLException e) { + throw new ConnectionException("Failed to open JDBC connection from URL: " + url, e); + } + + return new JdbcDataContext(connection, tableTypes, catalogName); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/jdbc/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory ---------------------------------------------------------------------- diff --git a/jdbc/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory b/jdbc/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory new file mode 100644 index 0000000..c7c4772 --- /dev/null +++ b/jdbc/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory @@ -0,0 +1 @@ +org.apache.metamodel.jdbc.JdbcDataContextFactory \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/jdbc/src/test/java/org/apache/metamodel/jdbc/H2databaseTest.java ---------------------------------------------------------------------- diff --git a/jdbc/src/test/java/org/apache/metamodel/jdbc/H2databaseTest.java b/jdbc/src/test/java/org/apache/metamodel/jdbc/H2databaseTest.java index 6560247..6e21ae5 100644 --- a/jdbc/src/test/java/org/apache/metamodel/jdbc/H2databaseTest.java +++ b/jdbc/src/test/java/org/apache/metamodel/jdbc/H2databaseTest.java @@ -26,8 +26,6 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; -import junit.framework.TestCase; - import org.apache.metamodel.UpdateCallback; import org.apache.metamodel.UpdateScript; import org.apache.metamodel.create.CreateTable; @@ -48,10 +46,15 @@ import org.apache.metamodel.schema.Table; import org.apache.metamodel.update.Update; import org.apache.metamodel.util.MutableRef; +import junit.framework.TestCase; + /** * Test case that tests interaction with the H2 embedded database */ public class H2databaseTest extends TestCase { + + public static final String DRIVER_CLASS = "org.h2.Driver"; + public static final String URL_MEMORY_DATABASE = "jdbc:h2:mem:"; private final String[] FIRST_NAMES = { "Suzy", "Barbara", "John", "Ken", "Billy", "Larry", "Joe", "Margareth", "Bobby", "Elizabeth" }; @@ -62,8 +65,8 @@ public class H2databaseTest extends TestCase { @Override protected void setUp() throws Exception { super.setUp(); - Class.forName("org.h2.Driver"); - conn = DriverManager.getConnection("jdbc:h2:mem:"); + Class.forName(DRIVER_CLASS); + conn = DriverManager.getConnection(URL_MEMORY_DATABASE); } @Override http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextFactoryTest.java ---------------------------------------------------------------------- diff --git a/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextFactoryTest.java b/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextFactoryTest.java new file mode 100644 index 0000000..9511164 --- /dev/null +++ b/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcDataContextFactoryTest.java @@ -0,0 +1,45 @@ +/** + * 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.metamodel.jdbc; + +import static org.junit.Assert.assertTrue; + +import org.apache.metamodel.DataContext; +import org.apache.metamodel.factory.DataContextFactoryRegistryImpl; +import org.apache.metamodel.factory.DataContextPropertiesImpl; +import org.apache.metamodel.jdbc.dialects.H2QueryRewriter; +import org.junit.Test; + +public class JdbcDataContextFactoryTest { + + @Test + public void testCreateDataContext() throws Exception { + final DataContextPropertiesImpl properties = new DataContextPropertiesImpl(); + properties.setDataContextType("jdbc"); + properties.put("driver-class", H2databaseTest.DRIVER_CLASS); + properties.put("url", H2databaseTest.URL_MEMORY_DATABASE); + + final DataContext dataContext = DataContextFactoryRegistryImpl.getDefaultInstance().createDataContext( + properties); + assertTrue(dataContext instanceof JdbcDataContext); + + final JdbcDataContext jdbcDataContext = (JdbcDataContext) dataContext; + assertTrue(jdbcDataContext.getQueryRewriter() instanceof H2QueryRewriter); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/52c3dafc/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index dad89f2..95ed697 100644 --- a/pom.xml +++ b/pom.xml @@ -376,6 +376,7 @@ under the License. <exclude>**/src/assembly/metamodel-packaged-assembly-descriptor.xml</exclude> <exclude>**/.gitignore/**</exclude> <exclude>.git/**</exclude> + <exclude>**/src/main/resources/META-INF/services/**</exclude> <exclude>**/src/test/resources/**</exclude> <exclude>**/src/site/**</exclude> <exclude>**/.project</exclude>
