blob: 450f486d148420c42db7d530f9398cdb4c38209e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 BEA Systems, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* wharley@bea.com - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.apt.core.internal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedResourceChangeListener;
import org.eclipse.jdt.apt.core.util.AptConfig;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.osgi.framework.BundleContext;
public class AptPlugin extends Plugin {
public static final String PLUGIN_ID = "org.eclipse.jdt.apt.core"; //$NON-NLS-1$
// Tracing options
public static boolean DEBUG = false;
public final static String APT_DEBUG_OPTION = AptPlugin.PLUGIN_ID + "/debug"; //$NON-NLS-1$
public static boolean DEBUG_GFM = false;
public final static String APT_DEBUG_GFM_OPTION = AptPlugin.APT_DEBUG_OPTION + "/generatedFiles"; //$NON-NLS-1$
public static boolean DEBUG_GFM_MAPS = false;
public final static String APT_DEBUG_GFM_MAPS_OPTION = AptPlugin.APT_DEBUG_OPTION + "/generatedFileMaps"; //$NON-NLS-1$
public static boolean DEBUG_COMPILATION_ENV = false;
public final static String APT_COMPILATION_ENV_OPTION = AptPlugin.APT_DEBUG_OPTION + "/compilationEnv"; //$NON-NLS-1$
/**
* Status IDs for system log entries. Must be unique per plugin.
*/
public static final int STATUS_EXCEPTION = 1;
public static final int STATUS_NOTOOLSJAR = 2;
public static final int STATUS_CANTLOADPLUGINFACTORY = 3;
public static final String APT_BATCH_PROCESSOR_PROBLEM_MARKER = PLUGIN_ID + ".marker"; //$NON-NLS-1$
/** Marker ID used for build problem, e.g., missing factory jar */
public static final String APT_LOADER_PROBLEM_MARKER = PLUGIN_ID + ".buildproblem"; //$NON-NLS-1$
/** Marker ID used for configuration problem, e.g generated source folder not on classpath */
public static final String APT_CONFIG_PROBLEM_MARKER = PLUGIN_ID + ".configproblem"; //$NON-NLS-1$
/** Marker ID used for posting problems during reconcile/build */
public static final String APT_COMPILATION_PROBLEM_MARKER = PLUGIN_ID + ".compile.problem"; //$NON-NLS-1$
private static final SimpleDateFormat TRACE_DATE_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS"); //$NON-NLS-1$
private static AptPlugin thePlugin = null; // singleton object
/**
* The javax.annotation.processing.Processor class, which is only available on Java 6 and higher.
*/
private static Class<?> _java6ProcessorClass;
// Entries are added lazily in getAptProject(), and removed upon
// project deletion in deleteAptProject().
private static final Map<IJavaProject,AptProject> PROJECT_MAP =
new HashMap<IJavaProject,AptProject>();
// Qualified names of services for which these containers may provide implementations
public static final String JAVA5_FACTORY_NAME = "com.sun.mirror.apt.AnnotationProcessorFactory"; //$NON-NLS-1$
public static final String JAVA6_FACTORY_NAME = "javax.annotation.processing.Processor"; //$NON-NLS-1$
public void start(BundleContext context) throws Exception {
thePlugin = this;
super.start(context);
initDebugTracing();
// Do we have access to
try {
_java6ProcessorClass = Class.forName(JAVA6_FACTORY_NAME);
} catch (Throwable e) {
// ignore
}
AptConfig.initialize();
// DO NOT load extensions from the start() method. This can cause cycles in class loading
// Not to mention it is bad form to load stuff early.
// AnnotationProcessorFactoryLoader.getLoader();
// register resource-changed listener
// TODO: can move this into AptProject.
int mask =
IResourceChangeEvent.PRE_BUILD |
IResourceChangeEvent.PRE_CLOSE |
IResourceChangeEvent.PRE_DELETE |
IResourceChangeEvent.POST_CHANGE;
JavaCore.addPreProcessingResourceChangedListener( new GeneratedResourceChangeListener(), mask );
if( DEBUG )
trace("registered resource change listener"); //$NON-NLS-1$
}
public void stop(BundleContext context) throws Exception {
super.stop(context);
}
public static AptPlugin getPlugin() {
return thePlugin;
}
/**
* Log a status message to the platform log. Use this for reporting exceptions.
* @param status
*/
public static void log(IStatus status) {
thePlugin.getLog().log(status);
}
/**
* Convenience wrapper around log(IStatus), to log an exception
* with severity of ERROR.
*/
public static void log(Throwable e, String message) {
log(new Status(IStatus.ERROR, PLUGIN_ID, STATUS_EXCEPTION, message, e));
}
/**
* Convenience wrapper around log(IStatus), to log an exception
* with severity of WARNING.
*/
public static void logWarning(Throwable e, String message) {
log(createWarningStatus(e, message));
}
/**
* Convenience wrapper for rethrowing exceptions as CoreExceptions,
* with severity of ERROR.
*/
public static Status createStatus(Throwable e, String message) {
return new Status(IStatus.ERROR, PLUGIN_ID, STATUS_EXCEPTION, message, e);
}
/**
* Convenience wrapper for rethrowing exceptions as CoreExceptions,
* with severity of WARNING.
*/
public static Status createWarningStatus(Throwable e, String message) {
return new Status(IStatus.WARNING, PLUGIN_ID, STATUS_EXCEPTION, message, e);
}
/**
* Convenience wrapper for rethrowing exceptions as CoreExceptions,
* with severity of INFO.
*/
public static Status createInfoStatus(Throwable e, String message) {
return new Status(IStatus.INFO, PLUGIN_ID, STATUS_EXCEPTION, message, e);
}
private void initDebugTracing() {
String option = Platform.getDebugOption(APT_DEBUG_OPTION);
if(option != null) DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
option = Platform.getDebugOption(APT_DEBUG_GFM_OPTION);
if(option != null) DEBUG_GFM = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
option = Platform.getDebugOption(APT_DEBUG_GFM_MAPS_OPTION);
if(option != null) DEBUG_GFM_MAPS = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
}
public static void trace(final String msg){
if (DEBUG) {
StringBuffer sb = new StringBuffer();
sb.append('[');
// SimpleDateFormat is not thread-safe, according to javadoc
synchronized(TRACE_DATE_FORMAT) {
sb.append(TRACE_DATE_FORMAT.format(new Date()));
}
sb.append('-');
// Some threads have qualified type names; too long.
String threadName = Thread.currentThread().getName();
int dot = threadName.lastIndexOf('.');
if (dot < 0) {
sb.append(threadName);
}
else {
sb.append(threadName.substring(dot+1));
}
sb.append(']');
sb.append(msg);
System.out.println(sb);
}
}
/**
* Convenience method to report an exception in debug trace mode.
*/
public static void trace(String msg, Throwable t) {
trace(msg);
if (DEBUG) {
t.printStackTrace(System.out);
}
}
private static AptProject getAptProject(IJavaProject javaProject, boolean create){
synchronized(PROJECT_MAP){
AptProject aptProject = PROJECT_MAP.get(javaProject);
if (aptProject != null) {
return aptProject;
}
else{
if( create ){
aptProject = new AptProject(javaProject);
PROJECT_MAP.put(javaProject, aptProject);
return aptProject;
}
else
return null;
}
}
}
public static AptProject getAptProject(IJavaProject javaProject) {
return getAptProject(javaProject, true);
}
public static void deleteAptProject(IJavaProject javaProject) {
synchronized (PROJECT_MAP) {
PROJECT_MAP.remove(javaProject);
}
}
/**
* True if we are running on a platform that supports Java 6 annotation processing,
* that is, if we are running on Java 6 or higher and the org.eclipse.jdt.compiler.apt
* plug-in is also present.
*/
public static boolean canRunJava6Processors() {
if (_java6ProcessorClass == null)
return false;
return Platform.getBundle("org.eclipse.jdt.compiler.apt") != null; //$NON-NLS-1$
}
/**
* The javax.annotation.processing.Processor class. This is only available on the
* Java 6 or higher platform, so it is loaded via reflection in {@link #start}.
*/
public static Class<?> getJava6ProcessorClass() {
return _java6ProcessorClass;
}
}