<commit_before>package io.hawt.ide;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.hawt.util.IOHelper;
import io.hawt.util.MBeanSupport;

/**
 * A facade for working with IDEs to open a source code editor
 */
public class IdeFacade extends MBeanSupport implements IdeFacadeMBean {
	private static final transient Logger LOG = LoggerFactory.getLogger(IdeFacade.class);
	private static final String IDEA_URL = "http://localhost:63342";
	private static final String REST_API = IDEA_URL + "/api/file";
    private static IdeFacade singleton;
    private File baseDir;
    private Boolean restApiSupported;

    public static IdeFacade getSingleton() {
        if (singleton == null) {
            LOG.warn("No IdeFacade constructed yet so using default configuration for now");
            singleton = new IdeFacade();
        }
        return singleton;
    }

    @Override
    public void init() throws Exception {
        IdeFacade.singleton = this;
        super.init();
    }

    @Override
    protected String getDefaultObjectName() {
        return "hawtio:type=IdeFacade";
    }

    /**
     * Returns the base directory of the current project
     */
    public File getBaseDir() {
        if (baseDir == null) {
            baseDir = new File(System.getProperty("basedir", "."));
        }
        return baseDir;
    }

    public void setBaseDir(File baseDir) {
        this.baseDir = baseDir;
    }

    /**
     * Attempt to open in Intellij IDEA: 
     *  - try to resolve path
     *  - attempt REST interface
     *  - fall back to Intellij's XmlRPC mechanism to open and navigate to a file
     */
    public String ideaOpen(final SourceReference sourceReference) throws Exception {
		String absoluteFileName = SourceLocator.findClassAbsoluteFileName(sourceReference.fileName, sourceReference.className, getBaseDir());
    	if(invokeRestApi(absoluteFileName, sourceReference)) {
    		return "OK";
    	} else {
    		if(sourceReference.hasLineOrColumn()) {
    			return ideaOpenAndNavigateWithRpc(absoluteFileName, sourceReference.getLineOrDefault(), sourceReference.getLineOrDefault());
    		} else {
				return ideaOpenWithRpc(absoluteFileName);
    		}
    	} 
    }


	private String ideaOpenAndNavigateWithRpc(String absoluteFileName, int line, int column) throws IOException {
		String xml = "<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\n" +
                "<methodCall>\n" +
                "  <methodName>fileOpener.openAndNavigate</methodName>\n" +
                "  <params>\n" +
                "    <param><value><string>" + absoluteFileName + "</string></value></param>\n" +
                "    <param><value><int>" + line + "</int></value></param>\n" +
                "    <param><value><int>" + column + "</int></value></param>\n" +
                "  </params>\n" +
                "</methodCall>\n";
        return ideaXmlRpc(xml);
	}



	/**
	 * Use HTTP to invoke open file API
	 * @param parameters to include as query parameters in URL
	 * @return true - if call succeeded with OK 200 response code
	 */
	private boolean invokeRestApi(final String absoluteFileName, final SourceReference sourceReference) {
		//previously probed to not be supported
		if(restApiSupported == Boolean.FALSE) {
			return false;
		}

        try {
        	final StringBuilder builder=new StringBuilder(REST_API);
        	builder.append("?file=");
        	builder.append(absoluteFileName);
        	if(sourceReference.line != null) {
        		builder.append("&line=");
        		builder.append(sourceReference.line);
        		if(sourceReference.column != null) {
            		builder.append("&column=");
            		builder.append(sourceReference.column);
            	}
        	}<commit_msg>#2316 : javadoc reference<commit_after>package io.hawt.ide;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.hawt.util.IOHelper;
import io.hawt.util.MBeanSupport;

/**
 * A facade for working with IDEs to open a source code editor
 */
public class IdeFacade extends MBeanSupport implements IdeFacadeMBean {
	private static final transient Logger LOG = LoggerFactory.getLogger(IdeFacade.class);
	private static final String IDEA_URL = "http://localhost:63342";
	private static final String REST_API = IDEA_URL + "/api/file";
    private static IdeFacade singleton;
    private File baseDir;
    private Boolean restApiSupported;

    public static IdeFacade getSingleton() {
        if (singleton == null) {
            LOG.warn("No IdeFacade constructed yet so using default configuration for now");
            singleton = new IdeFacade();
        }
        return singleton;
    }

    @Override
    public void init() throws Exception {
        IdeFacade.singleton = this;
        super.init();
    }

    @Override
    protected String getDefaultObjectName() {
        return "hawtio:type=IdeFacade";
    }

    /**
     * Returns the base directory of the current project
     */
    public File getBaseDir() {
        if (baseDir == null) {
            baseDir = new File(System.getProperty("basedir", "."));
        }
        return baseDir;
    }

    public void setBaseDir(File baseDir) {
        this.baseDir = baseDir;
    }

    /**
     * Attempt to open in Intellij IDEA: 
     *  - try to resolve path
     *  - attempt REST interface
     *  - fall back to Intellij's XmlRPC mechanism to open and navigate to a file
     */
    public String ideaOpen(final SourceReference sourceReference) throws Exception {
		String absoluteFileName = SourceLocator.findClassAbsoluteFileName(sourceReference.fileName, sourceReference.className, getBaseDir());
    	if(invokeRestApi(absoluteFileName, sourceReference)) {
    		return "OK";
    	} else {
    		if(sourceReference.hasLineOrColumn()) {
    			return ideaOpenAndNavigateWithRpc(absoluteFileName, sourceReference.getLineOrDefault(), sourceReference.getLineOrDefault());
    		} else {
				return ideaOpenWithRpc(absoluteFileName);
    		}
    	} 
    }


	private String ideaOpenAndNavigateWithRpc(String absoluteFileName, int line, int column) throws IOException {
		String xml = "<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\n" +
                "<methodCall>\n" +
                "  <methodName>fileOpener.openAndNavigate</methodName>\n" +
                "  <params>\n" +
                "    <param><value><string>" + absoluteFileName + "</string></value></param>\n" +
                "    <param><value><int>" + line + "</int></value></param>\n" +
                "    <param><value><int>" + column + "</int></value></param>\n" +
                "  </params>\n" +
                "</methodCall>\n";
        return ideaXmlRpc(xml);
	}



	/**
	 * Use HTTP to invoke open file API , 
	 * see https://github.com/JetBrains/intellij-community/blob/master/platform/built-in-server/src/org/jetbrains/ide/OpenFileHttpService.kt
	 * @param parameters to include as query parameters in URL
	 * @return true - if call succeeded with OK 200 response code
	 */
	private boolean invokeRestApi(final String absoluteFileName, final SourceReference sourceReference) {
		//previously probed to not be supported
		if(restApiSupported == Boolean.FALSE) {
			return false;
		}

        try {
        	final StringBuilder builder=new StringBuilder(REST_API);
        	builder.append("?file=");
        	builder.append(absoluteFileName);
        	if(sourceReference.line != null) {
        		builder.append("&line=");
        		builder.append(sourceReference.line);
        		if(sourceReference.column != null) {
            		builder.append("&column=");
            		builder.append(sourceReference.column);
            	}
        	}
{'fraction_non_alphanumeric': 0.11252914468032887, 'fraction_numerical': 0.003681433304699963, 'mean_word_length': 2.723161260849703, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 2, '>': 53, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4549673', 'n_tokens_mistral': 2409, 'n_tokens_neox': 2284, 'n_words': 564}