/**
* Copyright (c) 2011, 2013 KUBO Atsuhiro <kubo@iteman.jp>,
* All rights reserved.
*
* This file is part of MakeGood.
*
* 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
*/
package com.piece_framework.makegood.aspect;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.NotFoundException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.core.runtime.Status;
import org.eclipse.ui.IStartup;
/**
* @since 1.6.0
*/
public class AspectWeaver implements IStartup {
private static final String EXTENSION_POINT_ID = "com.piece_framework.makegood.aspect.manifests"; //$NON-NLS-1$
private static final Object processLock = new Object();
private static boolean isFinished = false;
@Override
public void earlyStartup() {
weave();
}
public void weave() {
synchronized (processLock) {
if (PDTVersion.getInstance().hasError()) return;
if (isFinished) return;
for (AspectManifest manifest: getManifests()) {
boolean result = loadDependencies(manifest);
if (!result) continue;
weaveAspects(manifest);
}
isFinished = true;
}
}
public static boolean isFinished() {
return isFinished;
}
private static List<AspectManifest> getManifests() {
List<AspectManifest> manifests = new ArrayList<AspectManifest>();
IExtensionRegistry extensionRegistry = RegistryFactory.getRegistry();
if (extensionRegistry == null) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to get the default extension registry. The registry provider has not been set or the registry has not been created.")); //$NON-NLS-1$
return manifests;
}
IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(EXTENSION_POINT_ID);
if (extensionPoint == null) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Unable to get the extension point \"" + EXTENSION_POINT_ID + "\".")); //$NON-NLS-1$ //$NON-NLS-2$
return manifests;
}
for (IExtension extension: extensionPoint.getExtensions()) {
for (IConfigurationElement configurationElement: extension.getConfigurationElements()) {
if ("manifest".equals(configurationElement.getName())) { //$NON-NLS-1$
Object executableExtension;
try {
executableExtension = configurationElement.createExecutableExtension("class"); //$NON-NLS-1$
} catch (CoreException e) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, e.getMessage(), e));
continue;
}
if (executableExtension instanceof AspectManifest) {
manifests.add((AspectManifest) executableExtension);
}
}
}
}
return manifests;
}
private boolean loadDependencies(AspectManifest manifest) {
try {
new BundleLoader(manifest.dependencies()).load();
} catch (NotFoundException e) {
log(e, manifest);
return false;
}
return true;
}
private void weaveAspects(AspectManifest manifest) {
Map<CtClass, CtClass> wovenClasses = new IdentityHashMap<CtClass, CtClass>();
for (Aspect aspect: manifest.aspects()) {
try {
aspect.weave();
} catch (NotFoundException e) {
log(e, manifest);
continue;
} catch (CannotCompileException e) {
log(e, manifest);
continue;
} catch (CannotWeaveException e) {
log(e, manifest);
continue;
}
for (CtClass wovenClass: aspect.getWovenClasses()) {
wovenClasses.put(wovenClass, wovenClass);
}
}
for (CtClass wovenClass: wovenClasses.values()) {
try {
wovenClass.toClass(manifest.getClass().getClassLoader(), null);
} catch (CannotCompileException e) {
log(e, manifest);
continue;
}
}
}
private void log(Exception e, AspectManifest manifest) {
Platform.getLog(Platform.getBundle(manifest.pluginId()))
.log(new Status(IStatus.ERROR, manifest.pluginId(), 0, e.getMessage(), e));
}
}