001/*
002 * Copyright (c) 2004-2010, Kohsuke Kawaguchi
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
006 * that the following conditions are met:
007 *
008 *     * Redistributions of source code must retain the above copyright notice, this list of
009 *       conditions and the following disclaimer.
010 *     * Redistributions in binary form must reproduce the above copyright notice, this list of
011 *       conditions and the following disclaimer in the documentation and/or other materials
012 *       provided with the distribution.
013 *
014 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
015 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
016 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
017 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
018 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
019 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
020 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
021 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
022 */
023
024package org.kohsuke.stapler.framework.io;
025
026import java.io.FilterWriter;
027import java.io.Writer;
028import java.io.IOException;
029
030/**
031 * Finds the lone LF and converts that to CR+LF.
032 *
033 * <p>
034 * Internet Explorer's <tt>XmlHttpRequest.responseText</tt> seems to
035 * normalize the line end, and if we only send LF without CR, it will
036 * not recognize that as a new line. To work around this problem,
037 * we use this filter to always convert LF to CR+LF.
038 *
039 * @author Kohsuke Kawaguchi
040 */
041public /*for now, until Hudson migration completes*/ class LineEndNormalizingWriter extends FilterWriter {
042
043    private boolean seenCR;
044
045    public LineEndNormalizingWriter(Writer out) {
046        super(out);
047    }
048
049    public void write(char cbuf[]) throws IOException {
050        write(cbuf, 0, cbuf.length);
051    }
052
053    public void write(String str) throws IOException {
054        write(str,0,str.length());
055    }
056
057    public void write(int c) throws IOException {
058        if(!seenCR && c==LF)
059            super.write("\r\n");
060        else
061            super.write(c);
062        seenCR = (c==CR);
063    }
064
065    public void write(char cbuf[], int off, int len) throws IOException {
066        int end = off+len;
067        int writeBegin = off;
068
069        for( int i=off; i<end; i++ ) {
070            char ch = cbuf[i];
071            if(!seenCR && ch==LF) {
072                // write up to the char before LF
073                super.write(cbuf,writeBegin,i-writeBegin);
074                super.write("\r\n");
075                writeBegin=i+1;
076            }
077            seenCR = (ch==CR);
078        }
079
080        super.write(cbuf,writeBegin,end-writeBegin);
081    }
082
083    public void write(String str, int off, int len) throws IOException {
084        int end = off+len;
085        int writeBegin = off;
086
087        for( int i=off; i<end; i++ ) {
088            char ch = str.charAt(i);
089            if(!seenCR && ch==LF) {
090                // write up to the char before LF
091                super.write(str,writeBegin,i-writeBegin);
092                super.write("\r\n");
093                writeBegin=i+1;
094            }
095            seenCR = (ch==CR);
096        }
097
098        super.write(str,writeBegin,end-writeBegin);
099    }
100
101    private static final int CR = 0x0D;
102    private static final int LF = 0x0A;
103}