content: /**
   * Copyright (C) 2010-2016 eBusiness Information, Excilys Group
   * Copyright (C) 2016-2020 the AndroidAnnotations project
   *
   * Licensed 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.androidannotations.internal.helper;
  
  import java.io.BufferedReader;
  import java.io.CharArrayWriter;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.PrintWriter;
  import java.io.StringWriter;
  import java.io.UnsupportedEncodingException;
  import java.net.URLEncoder;
  import java.util.Map;
  import java.util.Map.Entry;
  import java.util.Set;
  
  import javax.annotation.processing.ProcessingEnvironment;
  import javax.lang.model.element.Element;
  import javax.lang.model.util.Elements;
  
  import org.androidannotations.internal.exception.ProcessingException;
  
  public class ErrorHelper {
  
  	public String getErrorMessage(ProcessingEnvironment processingEnv, ProcessingException e, String aaVersion) {
  		String errorMessage = "Unexpected error in AndroidAnnotations " + aaVersion + "!\n"
  				+ "You should check if there is already an issue about it on https://github.com/androidannotations/androidannotations/search?q=" + urlEncodedErrorMessage(e) + "&type=Issues\n"
  				+ "If none exists, please open a new one with the following content and tell us if you can reproduce it or not. "
  				+ "Don't forget to give us as much information as you can (like parts of your code in failure).\n";
  		errorMessage += "Java version: " + getJavaCompilerVersion() + "\n";
  		errorMessage += "Javac processors options: " + annotationProcessorOptions(processingEnv) + "\n";
  		errorMessage += "Stacktrace: " + stackTraceToString(e.getCause());
  
  		Element element = e.getElement();
  		if (element != null) {
  			errorMessage += "Thrown from: " + elementContainer(element) + "\n";
  			errorMessage += "Element (" + element.getClass().getSimpleName() + "): " + elementFullString(processingEnv, element) + "\n";
  		}
  
  		return errorMessage;
  	}
  
  	private String elementFullString(ProcessingEnvironment processingEnv, Element element) {
  		Elements elementUtils = processingEnv.getElementUtils();
  		CharArrayWriter writer = new CharArrayWriter();
  		elementUtils.printElements(writer, element);
  		return writer.toString();
  	}
  
  	private String elementContainer(Element element) {
  		Element enclosingElement = element.getEnclosingElement();
  		return enclosingElement != null ? enclosingElement.toString() : "";
  	}
  
  	private String annotationProcessorOptions(ProcessingEnvironment processingEnv) {
  		Map<String, String> options = processingEnv.getOptions();
  		Set<Entry<String, String>> optionsEntries = options.entrySet();
  
  		String result = "";
  		for (Entry<String, String> optionEntry : optionsEntries) {
  			result += optionEntry.getKey() + "=" + optionEntry.getValue() + ", ";
  		}
  		return result.length() > 2 ? result.substring(0, result.length() - 2) : result;
  	}
  
  	private String getJavaCompilerVersion() {
  		ProcessBuilder pb = new ProcessBuilder("javac", "-version");
  		pb.redirectErrorStream(true);
  
  		BufferedReader in = null;
  		try {
  			Process process = pb.start();
  			in = new BufferedReader(new InputStreamReader(process.getInputStream()));
  			String buffer = in.readLine();
  			process.waitFor();
  			return buffer;
  		} catch (Exception e) {
  			// ignored
  		} finally {
  			if (in != null) {
  				try {
  					in.close();
  				} catch (IOException e) {
  					// cannot help this
  				}
  			}
  		}
  		return "unknown";
  	}
  
  	private String urlEncodedErrorMessage(Throwable e) {
  		try {
  			return URLEncoder.encode(e.getCause().getClass().getName(), "UTF-8");
  		} catch (UnsupportedEncodingException e1) {
  			return "";
  		}
  	}
  
  	private String stackTraceToString(Throwable e) {
  		StringWriter writer = new StringWriter();
  		PrintWriter pw = new PrintWriter(writer);
  		e.printStackTrace(pw);
  		return writer.toString();
  	}
  
  }
  