Update to POI 3.10-FINAL.
This commit is contained in:
committed by
Michael Minella
parent
0abcbfeac5
commit
bec581912f
77
spring-batch-excel/pom.xml
Normal file
77
spring-batch-excel/pom.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframewor.batch</groupId>
|
||||
<artifactId>spring-batch-excel</artifactId>
|
||||
<version>1.3.0.BUILD-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<spring.batch.version>2.2.5.RELEASE</spring.batch.version>
|
||||
<jxl.version>2.6.12</jxl.version>
|
||||
<poi.version>3.10-FINAL</poi.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.batch</groupId>
|
||||
<artifactId>spring-batch-core</artifactId>
|
||||
<version>${spring.batch.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.batch</groupId>
|
||||
<artifactId>spring-batch-infrastructure</artifactId>
|
||||
<version>${spring.batch.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.jexcelapi</groupId>
|
||||
<artifactId>jxl</artifactId>
|
||||
<version>${jxl.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>${poi.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Test Dependencies -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.5.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
|
||||
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.batch.item.ItemReader} implementation which uses the JExcelApi to read an Excel
|
||||
* file. It will read the file sheet for sheet and row for row. It is based on
|
||||
* the {@link org.springframework.batch.item.file.FlatFileItemReader}
|
||||
*
|
||||
* @param <T> the type
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
public abstract class AbstractExcelItemReader<T> extends AbstractItemCountingItemStreamItemReader<T> implements
|
||||
ResourceAwareItemReaderItemStream<T>, InitializingBean {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
private Resource resource;
|
||||
private int linesToSkip = 0;
|
||||
private int currentRow = 0;
|
||||
private int currentSheet = 0;
|
||||
private RowMapper<T> rowMapper;
|
||||
private RowCallbackHandler skippedRowsCallback;
|
||||
private boolean noInput = false;
|
||||
private boolean strict = true;
|
||||
|
||||
public AbstractExcelItemReader() {
|
||||
super();
|
||||
this.setName(ClassUtils.getShortName(this.getClass()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T doRead() throws Exception {
|
||||
if (this.noInput) {
|
||||
return null;
|
||||
}
|
||||
final Sheet sheet = this.getSheet(this.currentSheet);
|
||||
final String[] row = this.readRow(sheet);
|
||||
if (ObjectUtils.isEmpty(row)) {
|
||||
this.currentSheet++;
|
||||
if (this.currentSheet >= this.getNumberOfSheets()) {
|
||||
if (logger.isDebugEnabled() ) {
|
||||
logger.debug("No more sheets in '" + this.resource.getDescription() + "'.");
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
this.currentRow = 0;
|
||||
this.openSheet();
|
||||
return this.doRead();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return this.rowMapper.mapRow(sheet, row, this.currentRow);
|
||||
} catch (final Exception e) {
|
||||
throw new ExcelFileParseException("Exception parsing Excel file.", e, this.resource.getDescription(),
|
||||
sheet.getName(), this.currentRow, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOpen() throws Exception {
|
||||
Assert.notNull(this.resource, "Input resource must be set");
|
||||
this.noInput = true;
|
||||
if (!this.resource.exists()) {
|
||||
if (this.strict) {
|
||||
throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): "
|
||||
+ this.resource);
|
||||
}
|
||||
logger.warn("Input resource does not exist '"+this.resource.getDescription()+"'.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.resource.isReadable()) {
|
||||
if (this.strict) {
|
||||
throw new IllegalStateException("Input resource must be readable (reader is in 'strict' mode): "
|
||||
+ this.resource);
|
||||
}
|
||||
logger.warn("Input resource is not readable '"+this.resource.getDescription()+"'.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.noInput = false;
|
||||
this.openExcelFile(this.resource);
|
||||
this.openSheet();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Opened workbook ["+this.resource.getFilename()+"] with "+this.getNumberOfSheets()+" sheets.");
|
||||
}
|
||||
}
|
||||
|
||||
private String[] readRow(final Sheet sheet) {
|
||||
this.currentRow++;
|
||||
if (this.currentRow < sheet.getNumberOfRows()) {
|
||||
return sheet.getRow(this.currentRow);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void openSheet() {
|
||||
final Sheet sheet = this.getSheet(this.currentSheet);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Opening sheet "+sheet.getName()+".");
|
||||
}
|
||||
for (int i = 0; i < this.linesToSkip; i++) {
|
||||
final String[] row = this.readRow(sheet);
|
||||
if (this.skippedRowsCallback != null) {
|
||||
this.skippedRowsCallback.handleRow(sheet, row);
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Openend sheet "+sheet.getName()+", with "+sheet.getNumberOfRows()+" rows.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void doClose() throws Exception {
|
||||
doCloseWorkbook();
|
||||
if (getResource() != null) {
|
||||
try {
|
||||
InputStream is = getResource().getInputStream();
|
||||
is.close();
|
||||
} catch (IOException ioe) {
|
||||
logger.warn("Exception whilst obtaining or closing the inputstream.", ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method which can be overriden by subclasses to do cleanup additional resources.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void doCloseWorkbook() throws Exception {
|
||||
}
|
||||
|
||||
protected Resource getResource() {
|
||||
return this.resource;
|
||||
}
|
||||
|
||||
public void setResource(final Resource resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.rowMapper, "RowMapper must be set");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of lines to skip. This number is applied to all worksheet
|
||||
* in the excel file! default to 0
|
||||
*
|
||||
* @param linesToSkip
|
||||
*/
|
||||
public void setLinesToSkip(final int linesToSkip) {
|
||||
this.linesToSkip = linesToSkip;
|
||||
}
|
||||
|
||||
protected abstract Sheet getSheet(int sheet);
|
||||
|
||||
protected abstract int getNumberOfSheets();
|
||||
|
||||
protected abstract void openExcelFile(Resource resource) throws Exception;
|
||||
|
||||
/**
|
||||
* In strict mode the reader will throw an exception on
|
||||
* {@link #open(org.springframework.batch.item.ExecutionContext)} if the input resource does not exist.
|
||||
*
|
||||
* @param strict true by default
|
||||
*/
|
||||
public void setStrict(final boolean strict) {
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
public void setRowMapper(final RowMapper<T> rowMapper) {
|
||||
this.rowMapper = rowMapper;
|
||||
}
|
||||
|
||||
public void setSkippedRowsCallback(final RowCallbackHandler skippedRowsCallback) {
|
||||
this.skippedRowsCallback = skippedRowsCallback;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel;
|
||||
|
||||
import org.springframework.batch.item.ParseException;
|
||||
|
||||
/**
|
||||
* Exception thrown when parsing excel files. The name of the sheet, the row number on that sheet and the
|
||||
* name of the excel file can be passed in so that in exception handling we can reuse it. This class only has
|
||||
* simply dependencies to make it is generic as possible.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
public class ExcelFileParseException extends ParseException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -3939056060545496492L;
|
||||
|
||||
private final String filename;
|
||||
private final String sheet;
|
||||
private final String[] row;
|
||||
private final int rowNumber;
|
||||
|
||||
/**
|
||||
* Construct an {@link ExcelFileParseException}.
|
||||
*
|
||||
* @param message the message
|
||||
* @param cause the root cause
|
||||
* @param filename the name of the excel file
|
||||
* @param sheet the name of the sheet
|
||||
* @param rowNumber the row number in the current sheet
|
||||
* @param row the row data as text
|
||||
*/
|
||||
public ExcelFileParseException(final String message, final Throwable cause, final String filename,
|
||||
final String sheet, final int rowNumber, final String[] row) {
|
||||
super(message, cause);
|
||||
this.filename = filename;
|
||||
this.sheet = sheet;
|
||||
this.rowNumber = rowNumber;
|
||||
this.row = row;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return this.filename;
|
||||
}
|
||||
|
||||
public String getSheet() {
|
||||
return this.sheet;
|
||||
}
|
||||
|
||||
public int getRowNumber() {
|
||||
return this.rowNumber;
|
||||
}
|
||||
|
||||
public String[] getRow() {
|
||||
return this.row;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel;
|
||||
|
||||
/**
|
||||
* Callback to handle skipped lines. Useful for header/footer processing.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
public interface RowCallbackHandler {
|
||||
|
||||
void handleRow(Sheet sheet, String[] row);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel;
|
||||
|
||||
/**
|
||||
* Map rows from an excel sheet to an object.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface RowMapper<T> {
|
||||
|
||||
/**
|
||||
* Implementations must implement this method to map the provided row to
|
||||
* the parameter type T. The row number represents the number of rows
|
||||
* into a {@link Sheet} the current line resides.
|
||||
*
|
||||
* @param sheet the current sheet
|
||||
* @param row to be mapped
|
||||
* @param rowNum of the current row
|
||||
* @return mapped object of type T
|
||||
* @throws Exception if error occured while parsing.
|
||||
*/
|
||||
T mapRow(Sheet sheet, String[] row, int rowNum) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel;
|
||||
|
||||
/**
|
||||
* Interface to wrap different Excel implementations like JExcel, JXL or Apache POI.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
public interface Sheet {
|
||||
|
||||
/**
|
||||
* Get the number of rows in this sheet.
|
||||
*
|
||||
* @return the number of rows.
|
||||
*/
|
||||
int getNumberOfRows();
|
||||
|
||||
/**
|
||||
* Get the name of the sheet.
|
||||
*
|
||||
* @return the name of the sheet.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Get the row as a String[]. Returns null if the row doesn't exist.
|
||||
*
|
||||
* @param rowNumber the row number to read.
|
||||
* @return a String[] or null
|
||||
*/
|
||||
String[] getRow(int rowNumber);
|
||||
|
||||
/**
|
||||
* Gets the first row of the sheet and use it as header.
|
||||
*
|
||||
* @return String[] of row 0
|
||||
*/
|
||||
String[] getHeader();
|
||||
|
||||
/**
|
||||
* The number of columns in this sheet.
|
||||
*
|
||||
* @return number of columns
|
||||
*/
|
||||
int getNumberOfColumns();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.jxl;
|
||||
|
||||
import jxl.Workbook;
|
||||
import jxl.read.biff.WorkbookParser;
|
||||
import org.springframework.batch.item.excel.AbstractExcelItemReader;
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.batch.item.ItemReader} implementation which uses the JExcelApi to read an Excel
|
||||
* file. It will read the file sheet for sheet and row for row. It is based on
|
||||
* the {@link org.springframework.batch.item.file.FlatFileItemReader}
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
* @param <T> the type
|
||||
*/
|
||||
public class JxlItemReader<T> extends AbstractExcelItemReader<T> {
|
||||
|
||||
private Workbook workbook;
|
||||
|
||||
public JxlItemReader() {
|
||||
super();
|
||||
this.setName(ClassUtils.getShortName(JxlItemReader.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void openExcelFile(final Resource resource) throws Exception {
|
||||
this.workbook = WorkbookParser.getWorkbook(resource.getInputStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCloseWorkbook() throws Exception {
|
||||
if (this.workbook != null) {
|
||||
this.workbook.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet getSheet(final int sheet) {
|
||||
if (sheet < this.workbook.getNumberOfSheets()) {
|
||||
return new JxlSheet(this.workbook.getSheet(sheet));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNumberOfSheets() {
|
||||
if (this.workbook == null) {
|
||||
throw new IllegalStateException("Workbook file not ready for reading!");
|
||||
}
|
||||
return this.workbook.getNumberOfSheets();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.jxl;
|
||||
|
||||
import jxl.Cell;
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.batch.item.excel.Sheet} implementation for JXL.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
public class JxlSheet implements Sheet {
|
||||
|
||||
private final jxl.Sheet delegate;
|
||||
|
||||
/**
|
||||
* Constructor which takes the delegate sheet.
|
||||
*
|
||||
* @param delegate the JXL sheet
|
||||
*/
|
||||
JxlSheet(final jxl.Sheet delegate) {
|
||||
super();
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getNumberOfRows() {
|
||||
return this.delegate.getRows();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String[] getHeader() {
|
||||
return this.getRow(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String[] getRow(final int rowNumber) {
|
||||
final Cell[] row = this.delegate.getRow(rowNumber);
|
||||
return JxlUtils.extractContents(row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getName() {
|
||||
return this.delegate.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getNumberOfColumns() {
|
||||
return this.delegate.getColumns();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.jxl;
|
||||
|
||||
import jxl.Cell;
|
||||
import jxl.Workbook;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class containing utility methods to work with JXL.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
public final class JxlUtils {
|
||||
|
||||
/** Private constructor to prevent easy instantiation. */
|
||||
private JxlUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given cell is emtpy. The cell is empty if it contains no characters, it will trim spaces.
|
||||
|
||||
* @param cell to check
|
||||
* @return true/false
|
||||
* @see org.springframework.util.StringUtils#hasText(String)
|
||||
*/
|
||||
public static boolean isEmpty(final Cell cell) {
|
||||
return cell == null || !StringUtils.hasText(cell.getContents());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given row (Cell[]) is empty. It is considered empty when the row is null, the array is empty or all
|
||||
* the cells in the row are empty.
|
||||
*
|
||||
* @param row to check
|
||||
* @return true/false
|
||||
*/
|
||||
public static boolean isEmpty(final Cell[] row) {
|
||||
if (row == null || row.length == 0) {
|
||||
return true;
|
||||
}
|
||||
for (final Cell cell : row) {
|
||||
if (!isEmpty(cell)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given workbook has any sheets.
|
||||
*
|
||||
* @param workbook to check
|
||||
* @return true/false
|
||||
*/
|
||||
public static boolean hasSheets(final Workbook workbook) {
|
||||
return workbook != null && workbook.getNumberOfSheets() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the content from the given row.
|
||||
*
|
||||
* @param row the row
|
||||
* @return the content as String[]
|
||||
*/
|
||||
public static String[] extractContents(final Cell[] row) {
|
||||
final List<String> values = new ArrayList<String>();
|
||||
for (final Cell cell : row) {
|
||||
if (!isEmpty(cell)) {
|
||||
values.add(cell.getColumn(), cell.getContents());
|
||||
} else {
|
||||
values.add(cell.getColumn(), "");
|
||||
}
|
||||
}
|
||||
return values.toArray(new String[values.size()]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
/*
|
||||
* Copyright 2006-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.mapping;
|
||||
|
||||
import org.springframework.batch.item.excel.RowMapper;
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
import org.springframework.batch.item.excel.transform.DefaultRowTokenizer;
|
||||
import org.springframework.batch.item.excel.transform.RowTokenizer;
|
||||
import org.springframework.batch.item.file.mapping.FieldSetMapper;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link RowMapper} implementation which delegates to a {@link RowTokenizer} and a {@link org.springframework.batch.item.file.mapping.FieldSetMapper} the mapping
|
||||
* of fields and construction of objects.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class DefaultRowMapper<T> implements RowMapper<T>, InitializingBean {
|
||||
|
||||
private RowTokenizer rowTokenizer = new DefaultRowTokenizer();
|
||||
private FieldSetMapper<T> fieldSetMapper;
|
||||
|
||||
public T mapRow(final Sheet sheet, final String[] row, final int rowNum) throws Exception {
|
||||
return this.fieldSetMapper.mapFieldSet(this.rowTokenizer.tokenize(sheet, row));
|
||||
}
|
||||
|
||||
public void setFieldSetMapper(final FieldSetMapper<T> fieldSetMapper) {
|
||||
this.fieldSetMapper = fieldSetMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link RowTokenizer} to use to create a {@link org.springframework.batch.item.file.transform.FieldSet}. Default uses the {@link DefaultRowTokenizer}.
|
||||
*
|
||||
* @param rowTokenizer to use
|
||||
*/
|
||||
public void setRowTokenizer(final RowTokenizer rowTokenizer) {
|
||||
this.rowTokenizer = rowTokenizer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(this.rowTokenizer, "The RowTokenizer must be set");
|
||||
Assert.notNull(this.fieldSetMapper, "The FieldSetMapper must be set");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2006-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.mapping;
|
||||
|
||||
import org.springframework.batch.item.excel.RowMapper;
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
|
||||
/**
|
||||
* Pass through {@link RowMapper} useful for passing the orginal String[]
|
||||
* back directly rather than a mapped object.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
public class PassThroughRowMapper implements RowMapper<String[]> {
|
||||
|
||||
public String[] mapRow(final Sheet sheet, final String[] row, final int rowNum) throws Exception {
|
||||
return row;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2006-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.poi;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.batch.item.excel.AbstractExcelItemReader;
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.batch.item.ItemReader} implementation which uses apache POI to read an Excel
|
||||
* file. It will read the file sheet for sheet and row for row. It is based on
|
||||
* the {@link org.springframework.batch.item.file.FlatFileItemReader}
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
* @param <T> the type
|
||||
*/
|
||||
public class PoiItemReader<T> extends AbstractExcelItemReader<T> {
|
||||
|
||||
private Workbook workbook;
|
||||
|
||||
@Override
|
||||
protected Sheet getSheet(final int sheet) {
|
||||
return new PoiSheet(this.workbook.getSheetAt(sheet));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNumberOfSheets() {
|
||||
return this.workbook.getNumberOfSheets();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void openExcelFile(final Resource resource) throws Exception {
|
||||
this.workbook = WorkbookFactory.create(resource.getInputStream());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.poi;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sheet implementation for Apache POI.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
public class PoiSheet implements Sheet {
|
||||
|
||||
private final org.apache.poi.ss.usermodel.Sheet delegate;
|
||||
|
||||
/**
|
||||
* Constructor which takes the delegate sheet.
|
||||
*
|
||||
* @param delegate the apache POI sheet
|
||||
*/
|
||||
PoiSheet(final org.apache.poi.ss.usermodel.Sheet delegate) {
|
||||
super();
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getNumberOfRows() {
|
||||
return this.delegate.getLastRowNum() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getName() {
|
||||
return this.delegate.getSheetName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String[] getRow(final int rowNumber) {
|
||||
if (rowNumber > this.delegate.getLastRowNum()) {
|
||||
return null;
|
||||
}
|
||||
final Row row = this.delegate.getRow(rowNumber);
|
||||
final List<String> cells = new LinkedList<String>();
|
||||
|
||||
final Iterator<Cell> cellIter = row.iterator();
|
||||
while (cellIter.hasNext()) {
|
||||
final Cell cell = cellIter.next();
|
||||
switch (cell.getCellType()) {
|
||||
case Cell.CELL_TYPE_NUMERIC:
|
||||
cells.add(String.valueOf(cell.getNumericCellValue()));
|
||||
break;
|
||||
case Cell.CELL_TYPE_BOOLEAN:
|
||||
cells.add(String.valueOf(cell.getBooleanCellValue()));
|
||||
break;
|
||||
case Cell.CELL_TYPE_STRING:
|
||||
case Cell.CELL_TYPE_BLANK:
|
||||
cells.add(cell.getStringCellValue());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Cannot handle cells of type " + cell.getCellType());
|
||||
}
|
||||
}
|
||||
return cells.toArray(new String[cells.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String[] getHeader() {
|
||||
return this.getRow(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getNumberOfColumns() {
|
||||
final String[] columns = this.getHeader();
|
||||
if (columns != null) {
|
||||
return columns.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.transform;
|
||||
|
||||
/**
|
||||
* Convert a column name to an attribute name and vice versa.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
public interface ColumnToAttributeConverter {
|
||||
|
||||
/**
|
||||
* Convert a column name to an attribute name.
|
||||
*
|
||||
* @param column to convert
|
||||
* @return the attribute name
|
||||
*/
|
||||
String toAttribute(String column);
|
||||
|
||||
/**
|
||||
* Convert an attribute name to a column name.
|
||||
*
|
||||
* @param attribute to convert
|
||||
* @return the column name
|
||||
*/
|
||||
String toColumn(String attribute);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.transform;
|
||||
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
import org.springframework.batch.item.file.transform.DefaultFieldSetFactory;
|
||||
import org.springframework.batch.item.file.transform.FieldSet;
|
||||
import org.springframework.batch.item.file.transform.FieldSetFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link RowTokenizer} which assumes the column names are on the first row in the sheet.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
public class DefaultRowTokenizer implements RowTokenizer, InitializingBean {
|
||||
|
||||
private FieldSetFactory fieldSetFactory = new DefaultFieldSetFactory();
|
||||
|
||||
private ColumnToAttributeConverter converter = new PassThroughColumnToAttributeConverter();
|
||||
|
||||
private boolean useColumnHeader = true;
|
||||
|
||||
private boolean includeSheetName = false;
|
||||
private String attributeForSheetName = null;
|
||||
|
||||
public FieldSet tokenize(final Sheet sheet, final String[] row) {
|
||||
String[] values = new String[sheet.getNumberOfColumns()];
|
||||
System.arraycopy(row, 0, values, 0, row.length);
|
||||
|
||||
if (this.includeSheetName) {
|
||||
values = StringUtils.addStringToArray(values, sheet.getName());
|
||||
}
|
||||
|
||||
if (this.useColumnHeader) {
|
||||
String[] names = sheet.getHeader();
|
||||
if (this.includeSheetName) {
|
||||
names = StringUtils.addStringToArray(names, this.attributeForSheetName);
|
||||
}
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
names[i] = this.converter.toAttribute(names[i]);
|
||||
}
|
||||
|
||||
return this.fieldSetFactory.create(values, names);
|
||||
} else {
|
||||
return this.fieldSetFactory.create(values);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link org.springframework.batch.item.file.transform.FieldSetFactory} to use. The {@link org.springframework.batch.item.file.transform.DefaultFieldSetFactory} is used by default.
|
||||
*
|
||||
* @param fieldSetFactory to set
|
||||
*/
|
||||
public void setFieldSetFactory(final FieldSetFactory fieldSetFactory) {
|
||||
this.fieldSetFactory = fieldSetFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indication to use the column header, the default is <code>true</code>.
|
||||
* @param useColumnHeader
|
||||
*/
|
||||
public void setUseColumnHeader(final boolean useColumnHeader) {
|
||||
this.useColumnHeader = useColumnHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ColumnToAttributeConverter}.
|
||||
*
|
||||
* @param converter to set
|
||||
*/
|
||||
public void setConverter(final ColumnToAttributeConverter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public void setIncludeSheetName(final boolean includeSheetName) {
|
||||
this.includeSheetName = includeSheetName;
|
||||
}
|
||||
|
||||
public void setAttributeForSheetName(final String attributeForSheetName) {
|
||||
this.attributeForSheetName = attributeForSheetName;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (this.includeSheetName && this.useColumnHeader) {
|
||||
Assert.hasText(this.attributeForSheetName,
|
||||
"When using column header as attributes and including the sheetname an attribute name for the sheetname is required.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.transform;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link ColumnToAttributeConverter} which maps the names to columns and vice versa based on the provide mapping
|
||||
* configuration. If a mapping cannot be found it returns the name as is.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
public class MappingColumnToAttributeConverter implements ColumnToAttributeConverter {
|
||||
|
||||
private final Map<String, String> mapping = new HashMap<String, String>();
|
||||
|
||||
public String toAttribute(final String column) {
|
||||
if (this.mapping.containsKey(column)) {
|
||||
return this.mapping.get(column);
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
public String toColumn(final String attribute) {
|
||||
if (this.mapping.containsValue(attribute)) {
|
||||
for (Map.Entry<String, String> entry : this.mapping.entrySet()) {
|
||||
if (ObjectUtils.nullSafeEquals(attribute, entry.getValue())) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public void setMappings(final Map<String, String> mappings) {
|
||||
this.mapping.clear();
|
||||
this.mapping.putAll(mappings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.transform;
|
||||
|
||||
/**
|
||||
* {@link ColumnToAttributeConverter} which simply returns the given value.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
public class PassThroughColumnToAttributeConverter implements ColumnToAttributeConverter {
|
||||
|
||||
public String toAttribute(final String column) {
|
||||
return column;
|
||||
}
|
||||
|
||||
public String toColumn(final String attribute) {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.transform;
|
||||
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
import org.springframework.batch.item.file.transform.FieldSet;
|
||||
|
||||
/**
|
||||
* Interface that is used by framework to convert a Cell[] into a {@link org.springframework.batch.item.file.transform.FieldSet}.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
|
||||
public interface RowTokenizer {
|
||||
|
||||
FieldSet tokenize(Sheet sheet, String[] row);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.item.ExecutionContext;
|
||||
import org.springframework.batch.item.excel.mapping.PassThroughRowMapper;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Base class for testing Excel based item readers.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*/
|
||||
public abstract class AbstractExcelItemReaderTests {
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
protected AbstractExcelItemReader itemReader;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
this.itemReader = createExcelItemReader();
|
||||
this.itemReader.setLinesToSkip(1); //First line is column names
|
||||
this.itemReader.setResource(new ClassPathResource("org/springframework/batch/item/excel/player.xls"));
|
||||
this.itemReader.setRowMapper(new PassThroughRowMapper());
|
||||
this.itemReader.setSkippedRowsCallback(new RowCallbackHandler() {
|
||||
|
||||
public void handleRow(final Sheet sheet, final String[] row) {
|
||||
logger.info("Skipping: " + StringUtils.arrayToCommaDelimitedString(row));
|
||||
}
|
||||
});
|
||||
configureItemReader(this.itemReader);
|
||||
this.itemReader.afterPropertiesSet();
|
||||
this.itemReader.open(new ExecutionContext());
|
||||
}
|
||||
|
||||
protected void configureItemReader(AbstractExcelItemReader itemReader) {
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
this.itemReader.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readExcelFile() throws Exception {
|
||||
assertEquals(3, this.itemReader.getNumberOfSheets());
|
||||
String[] row = null;
|
||||
do {
|
||||
row = (String[]) this.itemReader.read();
|
||||
this.logger.debug("Read: "+ StringUtils.arrayToCommaDelimitedString(row));
|
||||
} while (row != null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testRequiredProperties() throws Exception {
|
||||
final AbstractExcelItemReader reader = createExcelItemReader();
|
||||
reader.afterPropertiesSet();
|
||||
}
|
||||
|
||||
protected abstract AbstractExcelItemReader createExcelItemReader();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.jxl;
|
||||
|
||||
import org.springframework.batch.item.excel.AbstractExcelItemReader;
|
||||
import org.springframework.batch.item.excel.AbstractExcelItemReaderTests;
|
||||
|
||||
/**
|
||||
* Test
|
||||
*/
|
||||
public class JxlItemReaderTest extends AbstractExcelItemReaderTests {
|
||||
|
||||
@Override
|
||||
protected AbstractExcelItemReader createExcelItemReader() {
|
||||
return new JxlItemReader();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.jxl;
|
||||
|
||||
import jxl.Cell;
|
||||
import jxl.Workbook;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
/**
|
||||
* Tests for {@link org.springframework.batch.item.excel.jxl.JxlUtils}.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
public class JxlUtilsTests {
|
||||
|
||||
private final Cell cell1 = Mockito.mock(Cell.class);
|
||||
private final Cell cell2 = Mockito.mock(Cell.class);
|
||||
private final Cell cell3 = Mockito.mock(Cell.class);
|
||||
private final Cell cell4 = Mockito.mock(Cell.class);
|
||||
|
||||
private final Workbook workbook = Mockito.mock(Workbook.class);
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Mockito.when(this.cell1.getContents()).thenReturn("foo");
|
||||
Mockito.when(this.cell2.getContents()).thenReturn(" ");
|
||||
Mockito.when(this.cell3.getContents()).thenReturn("");
|
||||
Mockito.when(this.cell4.getContents()).thenReturn(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the {@link org.springframework.batch.item.excel.jxl.JxlUtils#isEmpty( jxl.Cell)} method.
|
||||
*/
|
||||
@Test
|
||||
public void checkIfCellsAreEmpty() {
|
||||
Assert.assertFalse("Cell1 should not be empty", JxlUtils.isEmpty(this.cell1));
|
||||
Assert.assertTrue("Cell2 should be empty", JxlUtils.isEmpty(this.cell2));
|
||||
Assert.assertTrue("Cell3 should be empty", JxlUtils.isEmpty(this.cell3));
|
||||
Assert.assertTrue("Cell4 should be empty", JxlUtils.isEmpty(this.cell4));
|
||||
Assert.assertTrue("[null] should be empty", JxlUtils.isEmpty((Cell) null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the {@link JxlUtils#isEmpty( jxl.Cell[])} method.
|
||||
*/
|
||||
@Test
|
||||
public void checkIfRowIsEmpty() {
|
||||
Assert.assertTrue("[null] should be empty", JxlUtils.isEmpty((Cell[]) null));
|
||||
Assert.assertTrue("[null] should be empty", JxlUtils.isEmpty(new Cell[0]));
|
||||
Assert.assertFalse("Cell[]1 should not be empty",
|
||||
JxlUtils.isEmpty(new Cell[]{this.cell1, this.cell2, this.cell3}));
|
||||
Assert.assertTrue("Cell[]2 should be empty", JxlUtils.isEmpty(new Cell[]{this.cell2, this.cell3, null}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the {@link JxlUtils#hasSheets( jxl.Workbook)} method.
|
||||
*/
|
||||
@Test
|
||||
public void checkIfWorkbookHasSheets() {
|
||||
Assert.assertFalse("[null] doesn't have sheets.", JxlUtils.hasSheets(null));
|
||||
Mockito.when(this.workbook.getNumberOfSheets()).thenReturn(5);
|
||||
Assert.assertTrue("Workbook should have sheets.", JxlUtils.hasSheets(this.workbook));
|
||||
Mockito.when(this.workbook.getNumberOfSheets()).thenReturn(0);
|
||||
Assert.assertFalse("Workbook shouldn't have sheets.", JxlUtils.hasSheets(this.workbook));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.mapping;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.batch.item.excel.Sheet;
|
||||
import org.springframework.batch.item.excel.transform.RowTokenizer;
|
||||
import org.springframework.batch.item.file.mapping.FieldSetMapper;
|
||||
import org.springframework.batch.item.file.transform.FieldSet;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultRowMapper}.
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultRowMapperTests {
|
||||
|
||||
@Mock
|
||||
private FieldSetMapper fieldSetMapper;
|
||||
|
||||
@Mock
|
||||
private RowTokenizer rowTokenizer;
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void nullRowTokenizerShouldLeadToException() throws Exception {
|
||||
final DefaultRowMapper mapper = new DefaultRowMapper();
|
||||
mapper.setRowTokenizer(null);
|
||||
mapper.setFieldSetMapper(this.fieldSetMapper);
|
||||
mapper.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void nullFieldSetMapperShouldLeadToException() throws Exception {
|
||||
final DefaultRowMapper mapper = new DefaultRowMapper();
|
||||
mapper.setRowTokenizer(this.rowTokenizer);
|
||||
mapper.setFieldSetMapper(null);
|
||||
mapper.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void foo() throws Exception {
|
||||
final DefaultRowMapper mapper = new DefaultRowMapper();
|
||||
mapper.setRowTokenizer(this.rowTokenizer);
|
||||
mapper.setFieldSetMapper(this.fieldSetMapper);
|
||||
final FieldSet fs = Mockito.mock(FieldSet.class);
|
||||
final Object result = new Object();
|
||||
Mockito.when(this.rowTokenizer.tokenize(any(Sheet.class), any(String[].class))).thenReturn(fs);
|
||||
Mockito.when(this.fieldSetMapper.mapFieldSet(fs)).thenReturn(result);
|
||||
Assert.assertEquals(result, mapper.mapRow(null, null, 0));
|
||||
Mockito.verify(this.rowTokenizer, Mockito.times(1)).tokenize(any(Sheet.class), any(String[].class));
|
||||
Mockito.verify(this.fieldSetMapper, Mockito.times(1)).mapFieldSet(fs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.mapping;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Tests for {@link PassThroughRowMapper}.
|
||||
*
|
||||
* @author Marten Deinum
|
||||
*
|
||||
*/
|
||||
public class PassThroughRowMapperTests {
|
||||
|
||||
private final PassThroughRowMapper rowMapper = new PassThroughRowMapper();
|
||||
|
||||
@Test
|
||||
public void mapRowShouldReturnSameValues() throws Exception {
|
||||
final String[] row = new String[] { "foo", "bar", "baz" };
|
||||
|
||||
assertArrayEquals(row, this.rowMapper.mapRow(null, row, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapRowShouldReturnNull() throws Exception {
|
||||
assertNull(this.rowMapper.mapRow(null, null, 0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.poi;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.item.excel.AbstractExcelItemReader;
|
||||
import org.springframework.batch.item.excel.AbstractExcelItemReaderTests;
|
||||
|
||||
public class PoiItemReaderXlsTests extends AbstractExcelItemReaderTests {
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private PoiItemReader itemReader;
|
||||
|
||||
@Override
|
||||
protected AbstractExcelItemReader createExcelItemReader() {
|
||||
return new PoiItemReader();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.poi;
|
||||
|
||||
import org.springframework.batch.item.excel.AbstractExcelItemReader;
|
||||
import org.springframework.batch.item.excel.AbstractExcelItemReaderTests;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
public class PoiItemReaderXlsxTests extends AbstractExcelItemReaderTests {
|
||||
|
||||
@Override
|
||||
protected void configureItemReader(AbstractExcelItemReader itemReader) {
|
||||
itemReader.setResource(new ClassPathResource("org/springframework/batch/item/excel/player.xlsx"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractExcelItemReader createExcelItemReader() {
|
||||
return new PoiItemReader();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.transform;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class MappingColumnToAttributeConverterTests {
|
||||
|
||||
private final MappingColumnToAttributeConverter converter = new MappingColumnToAttributeConverter();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
final Map<String, String> mappings = new HashMap<String, String>();
|
||||
mappings.put("foo", "bar1");
|
||||
mappings.put("baz", "bar2");
|
||||
mappings.put("with spaces", "noSpaces");
|
||||
this.converter.setMappings(mappings);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertColumnToAttribtue() {
|
||||
assertEquals("bar1", this.converter.toAttribute("foo"));
|
||||
assertEquals("noSpaces", this.converter.toAttribute("with spaces"));
|
||||
assertEquals("not existing", this.converter.toAttribute("not existing"));
|
||||
assertNull(this.converter.toAttribute(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertAttributeToColumn() {
|
||||
assertEquals("baz", this.converter.toColumn("bar2"));
|
||||
assertEquals("with spaces", this.converter.toColumn("noSpaces"));
|
||||
assertEquals("not existing", this.converter.toColumn("not existing"));
|
||||
assertNull(this.converter.toAttribute(null));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2011-2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.batch.item.excel.transform;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class PassThroughColumnToAttributeConverterTests {
|
||||
|
||||
private final PassThroughColumnToAttributeConverter converter = new PassThroughColumnToAttributeConverter();
|
||||
|
||||
@Test
|
||||
public void columnNameShouldRemainTheSame() {
|
||||
final String column = "column";
|
||||
assertEquals(column, this.converter.toAttribute(column));
|
||||
assertNull(this.converter.toAttribute(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void attributeNameShouldRemainTheSame() {
|
||||
final String attribute = "attribute";
|
||||
assertEquals(attribute, this.converter.toColumn(attribute));
|
||||
assertNull(this.converter.toColumn(null));
|
||||
}
|
||||
|
||||
}
|
||||
21
spring-batch-excel/src/test/resources/log4j.xml
Normal file
21
spring-batch-excel/src/test/resources/log4j.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
<log4j:configuration debug="true"
|
||||
xmlns:log4j='http://jakarta.apache.org/log4j/'>
|
||||
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%d %p %t [%c] - %m %n"/>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<category name="org.springframework.batch">
|
||||
<level value="DEBUG" />
|
||||
</category>
|
||||
|
||||
<root>
|
||||
<level value="INFO"/>
|
||||
<appender-ref ref="console"/>
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user