directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fel...@apache.org
Subject svn commit: r592082 [5/20] - in /directory/sandbox/felixk/studio-ldapbrowser-core: ./ META-INF/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/directory/ src/main/java/org/apache/directory/studio/ sr...
Date Mon, 05 Nov 2007 16:52:07 GMT
Added: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportCsvJob.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportCsvJob.java?rev=592082&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportCsvJob.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportCsvJob.java Mon Nov  5 08:51:43 2007
@@ -0,0 +1,398 @@
+/*
+ *  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.studio.connection.core.Connection;
+import org.apache.directory.studio.connection.core.StudioProgressMonitor;
+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.ConnectionException;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.ISearch;
+import org.apache.directory.studio.ldapbrowser.core.model.ReferralException;
+import org.apache.directory.studio.ldapbrowser.core.model.SearchParameter;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection.ReferralHandlingMethod;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.LdifEnumeration;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.container.LdifContainer;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.container.LdifContentRecord;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.lines.LdifAttrValLine;
+import org.apache.directory.studio.ldapbrowser.core.utils.LdifUtils;
+import org.eclipse.core.runtime.Preferences;
+
+
+/**
+ * Job to export directory content to an CSV file.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ExportCsvJob extends AbstractEclipseJob
+{
+
+    /** 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 ExportCsvJob.
+     * 
+     * @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 ExportCsvJob( String exportCsvFilename, IBrowserConnection browserConnection,
+        SearchParameter searchParameter, boolean exportDn )
+    {
+        this.exportCsvFilename = exportCsvFilename;
+        this.browserConnection = browserConnection;
+        this.searchParameter = searchParameter;
+        this.exportDn = exportDn;
+
+        setName( BrowserCoreMessages.jobs__export_csv_name );
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getConnections()
+     */
+    protected Connection[] getConnections()
+    {
+        return new Connection[]
+            { browserConnection.getConnection() };
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getLockedObjects()
+     */
+    protected Object[] getLockedObjects()
+    {
+        return new Object[]
+            { browserConnection.getUrl() + "_" + DigestUtils.shaHex( exportCsvFilename ) };
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#executeAsyncJob(org.apache.directory.studio.connection.core.StudioProgressMonitor)
+     */
+    protected void executeAsyncJob( 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.
+     * @throws ConnectionException the connection exception
+     */
+    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, ConnectionException
+    {
+        try
+        {
+            LdifEnumeration enumeration = ExportLdifJob.search( browserConnection, searchParameter, monitor );
+            while ( !monitor.isCanceled() && enumeration.hasNext( monitor ) )
+            {
+                LdifContainer container = enumeration.next( monitor );
+
+                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 ( ConnectionException ce )
+        {
+
+            if ( ce.getLdapStatusCode() == 3 || ce.getLdapStatusCode() == 4 || ce.getLdapStatusCode() == 11 )
+            {
+                // nothing
+            }
+            else if ( ce instanceof ReferralException )
+            {
+
+                if ( searchParameter.getReferralsHandlingMethod() == ReferralHandlingMethod.FOLLOW )
+                {
+                    ReferralException re = ( ReferralException ) ce;
+                    ISearch[] referralSearches = re.getReferralSearches();
+                    for ( int i = 0; i < referralSearches.length; i++ )
+                    {
+                        ISearch referralSearch = referralSearches[i];
+
+                        // export recursive
+                        exportToCsv( referralSearch.getBrowserConnection(), referralSearch.getSearchParameter(),
+                            bufferedWriter, count, monitor, attributes, attributeDelimiter, valueDelimiter,
+                            quoteCharacter, lineSeparator, encoding, binaryEncoding, exportDn );
+                    }
+                }
+            }
+            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 )
+        {
+            sb.append( quoteCharacter );
+            sb.append( record.getDnLine().getValueAsString() );
+            sb.append( quoteCharacter );
+
+            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 );
+
+                // escape
+                value = value.replaceAll( quoteCharacter, quoteCharacter + quoteCharacter );
+
+                // always quote
+                sb.append( quoteCharacter );
+                sb.append( value );
+                sb.append( quoteCharacter );
+            }
+
+            // delimiter
+            if ( i + 1 < attributes.length )
+            {
+                sb.append( attributeDelimiter );
+            }
+
+        }
+        sb.append( lineSeparator );
+
+        return sb.toString();
+    }
+
+
+    /**
+     * 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;
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getErrorMessage()
+     */
+    protected String getErrorMessage()
+    {
+        return BrowserCoreMessages.jobs__export_cvs_error;
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportCsvJob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportDsmlJob.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportDsmlJob.java?rev=592082&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportDsmlJob.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportDsmlJob.java Mon Nov  5 08:51:43 2007
@@ -0,0 +1,472 @@
+/*
+ *  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.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.directory.shared.asn1.codec.DecoderException;
+import org.apache.directory.shared.ldap.codec.AttributeValueAssertion;
+import org.apache.directory.shared.ldap.codec.LdapConstants;
+import org.apache.directory.shared.ldap.codec.search.AndFilter;
+import org.apache.directory.shared.ldap.codec.search.AttributeValueAssertionFilter;
+import org.apache.directory.shared.ldap.codec.search.ExtensibleMatchFilter;
+import org.apache.directory.shared.ldap.codec.search.Filter;
+import org.apache.directory.shared.ldap.codec.search.NotFilter;
+import org.apache.directory.shared.ldap.codec.search.OrFilter;
+import org.apache.directory.shared.ldap.codec.search.PresentFilter;
+import org.apache.directory.shared.ldap.codec.search.SearchRequest;
+import org.apache.directory.shared.ldap.codec.search.SubstringFilter;
+import org.apache.directory.shared.ldap.filter.BranchNode;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.ExtensibleNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.filter.FilterParserImpl;
+import org.apache.directory.shared.ldap.filter.PresenceNode;
+import org.apache.directory.shared.ldap.filter.SimpleNode;
+import org.apache.directory.shared.ldap.filter.SubstringNode;
+import org.apache.directory.shared.ldap.message.ScopeEnum;
+import org.apache.directory.studio.connection.core.Connection;
+import org.apache.directory.studio.connection.core.StudioProgressMonitor;
+import org.apache.directory.studio.dsmlv2.engine.Dsmlv2Engine;
+import org.apache.directory.studio.dsmlv2.request.SearchRequestDsml;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+import org.apache.directory.studio.ldapbrowser.core.model.Control;
+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.model.IBrowserConnection.AliasDereferencingMethod;
+import org.apache.directory.studio.ldapbrowser.core.model.ISearch.SearchScope;
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+
+/**
+ * This class implements a Job for Exporting a part of a LDAP Server into a DSML File.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ExportDsmlJob extends AbstractEclipseJob
+{
+    /** The name of the DSML file to export to */
+    private String exportDsmlFilename;
+
+    /** The connection to use */
+    private IBrowserConnection browserConnection;
+
+    /** The Search Parameter of the export*/
+    private SearchParameter searchParameter;
+
+
+    /**
+     * Creates a new instance of ExportDsmlJob.
+     *
+     * @param exportDsmlFilename
+     *          the name of the DSML file to export to
+     * @param connection
+     *          the connection to use
+     * @param searchParameter
+     *          the Search Parameter of the export
+     */
+    public ExportDsmlJob( String exportDsmlFilename, IBrowserConnection connection, SearchParameter searchParameter )
+    {
+        this.exportDsmlFilename = exportDsmlFilename;
+        this.browserConnection = connection;
+        this.searchParameter = searchParameter;
+
+        setName( BrowserCoreMessages.jobs__export_dsml_name );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getConnections()
+     */
+    protected Connection[] getConnections()
+    {
+        return new Connection[]
+            { browserConnection.getConnection() };
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getLockedObjects()
+     */
+    protected Object[] getLockedObjects()
+    {
+        List<String> l = new ArrayList<String>();
+        l.add( browserConnection.getUrl() + "_" + DigestUtils.shaHex( exportDsmlFilename ) );
+        return l.toArray();
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#executeAsyncJob(org.apache.directory.studio.ldapbrowser.core.jobs.ExtendedProgressMonitor)
+     */
+    protected void executeAsyncJob( StudioProgressMonitor monitor )
+    {
+        monitor.beginTask( BrowserCoreMessages.jobs__export_dsml_task, 2 );
+        monitor.reportProgress( " " ); //$NON-NLS-1$
+        monitor.worked( 1 );
+
+        try
+        {
+            SearchRequest searchRequest = new SearchRequest();
+            searchRequest.setProtocolOP( searchRequest );
+
+            // DN
+            searchRequest.setBaseObject( searchParameter.getSearchBase( ) );
+
+            // Scope
+            SearchScope scope = searchParameter.getScope();
+            if ( scope == SearchScope.OBJECT )
+            {
+                searchRequest.setScope( ScopeEnum.BASE_OBJECT );
+            }
+            else if ( scope == SearchScope.ONELEVEL )
+            {
+                searchRequest.setScope( ScopeEnum.SINGLE_LEVEL );
+            }
+            else if ( scope == SearchScope.SUBTREE )
+            {
+                searchRequest.setScope( ScopeEnum.WHOLE_SUBTREE );
+            }
+
+            // DerefAliases
+            AliasDereferencingMethod derefAliases = searchParameter.getAliasesDereferencingMethod();
+            switch ( derefAliases )
+            {
+                case ALWAYS:
+                    searchRequest.setDerefAliases( LdapConstants.DEREF_ALWAYS );
+                    break;
+                case FINDING:
+                    searchRequest.setDerefAliases( LdapConstants.DEREF_FINDING_BASE_OBJ );
+                    break;
+                case NEVER:
+                    searchRequest.setDerefAliases( LdapConstants.NEVER_DEREF_ALIASES );
+                    break;
+                case SEARCH:
+                    searchRequest.setDerefAliases( LdapConstants.DEREF_IN_SEARCHING );
+                    break;
+                default:
+                    break;
+            }
+
+            // Time Limit
+            int timeLimit = searchParameter.getTimeLimit();
+            if ( timeLimit != 0 )
+            {
+                searchRequest.setTimeLimit( timeLimit );
+            }
+
+            // Size Limit
+            int countLimit = searchParameter.getCountLimit();
+            if ( countLimit != 0 )
+            {
+                searchRequest.setSizeLimit( countLimit );
+            }
+
+            // Filter
+            searchRequest.setFilter( convertToSharedLdapFilter( searchParameter.getFilter() ) );
+
+            // Attributes
+            String[] returningAttributes = searchParameter.getReturningAttributes();
+            for ( int i = 0; i < returningAttributes.length; i++ )
+            {
+                searchRequest.addAttribute( returningAttributes[i] );
+            }
+
+            // Controls
+            List<org.apache.directory.shared.ldap.codec.Control> sharedLdapControls = convertToSharedLdapControls( searchParameter
+                .getControls() );
+            for ( int i = 0; i < sharedLdapControls.size(); i++ )
+            {
+                searchRequest.addControl( sharedLdapControls.get( i ) );
+            }
+
+            // Executing the request
+            Document xmlRequest = DocumentHelper.createDocument();
+            Element rootElement = xmlRequest.addElement( "batchRequest" );
+            SearchRequestDsml searchRequestDsml = new SearchRequestDsml( searchRequest );
+            searchRequestDsml.toDsml( rootElement );
+            Dsmlv2Engine engine = new Dsmlv2Engine( browserConnection.getConnection().getHost(), browserConnection
+                .getConnection().getPort(), browserConnection.getConnection().getBindPrincipal(), browserConnection
+                .getConnection().getBindPassword() );
+            String response = engine.processDSML( xmlRequest.asXML() );
+
+            // Saving the response
+            FileOutputStream fout = new FileOutputStream( exportDsmlFilename );
+            new PrintStream( fout ).println( response );
+            fout.close();
+        }
+        catch ( Exception e )
+        {
+            monitor.reportError( e );
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getErrorMessage()
+     */
+    protected String getErrorMessage()
+    {
+        return BrowserCoreMessages.jobs__export_dsml_error;
+    }
+
+
+    /**
+     * Converts a String filter into a Shared LDAP Filter.
+     *
+     * @param filter
+     *      the filter String to convert
+     * @return
+     *      the corresponding Shared LDAP Filter
+     * @throws ParseException 
+     * @throws IOException 
+     * @throws DecoderException 
+     */
+    public static Filter convertToSharedLdapFilter( String filter ) throws IOException, ParseException,
+        DecoderException
+    {
+        FilterParser filterParser = new FilterParserImpl();
+
+        ExprNode exprNode = filterParser.parse( filter );
+
+        return convertToSharedLdapFilter( exprNode );
+    }
+
+
+    /**
+     * Converts a ExprNode Filter Model into a Shared LDAP Model.
+     *
+     * @param exprNode
+     *      the filter
+     * @return
+     *      the corresponding filter in the Shared LDAP Model
+     * @throws DecoderException 
+     */
+    public static Filter convertToSharedLdapFilter( ExprNode exprNode ) throws DecoderException
+    {
+        Filter sharedLdapFilter = null;
+
+        if ( exprNode instanceof BranchNode )
+        {
+            BranchNode branchNode = ( BranchNode ) exprNode;
+
+            switch ( branchNode.getOperator() )
+            {
+                case AND:
+                    AndFilter andFilter = new AndFilter();
+                    sharedLdapFilter = andFilter;
+
+                    List<Filter> andFilters = iterateOnFilters( branchNode.getChildren() );
+                    for ( int i = 0; i < andFilters.size(); i++ )
+                    {
+                        andFilter.addFilter( andFilters.get( i ) );
+                    }
+                    break;
+
+                case OR:
+                    OrFilter orFilter = new OrFilter();
+                    sharedLdapFilter = orFilter;
+
+                    List<Filter> orFilters = iterateOnFilters( branchNode.getChildren() );
+                    for ( int i = 0; i < orFilters.size(); i++ )
+                    {
+                        orFilter.addFilter( orFilters.get( i ) );
+                    }
+                    break;
+                case NOT:
+                    NotFilter notFilter = new NotFilter();
+                    sharedLdapFilter = notFilter;
+
+                    List<Filter> notFilters = iterateOnFilters( branchNode.getChildren() );
+                    notFilter.setNotFilter( notFilters.get( 0 ) );
+                    break;
+            }
+        }
+        else if ( exprNode instanceof PresenceNode )
+        {
+            PresenceNode presenceNode = ( PresenceNode ) exprNode;
+
+            PresentFilter presentFilter = new PresentFilter();
+            sharedLdapFilter = presentFilter;
+
+            presentFilter.setAttributeDescription( presenceNode.getAttribute() );
+        }
+        else if ( exprNode instanceof SimpleNode )
+        {
+            SimpleNode simpleNode = ( SimpleNode ) exprNode;
+
+            switch ( simpleNode.getAssertionType() )
+            {
+                case APPROXIMATE:
+                    AttributeValueAssertionFilter approxMatchFilter = createAttributeValueAssertionFilter( simpleNode,
+                        LdapConstants.APPROX_MATCH_FILTER );
+                    sharedLdapFilter = approxMatchFilter;
+                    break;
+
+                case EQUALITY:
+                    AttributeValueAssertionFilter equalityMatchFilter = createAttributeValueAssertionFilter(
+                        simpleNode, LdapConstants.EQUALITY_MATCH_FILTER );
+                    sharedLdapFilter = equalityMatchFilter;
+                    break;
+
+                case GREATEREQ:
+                    AttributeValueAssertionFilter greaterOrEqualFilter = createAttributeValueAssertionFilter(
+                        simpleNode, LdapConstants.GREATER_OR_EQUAL_FILTER );
+                    sharedLdapFilter = greaterOrEqualFilter;
+                    break;
+
+                case LESSEQ:
+                    AttributeValueAssertionFilter lessOrEqualFilter = createAttributeValueAssertionFilter( simpleNode,
+                        LdapConstants.LESS_OR_EQUAL_FILTER );
+                    sharedLdapFilter = lessOrEqualFilter;
+                    break;
+            }
+        }
+        else if ( exprNode instanceof ExtensibleNode )
+        {
+            ExtensibleNode extensibleNode = ( ExtensibleNode ) exprNode;
+
+            ExtensibleMatchFilter extensibleMatchFilter = new ExtensibleMatchFilter();
+            sharedLdapFilter = extensibleMatchFilter;
+
+            extensibleMatchFilter.setDnAttributes( extensibleNode.dnAttributes() );
+            extensibleMatchFilter.setMatchingRule( extensibleNode.getMatchingRuleId() );
+            extensibleMatchFilter.setMatchValue( extensibleNode.getValue() );
+            extensibleMatchFilter.setType( extensibleNode.getAttribute() );
+        }
+        else if ( exprNode instanceof SubstringNode )
+        {
+            SubstringNode substringNode = ( SubstringNode ) exprNode;
+
+            SubstringFilter substringFilter = new SubstringFilter();
+            sharedLdapFilter = substringFilter;
+
+            substringFilter.setType( substringNode.getAttribute() );
+            substringFilter.setInitialSubstrings( substringNode.getInitial() );
+            substringFilter.setFinalSubstrings( substringNode.getFinal() );
+            List anys = substringNode.getAny();
+            for ( int i = 0; i < anys.size(); i++ )
+            {
+                substringFilter.addAnySubstrings( ( String ) anys.get( i ) );
+            }
+        }
+
+        return sharedLdapFilter;
+    }
+
+
+    /**
+     * Iterates the conversion on the given List of notdes.
+     *
+     * @param filters
+     *      the List of nodes to convert
+     * @return
+     *      an array containing the conversion for each Ldap Filter into its Shared LDAP Model
+     * @throws DecoderException 
+     */
+    private static List<Filter> iterateOnFilters( List<ExprNode> filters ) throws DecoderException
+    {
+        List<Filter> filtersList = new ArrayList<Filter>();
+
+        for ( int c = 0; c < filters.size(); c++ )
+        {
+            filtersList.add( convertToSharedLdapFilter( filters.get( c ) ) );
+        }
+
+        return filtersList;
+    }
+
+
+    /**
+     * Create and returns an Attribute Value Assertion Filter from the given SimpleNode ant the given type.
+     *
+     * @param node
+     *      the filter to convert
+     * @param type
+     *      the type of the Attribute Value Assertion Filter
+     * @return
+     *      the corresponding Attribute Value Assertion Filter
+     */
+    private static AttributeValueAssertionFilter createAttributeValueAssertionFilter( SimpleNode node, int type )
+    {
+        AttributeValueAssertionFilter avaFilter = new AttributeValueAssertionFilter( type );
+
+        AttributeValueAssertion assertion = new AttributeValueAssertion();
+        avaFilter.setAssertion( assertion );
+        assertion.setAttributeDesc( node.getAttribute() );
+        assertion.setAssertionValue( node.getValue() );
+
+        return avaFilter;
+    }
+
+
+    /**
+     * Converts the given array of Controls into their corresponding representation in the Shared LDAP Model.
+     *
+     * @param controls
+     *      the array of Controls to convert
+     * @return
+     *      a List of Shared LDAP Control Objects corresponding to the given Controls
+     */
+    private List<org.apache.directory.shared.ldap.codec.Control> convertToSharedLdapControls( Control[] controls )
+    {
+        List<org.apache.directory.shared.ldap.codec.Control> returnList = new ArrayList<org.apache.directory.shared.ldap.codec.Control>();
+
+        if ( controls != null )
+        {
+            for ( int i = 0; i < controls.length; i++ )
+            {
+                returnList.add( convertToSharedLDAP( controls[i] ) );
+            }
+        }
+
+        return returnList;
+    }
+
+
+    /**
+     * Converts the given Control into its corresponding representation in the Shared LDAP Model.
+     *
+     * @param control
+     *      the Control to convert
+     * @return
+     *      the corresponding Control in the Shared LDAP Model
+     */
+    private static org.apache.directory.shared.ldap.codec.Control convertToSharedLDAP( Control control )
+    {
+        org.apache.directory.shared.ldap.codec.Control sharedLdapControl = new org.apache.directory.shared.ldap.codec.Control();
+
+        sharedLdapControl.setControlType( control.getOid() );
+        sharedLdapControl.setControlValue( control.getControlValue() );
+
+        return sharedLdapControl;
+    }
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportDsmlJob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifJob.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifJob.java?rev=592082&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifJob.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifJob.java Mon Nov  5 08:51:43 2007
@@ -0,0 +1,303 @@
+/*
+ *  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.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.SearchResult;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.studio.connection.core.Connection;
+import org.apache.directory.studio.connection.core.StudioProgressMonitor;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+import org.apache.directory.studio.ldapbrowser.core.model.ConnectionException;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.ISearch;
+import org.apache.directory.studio.ldapbrowser.core.model.ReferralException;
+import org.apache.directory.studio.ldapbrowser.core.model.SearchParameter;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection.ReferralHandlingMethod;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.LdifEnumeration;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.container.LdifContainer;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.container.LdifContentRecord;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.lines.LdifAttrValLine;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.lines.LdifDnLine;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.lines.LdifSepLine;
+import org.apache.directory.studio.ldapbrowser.core.utils.AttributeComparator;
+import org.apache.directory.studio.ldapbrowser.core.utils.JNDIUtils;
+
+
+/**
+ * Job to export directory content to an LDIF file.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ExportLdifJob extends AbstractEclipseJob
+{
+
+    /** The filename of the LDIF file. */
+    private String exportLdifFilename;
+
+    /** The browser connection. */
+    private IBrowserConnection browserConnection;
+
+    /** The search parameter. */
+    private SearchParameter searchParameter;
+
+
+    /**
+     * Creates a new instance of ExportLdifJob.
+     * 
+     * @param exportLdifFilename the filename of the LDIF file
+     * @param browserConnection the browser connection
+     * @param searchParameter the search parameter
+     */
+    public ExportLdifJob( String exportLdifFilename, IBrowserConnection browserConnection, SearchParameter searchParameter )
+    {
+        this.exportLdifFilename = exportLdifFilename;
+        this.browserConnection = browserConnection;
+        this.searchParameter = searchParameter;
+
+        setName( BrowserCoreMessages.jobs__export_ldif_name );
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getConnections()
+     */
+    protected Connection[] getConnections()
+    {
+        return new Connection[]
+            { browserConnection.getConnection() };
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getLockedObjects()
+     */
+    protected Object[] getLockedObjects()
+    {
+        List<Object> l = new ArrayList<Object>();
+        l.add( browserConnection.getUrl() + "_" + DigestUtils.shaHex( exportLdifFilename ) );
+        return l.toArray();
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#executeAsyncJob(org.apache.directory.studio.connection.core.StudioProgressMonitor)
+     */
+    protected void executeAsyncJob( StudioProgressMonitor monitor )
+    {
+        monitor.beginTask( BrowserCoreMessages.jobs__export_ldif_task, 2 );
+        monitor.reportProgress( " " ); //$NON-NLS-1$
+        monitor.worked( 1 );
+
+        try
+        {
+            // open file
+            FileWriter fileWriter = new FileWriter( exportLdifFilename );
+            BufferedWriter bufferedWriter = new BufferedWriter( fileWriter );
+
+            // export
+            int count = 0;
+            export( browserConnection, searchParameter, bufferedWriter, count, monitor );
+
+            // close file
+            bufferedWriter.close();
+            fileWriter.close();
+
+        }
+        catch ( Exception e )
+        {
+            monitor.reportError( e );
+        }
+    }
+
+
+    
+    private static void export( IBrowserConnection browserConnection, SearchParameter searchParameter, BufferedWriter bufferedWriter,
+        int count, StudioProgressMonitor monitor ) throws IOException, ConnectionException
+    {
+        try
+        {
+            AttributeComparator comparator = new AttributeComparator( browserConnection );
+            LdifEnumeration enumeration = search( browserConnection, searchParameter, monitor );
+            
+            while ( !monitor.isCanceled() && enumeration.hasNext( monitor ) )
+            {
+                LdifContainer container = enumeration.next( monitor );
+
+                if ( container instanceof LdifContentRecord )
+                {
+                    LdifContentRecord record = ( LdifContentRecord ) container;
+                    LdifDnLine dnLine = record.getDnLine();
+                    LdifAttrValLine[] attrValLines = record.getAttrVals();
+                    LdifSepLine sepLine = record.getSepLine();
+
+                    // sort and format
+                    Arrays.sort( attrValLines, comparator );
+                    LdifContentRecord newRecord = new LdifContentRecord( dnLine );
+                    for ( int i = 0; i < attrValLines.length; i++ )
+                    {
+                        newRecord.addAttrVal( attrValLines[i] );
+                    }
+                    newRecord.finish( sepLine );
+                    String s = newRecord.toFormattedString();
+
+                    // String s = record.toFormattedString();
+                    bufferedWriter.write( s );
+
+                    count++;
+                    monitor.reportProgress( BrowserCoreMessages.bind( BrowserCoreMessages.jobs__export_progress,
+                        new String[]
+                            { Integer.toString( count ) } ) );
+                }
+            }
+        }
+        catch ( ConnectionException ce )
+        {
+            if ( ce.getLdapStatusCode() == ConnectionException.STAUS_CODE_TIMELIMIT_EXCEEDED 
+                || ce.getLdapStatusCode() == ConnectionException.STAUS_CODE_SIZELIMIT_EXCEEDED 
+                || ce.getLdapStatusCode() == ConnectionException.STAUS_CODE_ADMINLIMIT_EXCEEDED )
+            {
+                // ignore
+            }
+            else if ( ce instanceof ReferralException )
+            {
+                if ( searchParameter.getReferralsHandlingMethod() == ReferralHandlingMethod.FOLLOW )
+                {
+                    ReferralException re = ( ReferralException ) ce;
+                    ISearch[] referralSearches = re.getReferralSearches();
+                    for ( int i = 0; i < referralSearches.length; i++ )
+                    {
+                        ISearch referralSearch = referralSearches[i];
+
+                        // export recursive
+                        export( referralSearch.getBrowserConnection(), referralSearch.getSearchParameter(), bufferedWriter,
+                            count, monitor );
+                    }
+                }
+            }
+            else
+            {
+                monitor.reportError( ce );
+            }
+        }
+    }
+
+
+    protected String getErrorMessage()
+    {
+        return BrowserCoreMessages.jobs__export_ldif_error;
+    }
+
+    
+    static LdifEnumeration search( IBrowserConnection browserConnection, SearchParameter parameter, StudioProgressMonitor monitor )
+        throws ConnectionException
+    {
+        NamingEnumeration<SearchResult> result = SearchJob.search( browserConnection, parameter, monitor );
+        
+        if(monitor.errorsReported())
+        {
+            throw JNDIUtils.createConnectionException( null, monitor.getException() );
+        }
+        return new JndiLdifEnumeration( result, parameter );
+    }
+    
+    static class JndiLdifEnumeration implements LdifEnumeration
+    {
+
+        private NamingEnumeration<SearchResult> enumeration;
+
+        private SearchParameter parameter;
+
+
+        public JndiLdifEnumeration( NamingEnumeration<SearchResult> enumeration, SearchParameter parameter )
+        {
+            this.enumeration = enumeration;
+            this.parameter = parameter;
+        }
+
+
+        public boolean hasNext( StudioProgressMonitor monitor ) throws ConnectionException
+        {
+            try
+            {
+                return enumeration != null && enumeration.hasMore();
+            }
+            catch ( NamingException e )
+            {
+                throw JNDIUtils.createConnectionException( parameter, e );
+            }
+        }
+
+
+        public LdifContainer next( StudioProgressMonitor monitor ) throws ConnectionException
+        {
+            try
+            {
+                SearchResult sr = enumeration.next();
+                LdapDN dn = JNDIUtils.getDn( sr );
+                LdifContentRecord record = LdifContentRecord.create( dn.toString() );
+
+                NamingEnumeration<? extends Attribute> attributeEnumeration = sr.getAttributes().getAll();
+                while ( attributeEnumeration.hasMore() )
+                {
+                    Attribute attribute = attributeEnumeration.next();
+                    String attributeName = attribute.getID();
+                    NamingEnumeration<?> valueEnumeration = attribute.getAll();
+                    while ( valueEnumeration.hasMore() )
+                    {
+                        Object o = valueEnumeration.next();
+                        if ( o instanceof String )
+                        {
+                            record.addAttrVal( LdifAttrValLine.create( attributeName, ( String ) o ) );
+                        }
+                        if ( o instanceof byte[] )
+                        {
+                            record.addAttrVal( LdifAttrValLine.create( attributeName, ( byte[] ) o ) );
+                        }
+                    }
+                }
+
+                record.finish( LdifSepLine.create() );
+
+                return record;
+
+            }
+            catch ( NamingException e )
+            {
+                throw JNDIUtils.createConnectionException( parameter, e );
+            }
+        }
+    }
+    
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportLdifJob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportXlsJob.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportXlsJob.java?rev=592082&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportXlsJob.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportXlsJob.java Mon Nov  5 08:51:43 2007
@@ -0,0 +1,345 @@
+/*
+ *  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.FileOutputStream;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.directory.studio.connection.core.Connection;
+import org.apache.directory.studio.connection.core.StudioProgressMonitor;
+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.ConnectionException;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.ISearch;
+import org.apache.directory.studio.ldapbrowser.core.model.ReferralException;
+import org.apache.directory.studio.ldapbrowser.core.model.SearchParameter;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection.ReferralHandlingMethod;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.LdifEnumeration;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.container.LdifContainer;
+import org.apache.directory.studio.ldapbrowser.core.model.ldif.container.LdifContentRecord;
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.eclipse.core.runtime.Preferences;
+
+
+/**
+ * Job to export directory content to an XLS file.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ExportXlsJob extends AbstractEclipseJob
+{
+
+    /** The maximum count limit */
+    public static final int MAX_COUNT_LIMIT = 65000;
+
+    /** The filename of the XLS file. */
+    private String exportXlsFilename;
+
+    /** The browser connection. */
+    private IBrowserConnection browserConnection;
+
+    /** The search parameter. */
+    private SearchParameter searchParameter;
+
+    /** The export dn flag. */
+    private boolean exportDn;
+
+
+    /**
+     * Creates a new instance of ExportXlsJob.
+     * 
+     * @param exportLdifFilename the export ldif filename
+     * @param browserConnection the browser connection
+     * @param searchParameter the search parameter
+     * @param exportDn true to export the DN
+     */
+    public ExportXlsJob( String exportLdifFilename, IBrowserConnection browserConnection,
+        SearchParameter searchParameter, boolean exportDn )
+    {
+        this.exportXlsFilename = exportLdifFilename;
+        this.browserConnection = browserConnection;
+        this.searchParameter = searchParameter;
+        this.exportDn = exportDn;
+
+        setName( BrowserCoreMessages.jobs__export_xls_name );
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getConnections()
+     */
+    protected Connection[] getConnections()
+    {
+        return new Connection[]
+            { browserConnection.getConnection() };
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getLockedObjects()
+     */
+    protected Object[] getLockedObjects()
+    {
+        return new Object[]
+            { browserConnection.getUrl() + "_" + DigestUtils.shaHex( exportXlsFilename ) };
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#executeAsyncJob(org.apache.directory.studio.connection.core.StudioProgressMonitor)
+     */
+    protected void executeAsyncJob( StudioProgressMonitor monitor )
+    {
+        monitor.beginTask( BrowserCoreMessages.jobs__export_xls_task, 2 );
+        monitor.reportProgress( " " ); //$NON-NLS-1$
+        monitor.worked( 1 );
+
+        Preferences coreStore = BrowserCorePlugin.getDefault().getPluginPreferences();
+        String valueDelimiter = coreStore.getString( BrowserCoreConstants.PREFERENCE_FORMAT_XLS_VALUEDELIMITER );
+        int binaryEncoding = coreStore.getInt( BrowserCoreConstants.PREFERENCE_FORMAT_XLS_BINARYENCODING );
+
+        HSSFWorkbook wb = new HSSFWorkbook();
+        HSSFSheet sheet = wb.createSheet( "Export" ); //$NON-NLS-1$
+
+        // header
+        HSSFRow headerRow = sheet.createRow( 0 );
+        LinkedHashMap<String, Short> attributeNameMap = new LinkedHashMap<String, Short>();
+        if ( this.exportDn )
+        {
+            short cellNum = ( short ) 0;
+            attributeNameMap.put( "dn", new Short( cellNum ) ); //$NON-NLS-1$
+            headerRow.createCell( cellNum ).setCellValue( "dn" ); //$NON-NLS-1$
+        }
+
+        // String[] exportAttributes =
+        // this.searchParameter.getReturningAttributes();
+        // exportAttributes = null;
+        // for (int i = 0; exportAttributes != null && i <
+        // exportAttributes.length; i++) {
+        // short cellNum = (short)attributeNameMap.size();
+        // attributeNameMap.put(exportAttributes[i], new Short(cellNum));
+        // headerRow.createCell(cellNum).setCellValue(exportAttributes[i]);
+        // }
+
+        // max export
+        if ( searchParameter.getCountLimit() < 1 || searchParameter.getCountLimit() > MAX_COUNT_LIMIT )
+        {
+            searchParameter.setCountLimit( MAX_COUNT_LIMIT );
+        }
+
+        // export
+        try
+        {
+            int count = 0;
+            exportToXls( browserConnection, searchParameter, sheet, headerRow, count, monitor, attributeNameMap,
+                valueDelimiter, binaryEncoding, this.exportDn );
+        }
+        catch ( Exception e )
+        {
+            monitor.reportError( e );
+        }
+
+        // column width
+        for ( int i = 0; i <= sheet.getLastRowNum(); i++ )
+        {
+            HSSFRow row = sheet.getRow( i );
+            for ( short j = 0; row != null && j <= row.getLastCellNum(); j++ )
+            {
+                HSSFCell cell = row.getCell( j );
+                if ( cell != null && cell.getCellType() == HSSFCell.CELL_TYPE_STRING )
+                {
+                    String value = cell.getStringCellValue();
+
+                    if ( ( short ) ( value.length() * 256 * 1.1 ) > sheet.getColumnWidth( j ) )
+                    {
+                        sheet.setColumnWidth( j, ( short ) ( value.length() * 256 * 1.1 ) );
+                    }
+                }
+            }
+        }
+
+        try
+        {
+            FileOutputStream fileOut = new FileOutputStream( exportXlsFilename );
+            wb.write( fileOut );
+            fileOut.close();
+        }
+        catch ( Exception e )
+        {
+            monitor.reportError( e );
+        }
+    }
+
+
+    /**
+     * Exports to XLS.
+     * 
+     * @param browserConnection the browser connection
+     * @param searchParameter the search parameter
+     * @param sheet the sheet
+     * @param headerRow the header row
+     * @param count the count
+     * @param monitor the monitor
+     * @param attributeNameMap the attribute name map
+     * @param valueDelimiter the value delimiter
+     * @param binaryEncoding the binary encoding
+     * @param exportDn the export dn
+     * 
+     * @throws IOException Signals that an I/O exception has occurred.
+     * @throws ConnectionException the connection exception
+     */
+    private static void exportToXls( IBrowserConnection browserConnection, SearchParameter searchParameter,
+        HSSFSheet sheet, HSSFRow headerRow, int count, StudioProgressMonitor monitor,
+        LinkedHashMap<String, Short> attributeNameMap, String valueDelimiter, int binaryEncoding, boolean exportDn )
+        throws IOException, ConnectionException
+    {
+        try
+        {
+            LdifEnumeration enumeration = ExportLdifJob.search( browserConnection, searchParameter, monitor );
+            while ( !monitor.isCanceled() && enumeration.hasNext( monitor ) )
+            {
+                LdifContainer container = enumeration.next( monitor );
+
+                if ( container instanceof LdifContentRecord )
+                {
+                    LdifContentRecord record = ( LdifContentRecord ) container;
+                    recordToHSSFRow( browserConnection, record, sheet, headerRow, attributeNameMap, valueDelimiter,
+                        binaryEncoding, exportDn );
+
+                    count++;
+                    monitor.reportProgress( BrowserCoreMessages.bind( BrowserCoreMessages.jobs__export_progress,
+                        new String[]
+                            { Integer.toString( count ) } ) );
+                }
+            }
+
+        }
+        catch ( ConnectionException ce )
+        {
+
+            if ( ce.getLdapStatusCode() == 3 || ce.getLdapStatusCode() == 4 || ce.getLdapStatusCode() == 11 )
+            {
+                // nothing
+            }
+            else if ( ce instanceof ReferralException )
+            {
+                if ( searchParameter.getReferralsHandlingMethod() == ReferralHandlingMethod.FOLLOW )
+                {
+                    ReferralException re = ( ReferralException ) ce;
+                    ISearch[] referralSearches = re.getReferralSearches();
+                    for ( ISearch referralSearch : referralSearches )
+                    {
+                        // export recursive
+                        exportToXls( referralSearch.getBrowserConnection(), referralSearch.getSearchParameter(), sheet,
+                            headerRow, count, monitor, attributeNameMap, valueDelimiter, binaryEncoding, exportDn );
+                    }
+                }
+            }
+            else
+            {
+                monitor.reportError( ce );
+            }
+        }
+    }
+
+
+    /**
+     * Transforms an LDIF record to an HSSF row.
+     * 
+     * @param browserConnection the browser connection
+     * @param record the record
+     * @param sheet the sheet
+     * @param headerRow the header row
+     * @param headerRowAttributeNameMap the header row attribute name map
+     * @param valueDelimiter the value delimiter
+     * @param binaryEncoding the binary encoding
+     * @param exportDn the export dn
+     */
+    private static void recordToHSSFRow( IBrowserConnection browserConnection, LdifContentRecord record,
+        HSSFSheet sheet, HSSFRow headerRow, Map<String, Short> headerRowAttributeNameMap, String valueDelimiter,
+        int binaryEncoding, boolean exportDn )
+    {
+        // group multi-valued attributes
+        Map<String, String> attributeMap = ExportCsvJob.getAttributeMap( null, record, valueDelimiter, "UTF-16",
+            binaryEncoding );
+
+        // output attributes
+        HSSFRow row = sheet.createRow( sheet.getLastRowNum() + 1 );
+        if ( exportDn )
+        {
+            HSSFCell cell = row.createCell( ( short ) 0 );
+            cell.setEncoding( HSSFCell.ENCODING_UTF_16 );
+            cell.setCellValue( record.getDnLine().getValueAsString() );
+        }
+        for ( String attributeName : attributeMap.keySet() )
+        {
+            String value = ( String ) attributeMap.get( attributeName );
+
+            if ( !headerRowAttributeNameMap.containsKey( attributeName ) )
+            {
+                short cellNum = ( short ) headerRowAttributeNameMap.size();
+                headerRowAttributeNameMap.put( attributeName, new Short( cellNum ) );
+                HSSFCell cell = headerRow.createCell( cellNum );
+                cell.setEncoding( HSSFCell.ENCODING_UTF_16 );
+                cell.setCellValue( attributeName );
+            }
+
+            if ( headerRowAttributeNameMap.containsKey( attributeName ) )
+            {
+                short cellNum = ( ( Short ) headerRowAttributeNameMap.get( attributeName ) ).shortValue();
+                HSSFCell cell = row.createCell( cellNum );
+                cell.setEncoding( HSSFCell.ENCODING_UTF_16 );
+                cell.setCellValue( value );
+            }
+        }
+
+        // for (int i = 0; i < attributes.length; i++) {
+        //			
+        // String attributeName = attributes[i];
+        // if (attributeMap.containsKey(attributeName)) {
+        // String value = (String)attributeMap.get(attributeName);
+        // short cellNum = (short)(i + (exportDn?1:0));
+        // row.createCell(cellNum).setCellValue(value);
+        // }
+        // }
+
+    }
+
+
+    /**
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getErrorMessage()
+     */
+    protected String getErrorMessage()
+    {
+        return BrowserCoreMessages.jobs__export_xls_error;
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ExportXlsJob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/FetchBaseDNsJob.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/FetchBaseDNsJob.java?rev=592082&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/FetchBaseDNsJob.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/FetchBaseDNsJob.java Mon Nov  5 08:51:43 2007
@@ -0,0 +1,110 @@
+/*
+ *  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.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.studio.connection.core.Connection;
+import org.apache.directory.studio.connection.core.StudioProgressMonitor;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+import org.apache.directory.studio.ldapbrowser.core.model.IAttribute;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+import org.apache.directory.studio.ldapbrowser.core.model.IRootDSE;
+
+
+public class FetchBaseDNsJob extends AbstractNotificationJob
+{
+
+    private IBrowserConnection connection;
+
+    private String[] baseDNs;
+
+
+    public FetchBaseDNsJob( IBrowserConnection connection )
+    {
+        this.connection = connection;
+        setName( BrowserCoreMessages.jobs__fetch_basedns_name );
+    }
+
+
+    protected Connection[] getConnections()
+    {
+        return new Connection[0];
+    }
+
+
+    protected Object[] getLockedObjects()
+    {
+        List l = new ArrayList();
+        l.add( connection );
+        return l.toArray();
+    }
+
+
+    protected void executeNotificationJob( StudioProgressMonitor monitor )
+    {
+        monitor.beginTask( BrowserCoreMessages.jobs__fetch_basedns_task, 5 );
+        monitor.reportProgress( " " ); //$NON-NLS-1$
+        monitor.worked( 1 );
+
+        IRootDSE rootDSE = connection.getRootDSE();
+        InitializeAttributesJob.initializeAttributes( rootDSE, true, monitor );
+//        IEntry[] baseDNEntries = connection.getRootDSE().getChildren();
+//        baseDNs = new String[baseDNEntries.length];
+//        for ( int i = 0; i < baseDNs.length; i++ )
+//        {
+//            baseDNs[i] = baseDNEntries[i].getDn().toString();
+//        }
+        
+        IAttribute attribute = rootDSE.getAttribute( IRootDSE.ROOTDSE_ATTRIBUTE_NAMINGCONTEXTS );
+        if ( attribute != null )
+        {
+            baseDNs = attribute.getStringValues();
+        }
+        
+        monitor.worked( 1 );
+    }
+
+
+    protected String getErrorMessage()
+    {
+        return BrowserCoreMessages.jobs__fetch_basedns_error;
+    }
+
+
+    public String[] getBaseDNs()
+    {
+        if ( baseDNs == null )
+        {
+            baseDNs = new String[0];
+        }
+        return baseDNs;
+    }
+
+
+    protected void runNotification()
+    {
+
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/FetchBaseDNsJob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportDsmlJob.java
URL: http://svn.apache.org/viewvc/directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportDsmlJob.java?rev=592082&view=auto
==============================================================================
--- directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportDsmlJob.java (added)
+++ directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportDsmlJob.java Mon Nov  5 08:51:43 2007
@@ -0,0 +1,182 @@
+/*
+ *  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.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.directory.shared.ldap.codec.LdapResponse;
+import org.apache.directory.shared.ldap.message.ResultCodeEnum;
+import org.apache.directory.studio.connection.core.Connection;
+import org.apache.directory.studio.connection.core.StudioProgressMonitor;
+import org.apache.directory.studio.dsmlv2.Dsmlv2ResponseParser;
+import org.apache.directory.studio.dsmlv2.engine.Dsmlv2Engine;
+import org.apache.directory.studio.dsmlv2.reponse.ErrorResponse;
+import org.apache.directory.studio.ldapbrowser.core.BrowserCoreMessages;
+import org.apache.directory.studio.ldapbrowser.core.model.IBrowserConnection;
+
+
+/**
+ * This class implements a Job for Importing a DSML File into a LDAP server
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class ImportDsmlJob extends AbstractEclipseJob
+{
+    /** The connection to use */
+    private IBrowserConnection browserConnection;
+
+    /** The DSML file to use */
+    private File dsmlFile;
+
+    /** The Save file to use */
+    private File responseFile;
+
+
+    /**
+     * Creates a new instance of ImportDsmlJob.
+     *
+     * @param connection
+     *          The connection to use
+     * @param dsmlFile
+     *          The DSML file to read from
+     * @param saveFile
+     *          The Save file to use
+     * @param continueOnError
+     *          The ContinueOnError flag
+     */
+    public ImportDsmlJob( IBrowserConnection connection, File dsmlFile, File saveFile )
+    {
+        this.browserConnection = connection;
+        this.dsmlFile = dsmlFile;
+        this.responseFile = saveFile;
+
+        setName( BrowserCoreMessages.jobs__import_dsml_name );
+    }
+
+
+    /**
+     * Creates a new instance of ImportDsmlJob.
+     *
+     * @param connection
+     *          The Connection to use
+     * @param dsmlFile
+     *          The DSML file to read from
+     * @param continueOnError
+     *          The ContinueOnError flag
+     */
+    public ImportDsmlJob( IBrowserConnection connection, File dsmlFile )
+    {
+        this( connection, dsmlFile, null );
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getConnections()
+     */
+    protected Connection[] getConnections()
+    {
+        return new Connection[]
+            { browserConnection.getConnection() };
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getLockedObjects()
+     */
+    protected Object[] getLockedObjects()
+    {
+        List l = new ArrayList();
+        l.add( browserConnection.getUrl() + "_" + DigestUtils.shaHex( dsmlFile.toString() ) );
+        return l.toArray();
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#executeAsyncJob(org.apache.directory.studio.ldapbrowser.core.jobs.ExtendedProgressMonitor)
+     */
+    protected void executeAsyncJob( StudioProgressMonitor monitor )
+    {
+
+        monitor.beginTask( BrowserCoreMessages.jobs__import_dsml_task, 2 );
+        monitor.reportProgress( " " ); //$NON-NLS-1$
+        monitor.worked( 1 );
+        
+        Dsmlv2Engine engine = new Dsmlv2Engine( browserConnection.getConnection().getHost(), browserConnection
+            .getConnection().getPort(), browserConnection.getConnection().getBindPrincipal(), browserConnection
+            .getConnection().getBindPassword() );
+        try
+        {
+            // Executing the DSML request and getting the response
+            String response = engine.processDSMLFile( dsmlFile.getAbsolutePath() );
+            
+            // Saving Response if needed
+            if ( responseFile != null )
+            {
+                FileOutputStream fout = new FileOutputStream( responseFile );
+                new PrintStream( fout ).println( response );
+                fout.close();
+            }
+            
+            // Processing Reponse (Reading and displaying possible errors)
+            int errorCount = 0;
+            Dsmlv2ResponseParser responseParser = new Dsmlv2ResponseParser();
+            responseParser.setInput( response );
+            LdapResponse ldapResponse = responseParser.getNextResponse();
+            while ( ldapResponse != null )
+            {
+                if ( ( ldapResponse instanceof ErrorResponse ) 
+                     || ( ldapResponse.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS ) )
+                {
+                    errorCount++;
+                }
+                ldapResponse = responseParser.getNextResponse();
+            }
+            
+            if ( errorCount > 0 )
+            {
+                monitor.reportError( BrowserCoreMessages.bind(
+                        BrowserCoreMessages.dsml__n_errors_see_responsefile, new String[]
+                            { "" + errorCount } ) ); //$NON-NLS-1$
+            }
+        }
+        catch ( Exception e )
+        {
+            monitor.reportError( e );
+        }
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.directory.studio.ldapbrowser.core.jobs.AbstractEclipseJob#getErrorMessage()
+     */
+    protected String getErrorMessage()
+    {
+        return BrowserCoreMessages.jobs__import_dsml_error;
+    }
+
+}

Propchange: directory/sandbox/felixk/studio-ldapbrowser-core/src/main/java/org/apache/directory/studio/ldapbrowser/core/jobs/ImportDsmlJob.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message