/** * 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.camel.component.hbase; import java.io.IOException; import java.security.PrivilegedAction; import java.util.List; import java.util.Map; import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.hbase.mapping.CellMappingStrategyFactory; import org.apache.camel.component.hbase.model.HBaseCell; import org.apache.camel.component.hbase.model.HBaseRow; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.HBaseAdmin; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.filter.Filter; import org.apache.hadoop.security.UserGroupInformation; /** * For reading/writing from/to an HBase store (Hadoop database). */ @UriEndpoint(firstVersion = "2.10.0", scheme = "hbase", title = "HBase", syntax = "hbase:tableName", consumerClass = HBaseConsumer.class, label = "hadoop") public class HBaseEndpoint extends DefaultEndpoint { private Configuration configuration; private final Connection connection; private HBaseAdmin admin; @UriPath(description = "The name of the table") @Metadata(required = "true") private final String tableName; @UriParam(label = "producer", defaultValue = "100") private int maxResults = 100; @UriParam private List<Filter> filters; @UriParam(label = "consumer", enums = "CamelHBasePut,CamelHBaseGet,CamelHBaseScan,CamelHBaseDelete") private String operation; @UriParam(label = "consumer", defaultValue = "true") private boolean remove = true; @UriParam(enums = "header,body") private String mappingStrategyName; @UriParam private String mappingStrategyClassName; @UriParam private CellMappingStrategyFactory cellMappingStrategyFactory = new CellMappingStrategyFactory(); @UriParam(label = "consumer") private HBaseRemoveHandler removeHandler = new HBaseDeleteHandler(); @UriParam private HBaseRow rowModel; @UriParam(label = "consumer") private int maxMessagesPerPoll; @UriParam private UserGroupInformation userGroupInformation; @UriParam(prefix = "row.", multiValue = true) private Map<String, Object> rowMapping; /** * in the purpose of performance optimization */ private byte[] tableNameBytes; public HBaseEndpoint(String uri, HBaseComponent component, Connection connection, String tableName) { super(uri, component); this.tableName = tableName; this.connection = connection; if (this.tableName == null) { throw new IllegalArgumentException("Table name can not be null"); } else { tableNameBytes = tableName.getBytes(); } } public Producer createProducer() throws Exception { return new HBaseProducer(this); } public Consumer createConsumer(Processor processor) throws Exception { HBaseConsumer consumer = new HBaseConsumer(this, processor); configureConsumer(consumer); consumer.setMaxMessagesPerPoll(maxMessagesPerPoll); return consumer; } public boolean isSingleton() { return true; } public Configuration getConfiguration() { return configuration; } public void setConfiguration(Configuration configuration) { this.configuration = configuration; } public HBaseAdmin getAdmin() { return admin; } public void setAdmin(HBaseAdmin admin) { this.admin = admin; } public int getMaxResults() { return maxResults; } /** * The maximum number of rows to scan. */ public void setMaxResults(int maxResults) { this.maxResults = maxResults; } public List<Filter> getFilters() { return filters; } /** * A list of filters to use. */ public void setFilters(List<Filter> filters) { this.filters = filters; } public String getOperation() { return operation; } /** * The HBase operation to perform */ public void setOperation(String operation) { this.operation = operation; } public CellMappingStrategyFactory getCellMappingStrategyFactory() { return cellMappingStrategyFactory; } /** * To use a custom CellMappingStrategyFactory that is responsible for mapping cells. */ public void setCellMappingStrategyFactory(CellMappingStrategyFactory cellMappingStrategyFactory) { this.cellMappingStrategyFactory = cellMappingStrategyFactory; } public String getMappingStrategyName() { return mappingStrategyName; } /** * The strategy to use for mapping Camel messages to HBase columns. Supported values: header, or body. */ public void setMappingStrategyName(String mappingStrategyName) { this.mappingStrategyName = mappingStrategyName; } public String getMappingStrategyClassName() { return mappingStrategyClassName; } /** * The class name of a custom mapping strategy implementation. */ public void setMappingStrategyClassName(String mappingStrategyClassName) { this.mappingStrategyClassName = mappingStrategyClassName; } public HBaseRow getRowModel() { return rowModel; } /** * An instance of org.apache.camel.component.hbase.model.HBaseRow which describes how each row should be modeled */ public void setRowModel(HBaseRow rowModel) { this.rowModel = rowModel; } public boolean isRemove() { return remove; } /** * If the option is true, Camel HBase Consumer will remove the rows which it processes. */ public void setRemove(boolean remove) { this.remove = remove; } public HBaseRemoveHandler getRemoveHandler() { return removeHandler; } /** * To use a custom HBaseRemoveHandler that is executed when a row is to be removed. */ public void setRemoveHandler(HBaseRemoveHandler removeHandler) { this.removeHandler = removeHandler; } public int getMaxMessagesPerPoll() { return maxMessagesPerPoll; } /** * Gets the maximum number of messages as a limit to poll at each polling. * <p/> * Is default unlimited, but use 0 or negative number to disable it as unlimited. */ public void setMaxMessagesPerPoll(int maxMessagesPerPoll) { this.maxMessagesPerPoll = maxMessagesPerPoll; } public UserGroupInformation getUserGroupInformation() { return userGroupInformation; } /** * Defines privileges to communicate with HBase such as using kerberos. */ public void setUserGroupInformation(UserGroupInformation userGroupInformation) { this.userGroupInformation = userGroupInformation; } public Map<String, Object> getRowMapping() { return rowMapping; } /** * To map the key/values from the Map to a {@link HBaseRow}. * <p/> * The following keys is supported: * <ul> * <li>rowId - The id of the row. This has limited use as the row usually changes per Exchange.</li> * <li>rowType - The type to covert row id to. Supported operations: CamelHBaseScan.</li> * <li>family - The column family. Supports a number suffix for referring to more than one columns.</li> * <li>qualifier - The column qualifier. Supports a number suffix for referring to more than one columns.</li> * <li>value - The value. Supports a number suffix for referring to more than one columns</li> * <li>valueType - The value type. Supports a number suffix for referring to more than one columns. Supported operations: CamelHBaseGet, and CamelHBaseScan.</li> * </ul> */ public void setRowMapping(Map<String, Object> rowMapping) { this.rowMapping = rowMapping; } @Override protected void doStart() throws Exception { super.doStart(); if (rowModel == null && rowMapping != null) { rowModel = createRowModel(rowMapping); } } @Override protected void doStop() throws Exception { super.doStop(); } /** * Gets connection to the table (secured or not, depends on the object initialization) * please remember to close the table after use * @return table, remember to close! */ public Table getTable() throws IOException { if (userGroupInformation != null) { return userGroupInformation.doAs(new PrivilegedAction<Table>() { @Override public Table run() { try { return connection.getTable(TableName.valueOf(tableNameBytes)); } catch (IOException e) { throw new RuntimeException(e); } } }); } else { return connection.getTable(TableName.valueOf(tableNameBytes)); } } /** * Creates an {@link HBaseRow} model from the specified endpoint parameters. */ private HBaseRow createRowModel(Map<String, Object> parameters) { HBaseRow rowModel = new HBaseRow(); if (parameters.containsKey(HBaseAttribute.HBASE_ROW_TYPE.asOption())) { String rowType = String.valueOf(parameters.remove(HBaseAttribute.HBASE_ROW_TYPE.asOption())); if (rowType != null && !rowType.isEmpty()) { rowModel.setRowType(getCamelContext().getClassResolver().resolveClass(rowType)); } } for (int i = 1; parameters.get(HBaseAttribute.HBASE_FAMILY.asOption(i)) != null && parameters.get(HBaseAttribute.HBASE_QUALIFIER.asOption(i)) != null; i++) { HBaseCell cellModel = new HBaseCell(); cellModel.setFamily(String.valueOf(parameters.remove(HBaseAttribute.HBASE_FAMILY.asOption(i)))); cellModel.setQualifier(String.valueOf(parameters.remove(HBaseAttribute.HBASE_QUALIFIER.asOption(i)))); cellModel.setValue(String.valueOf(parameters.remove(HBaseAttribute.HBASE_VALUE.asOption(i)))); if (parameters.containsKey(HBaseAttribute.HBASE_VALUE_TYPE.asOption(i))) { String valueType = String.valueOf(parameters.remove(HBaseAttribute.HBASE_VALUE_TYPE.asOption(i))); if (valueType != null && !valueType.isEmpty()) { rowModel.setRowType(getCamelContext().getClassResolver().resolveClass(valueType)); } } rowModel.getCells().add(cellModel); } return rowModel; } }