All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.java.IndentFileEntry Maven / Gradle / Ivy

There is a newer version: RELEASE230
Show newest version
/*
 * 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.netbeans.modules.java;

import java.io.*;
import java.nio.charset.Charset;

import javax.swing.JEditorPane;
import javax.swing.text.Document;
import javax.swing.text.StyledDocument;
import javax.swing.text.EditorKit;
import org.netbeans.api.queries.FileEncodingQuery;

import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
import org.openide.loaders.MultiDataObject;
import org.openide.loaders.FileEntry;
import org.openide.text.IndentEngine;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;

/**
 *
 * @author  Svata
 * @version 1.0
 */
public abstract class IndentFileEntry extends FileEntry.Format {
    private static final String NEWLINE = "\n"; // NOI18N
    private static final String EA_PREFORMATTED = "org-netbeans-modules-java-preformattedSource"; // NOI18N

    private ThreadLocal indentEngine;
    
    /** Creates new JavaFileEntry */
    IndentFileEntry(MultiDataObject dobj, FileObject file) {
        super(dobj, file);
    }

    private EditorKit createEditorKit(String mimeType) {
        EditorKit kit;
        
        kit = JEditorPane.createEditorKitForContentType(mimeType);
        if (kit == null) {
            kit = new javax.swing.text.DefaultEditorKit();
        }
        return kit;
    }
    
    /* package private */ final void setIndentEngine(IndentEngine engine) {
        synchronized (this) {
            if (indentEngine == null)
                indentEngine = new ThreadLocal();
        }
        indentEngine.set(engine);
    }
    
    /* package private */ final void initializeIndentEngine() {
        StyledDocument doc = createDocument(createEditorKit(getFile().getMIMEType()));
        IndentEngine engine = IndentEngine.find(doc); // NOI18N
        setIndentEngine(engine);
    }

    private StyledDocument createDocument(EditorKit kit) {
        Document doc = kit.createDefaultDocument();
        if (doc instanceof StyledDocument) {
            return (StyledDocument)doc;
        } else {
            return new org.openide.text.FilterDocument(doc);
        }
    }
    
    /** Creates a new Java source from the template. Unlike the standard FileEntry.Format,
        this indents the resulting text using an indentation engine.
    */
    @Override
    public FileObject createFromTemplate (FileObject f, String name) throws IOException {
        String ext = getFile ().getExt ();

        if (name == null) {
            name = FileUtil.findFreeFileName(f, getFile ().getName (), ext);
        }
        FileObject fo = f.createData (name, ext);
        java.text.Format frm = createFormat (f, name, ext);
        InputStream is=getFile ().getInputStream ();
        Charset encoding = FileEncodingQuery.getEncoding(getFile());
        Reader reader = new InputStreamReader(is,encoding);
        BufferedReader r = new BufferedReader (reader);
        StyledDocument doc = createDocument(createEditorKit(fo.getMIMEType()));
        IndentEngine eng = (IndentEngine)indentEngine.get();
        if (eng == null) eng = IndentEngine.find(doc);
        Object attr = getFile().getAttribute(EA_PREFORMATTED);
        boolean preformatted = false;
        
        if (attr instanceof Boolean) {
            preformatted = ((Boolean)attr).booleanValue();
        }

        try {
            FileLock lock = fo.lock ();
            try {
                encoding = FileEncodingQuery.getEncoding(fo);
                OutputStream os=fo.getOutputStream(lock);
                OutputStreamWriter w = new OutputStreamWriter(os, encoding);
                try {
                    String line = null;
                    String current;
                    int offset = 0;

                    while ((current = r.readLine ()) != null) {
                        if (line != null) {
                            // newline between lines
                            doc.insertString(offset, NEWLINE, null);
                            offset++;
                        }
                        line = frm.format (current);

                        // partial indentation used only for pre-formatted sources
                        // see #19178 etc.
                        if (!preformatted || !line.equals(current)) {
                            line = fixupGuardedBlocks(safeIndent(eng, line, doc, offset));
                        }
                        doc.insertString(offset, line, null);
                            offset += line.length();
                    }
                    doc.insertString(doc.getLength(), NEWLINE, null);
                    w.write(doc.getText(0, doc.getLength()));
                } catch (javax.swing.text.BadLocationException e) {
                } finally {
                    w.close ();
                }
            } finally {
                lock.releaseLock ();
            }
        } finally {
            r.close ();
        }
        // copy attributes
        FileUtil.copyAttributes (getFile (), fo, (n, v) -> {
            return DataObject.PROP_TEMPLATE.equals(n) ? null : FileUtil.defaultAttributesTransformer().apply(n, v);
        });
        return fo;
    }
    
    /** The prefix of all magic strings */
    private static final String MAGIC_PREFIX = "//GEN-"; // NOI18N

    static String fixupGuardedBlocks(String indentedLine) {
        int offset = indentedLine.indexOf(MAGIC_PREFIX);
        if (offset == -1)
            return indentedLine;
        // move the guarded block at the end of the first line in the string
        int firstLineEnd = indentedLine.indexOf('\n'); // NOI18N
        if (firstLineEnd == -1 || firstLineEnd > offset)
            // already on the first line.
            return indentedLine;
        int guardedLineEnd = indentedLine.indexOf('\n', offset); // NOI18N
        StringBuffer sb = new StringBuffer(indentedLine.length());
        sb.append(indentedLine.substring(0, firstLineEnd));
        if (guardedLineEnd != -1) {
            sb.append(indentedLine.substring(offset, guardedLineEnd));
        } else {
            sb.append(indentedLine.substring(offset));
        }
        sb.append(indentedLine.substring(firstLineEnd, offset));
        if (guardedLineEnd != -1)
            sb.append(indentedLine.substring(guardedLineEnd));
        return sb.toString();
    }

    public static String safeIndent(IndentEngine engine, String text, StyledDocument doc, int offset) {
        if (engine == null)
            return text;
        try {
            StringWriter writer = new StringWriter();
            Writer indentator = engine.createWriter(doc, offset, writer);
            indentator.write(text);
            indentator.close();
            return writer.toString();
        } catch (Exception ex) {	    
            Exceptions.printStackTrace(Exceptions.attachMessage(ex,NbBundle.getMessage(IndentFileEntry.class, "EXMSG_IndentationEngineError")));
            return text;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy