blob: e6195ba775adfde908756ec58007d6b741775221 [file] [log] [blame]
/*
* 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.directory.studio.ldapbrowser.core.jobs;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.directory.api.ldap.model.constants.SchemaConstants;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.schema.AttributeType;
import org.apache.directory.studio.common.core.jobs.StudioProgressMonitor;
import org.apache.directory.studio.connection.core.Connection;
import org.apache.directory.studio.connection.core.jobs.StudioConnectionRunnableWithProgress;
import org.apache.directory.studio.ldapbrowser.core.BrowserCoreConstants;
import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
import org.apache.directory.studio.ldapbrowser.core.BrowserCorePlugin;
import org.apache.directory.studio.ldapbrowser.core.model.AttributeDescription;
import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
import org.apache.directory.studio.ldapbrowser.core.model.SearchParameter;
import org.apache.directory.studio.ldapbrowser.core.utils.JNDIUtils;
import org.apache.directory.studio.ldapbrowser.core.utils.Utils;
import org.apache.directory.studio.ldifparser.LdifUtils;
import org.apache.directory.studio.ldifparser.model.LdifEnumeration;
import org.apache.directory.studio.ldifparser.model.container.LdifContainer;
import org.apache.directory.studio.ldifparser.model.container.LdifContentRecord;
import org.apache.directory.studio.ldifparser.model.lines.LdifAttrValLine;
import org.eclipse.core.runtime.Preferences;
/**
* Runnable to export directory content to an CSV file.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class ExportCsvRunnable implements StudioConnectionRunnableWithProgress
{
/** The filename of the CSV file. */
private String exportCsvFilename;
/** The browser connection. */
private IBrowserConnection browserConnection;
/** The search parameter. */
private SearchParameter searchParameter;
/** The export dn flag. */
private boolean exportDn;
/**
* Creates a new instance of ExportCsvRunnable.
*
* @param exportCsvFilename the filename of the csv file
* @param browserConnection the browser connection
* @param searchParameter the search parameter
* @param exportDn true to export the Dn
*/
public ExportCsvRunnable( String exportCsvFilename, IBrowserConnection browserConnection,
SearchParameter searchParameter, boolean exportDn )
{
this.exportCsvFilename = exportCsvFilename;
this.browserConnection = browserConnection;
this.searchParameter = searchParameter;
this.exportDn = exportDn;
}
/**
* {@inheritDoc}
*/
public Connection[] getConnections()
{
return new Connection[]
{ browserConnection.getConnection() };
}
/**
* {@inheritDoc}
*/
public String getName()
{
return BrowserCoreMessages.jobs__export_csv_name;
}
/**
* {@inheritDoc}
*/
public Object[] getLockedObjects()
{
return new Object[]
{ browserConnection.getUrl() + "_" + DigestUtils.shaHex( exportCsvFilename ) }; //$NON-NLS-1$
}
/**
* {@inheritDoc}
*/
public String getErrorMessage()
{
return BrowserCoreMessages.jobs__export_cvs_error;
}
/**
* {@inheritDoc}
*/
public void run( StudioProgressMonitor monitor )
{
monitor.beginTask( BrowserCoreMessages.jobs__export_csv_task, 2 );
monitor.reportProgress( " " ); //$NON-NLS-1$
monitor.worked( 1 );
Preferences coreStore = BrowserCorePlugin.getDefault().getPluginPreferences();
String attributeDelimiter = coreStore.getString( BrowserCoreConstants.PREFERENCE_FORMAT_CSV_ATTRIBUTEDELIMITER );
String valueDelimiter = coreStore.getString( BrowserCoreConstants.PREFERENCE_FORMAT_CSV_VALUEDELIMITER );
String quoteCharacter = coreStore.getString( BrowserCoreConstants.PREFERENCE_FORMAT_CSV_QUOTECHARACTER );
String lineSeparator = coreStore.getString( BrowserCoreConstants.PREFERENCE_FORMAT_CSV_LINESEPARATOR );
String encoding = coreStore.getString( BrowserCoreConstants.PREFERENCE_FORMAT_CSV_ENCODING );
int binaryEncoding = coreStore.getInt( BrowserCoreConstants.PREFERENCE_FORMAT_CSV_BINARYENCODING );
String[] exportAttributes = this.searchParameter.getReturningAttributes();
try
{
// open file
FileOutputStream fos = new FileOutputStream( exportCsvFilename );
OutputStreamWriter osw = new OutputStreamWriter( fos, encoding );
BufferedWriter bufferedWriter = new BufferedWriter( osw );
// header
if ( this.exportDn )
{
bufferedWriter.write( "dn" ); //$NON-NLS-1$
if ( exportAttributes == null || exportAttributes.length > 0 )
bufferedWriter.write( attributeDelimiter );
}
for ( int i = 0; i < exportAttributes.length; i++ )
{
bufferedWriter.write( exportAttributes[i] );
if ( i + 1 < exportAttributes.length )
bufferedWriter.write( attributeDelimiter );
}
bufferedWriter.write( BrowserCoreConstants.LINE_SEPARATOR );
// export
int count = 0;
exportToCsv( browserConnection, searchParameter, bufferedWriter, count, monitor, exportAttributes,
attributeDelimiter, valueDelimiter, quoteCharacter, lineSeparator, encoding, binaryEncoding, exportDn );
// close file
bufferedWriter.close();
osw.close();
fos.close();
}
catch ( Exception e )
{
monitor.reportError( e );
}
}
/**
* Exports to CSV.
*
* @param browserConnection the browser connection
* @param searchParameter the search parameter
* @param bufferedWriter the buffered writer
* @param count the count
* @param monitor the monitor
* @param attributes the attributes
* @param attributeDelimiter the attribute delimiter
* @param valueDelimiter the value delimiter
* @param quoteCharacter the quote character
* @param lineSeparator the line separator
* @param encoding the encoding
* @param binaryEncoding the binary encoding
* @param exportDn the export dn
*
* @throws IOException Signals that an I/O exception has occurred.
*/
private static void exportToCsv( IBrowserConnection browserConnection, SearchParameter searchParameter,
BufferedWriter bufferedWriter, int count, StudioProgressMonitor monitor, String[] attributes,
String attributeDelimiter, String valueDelimiter, String quoteCharacter, String lineSeparator, String encoding,
int binaryEncoding, boolean exportDn ) throws IOException
{
try
{
LdifEnumeration enumeration = ExportLdifRunnable.search( browserConnection, searchParameter, monitor );
while ( !monitor.isCanceled() && !monitor.errorsReported() && enumeration.hasNext() )
{
LdifContainer container = enumeration.next();
if ( container instanceof LdifContentRecord )
{
LdifContentRecord record = ( LdifContentRecord ) container;
bufferedWriter.write( recordToCsv( browserConnection, record, attributes, attributeDelimiter,
valueDelimiter, quoteCharacter, lineSeparator, encoding, binaryEncoding, exportDn ) );
count++;
monitor.reportProgress( BrowserCoreMessages.bind( BrowserCoreMessages.jobs__export_progress,
new String[]
{ Integer.toString( count ) } ) );
}
}
}
catch ( LdapException ce )
{
int ldapStatusCode = JNDIUtils.getLdapStatusCode( ce );
if ( ldapStatusCode == 3 || ldapStatusCode == 4 || ldapStatusCode == 11 )
{
// nothing
}
else
{
monitor.reportError( ce );
}
}
}
/**
* Transforms an LDIF rRecord to CSV.
*
* @param browserConnection the browser connection
* @param record the record
* @param attributes the attributes
* @param attributeDelimiter the attribute delimiter
* @param valueDelimiter the value delimiter
* @param quoteCharacter the quote character
* @param lineSeparator the line separator
* @param encoding the encoding
* @param binaryEncoding the binary encoding
* @param exportDn the export dn
*
* @return the string
*/
private static String recordToCsv( IBrowserConnection browserConnection, LdifContentRecord record,
String[] attributes, String attributeDelimiter, String valueDelimiter, String quoteCharacter,
String lineSeparator, String encoding, int binaryEncoding, boolean exportDn )
{
// group multi-valued attributes
Map<String, String> attributeMap = getAttributeMap( browserConnection, record, valueDelimiter, encoding,
binaryEncoding );
// print attributes
StringBuffer sb = new StringBuffer();
if ( exportDn )
{
String value = record.getDnLine().getValueAsString();
appendValue( quoteCharacter, sb, value );
if ( attributes == null || attributes.length > 0 )
sb.append( attributeDelimiter );
}
for ( int i = 0; i < attributes.length; i++ )
{
String attributeName = attributes[i];
AttributeDescription ad = new AttributeDescription( attributeName );
String oidString = ad.toOidString( browserConnection.getSchema() );
if ( attributeMap.containsKey( oidString ) )
{
String value = attributeMap.get( oidString );
AttributeType type = browserConnection.getSchema().getAttributeTypeDescription( attributeName );
if ( SchemaConstants.POSTAL_ADDRESS_SYNTAX.equals( type.getSyntaxOid() ) )
{
value = Utils.decodePostalAddress( value, lineSeparator );
}
appendValue( quoteCharacter, sb, value );
}
// delimiter
if ( i + 1 < attributes.length )
{
sb.append( attributeDelimiter );
}
}
sb.append( lineSeparator );
return sb.toString();
}
private static void appendValue( String quoteCharacter, StringBuffer sb, String value )
{
// escape quote character
value = value.replaceAll( quoteCharacter, quoteCharacter + quoteCharacter );
// prefix values starting with '=' with a single quote to avoid interpretation as formula
if ( value.startsWith( "=" ) )
{
value = "'" + value;
}
// always quote
sb.append( quoteCharacter );
sb.append( value );
sb.append( quoteCharacter );
}
/**
* Gets the attribute map.
*
* @param browserConnection the browser connection
* @param record the record
* @param valueDelimiter the value delimiter
* @param encoding the encoding
* @param binaryEncoding the binary encoding
*
* @return the attribute map
*/
static Map<String, String> getAttributeMap( IBrowserConnection browserConnection, LdifContentRecord record,
String valueDelimiter, String encoding, int binaryEncoding )
{
Map<String, String> attributeMap = new HashMap<String, String>();
LdifAttrValLine[] lines = record.getAttrVals();
for ( int i = 0; i < lines.length; i++ )
{
String attributeName = lines[i].getUnfoldedAttributeDescription();
if ( browserConnection != null )
{
// convert attributeName to oid
AttributeDescription ad = new AttributeDescription( attributeName );
attributeName = ad.toOidString( browserConnection.getSchema() );
}
String value = lines[i].getValueAsString();
if ( !Charset.forName( encoding ).newEncoder().canEncode( value ) )
{
if ( binaryEncoding == BrowserCoreConstants.BINARYENCODING_BASE64 )
{
value = LdifUtils.base64encode( lines[i].getValueAsBinary() );
}
else if ( binaryEncoding == BrowserCoreConstants.BINARYENCODING_HEX )
{
value = LdifUtils.hexEncode( lines[i].getValueAsBinary() );
}
else
{
value = BrowserCoreConstants.BINARY;
}
if ( attributeMap.containsKey( attributeName ) )
{
String oldValue = ( String ) attributeMap.get( attributeName );
attributeMap.put( attributeName, oldValue + valueDelimiter + value );
}
else
{
attributeMap.put( attributeName, value );
}
}
else
{
if ( attributeMap.containsKey( attributeName ) )
{
String oldValue = ( String ) attributeMap.get( attributeName );
attributeMap.put( attributeName, oldValue + valueDelimiter + value );
}
else
{
attributeMap.put( attributeName, value );
}
}
}
return attributeMap;
}
}