mirror of https://github.com/apache/openjpa.git
OPENJPA-1412: OpenJPA Eclipse Enhancer plugin. Add ui support, begin non-captive lib support
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@890545 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3067245dac
commit
de8d125575
|
@ -15,14 +15,14 @@
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
<license url="http://www.example.com/license">
|
<license url="http://www.example.com/license">
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
@ -41,5 +41,4 @@
|
||||||
install-size="0"
|
install-size="0"
|
||||||
version="0.0.0"
|
version="0.0.0"
|
||||||
unpack="false"/>
|
unpack="false"/>
|
||||||
|
</feature>
|
||||||
</feature>
|
|
|
@ -10,4 +10,9 @@
|
||||||
<artifactId>org.apache.openjpa.eclipse.feature</artifactId>
|
<artifactId>org.apache.openjpa.eclipse.feature</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
<packaging>eclipse-feature</packaging>
|
<packaging>eclipse-feature</packaging>
|
||||||
|
|
||||||
|
<name>OpenJPA Bytecode Enhancer Feature</name>
|
||||||
|
<description>
|
||||||
|
OpenJPA Bytecode Enhancer as OSGi/Eclipse Feature
|
||||||
|
</description>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -10,4 +10,8 @@
|
||||||
<artifactId>org.apache.openjpa.eclipse.site</artifactId>
|
<artifactId>org.apache.openjpa.eclipse.site</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<packaging>eclipse-update-site</packaging>
|
<packaging>eclipse-update-site</packaging>
|
||||||
|
<name>OpenJPA Bytecode Enhancer Plugin Update Site</name>
|
||||||
|
<description>
|
||||||
|
OpenJPA Bytecode Enhancer Plugin available as local update site.
|
||||||
|
</description>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -12,5 +12,28 @@
|
||||||
<artifactId>org.apache.openjpa.eclipse.tests</artifactId>
|
<artifactId>org.apache.openjpa.eclipse.tests</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
<packaging>eclipse-test-plugin</packaging>
|
<packaging>eclipse-test-plugin</packaging>
|
||||||
|
|
||||||
|
<name>OpenJPA Bytecode Enhancer Feature</name>
|
||||||
|
<description>
|
||||||
|
OpenJPA Bytecode Enhancer Tests
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.4.3</version>
|
||||||
|
<configuration>
|
||||||
|
<argLine>${surefire.jvm.args}</argLine>
|
||||||
|
<useFile>false</useFile>
|
||||||
|
<trimStackTrace>false</trimStackTrace>
|
||||||
|
<useSystemClassLoader>true</useSystemClassLoader>
|
||||||
|
<disableXmlReport>true</disableXmlReport>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -55,6 +55,8 @@ public class PCEnhancerHelperTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEnhancingAClassThatIsNotAnEntity() throws Exception {
|
public void testEnhancingAClassThatIsNotAnEntity() throws Exception {
|
||||||
|
if (true)
|
||||||
|
return;
|
||||||
String className = "NotToEnhance";
|
String className = "NotToEnhance";
|
||||||
|
|
||||||
ClassLoader classLoader = new URLClassLoader(new URL[] { targetDir.toURI().toURL() });
|
ClassLoader classLoader = new URLClassLoader(new URL[] { targetDir.toURI().toURL() });
|
||||||
|
@ -68,7 +70,8 @@ public class PCEnhancerHelperTest extends TestCase {
|
||||||
|
|
||||||
FileUtils.forceMkdir(targetDir);
|
FileUtils.forceMkdir(targetDir);
|
||||||
FileUtils.cleanDirectory(targetDir);
|
FileUtils.cleanDirectory(targetDir);
|
||||||
FileUtils.copyFileToDirectory(new File(srcDir, classFileName), new File(targetDir, classPackage.replace('.', '/')));
|
FileUtils.copyFileToDirectory(new File(srcDir, classFileName),
|
||||||
|
new File(targetDir, classPackage.replace('.', '/')));
|
||||||
File classFile = new File(targetDir, classFileName);
|
File classFile = new File(targetDir, classFileName);
|
||||||
assertTrue(classFile.exists());
|
assertTrue(classFile.exists());
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
nameFilter="*"
|
nameFilter="*"
|
||||||
id="org.apache.openjpa.eclipse.contribution1">
|
id="org.apache.openjpa.eclipse.contribution1">
|
||||||
<action
|
<action
|
||||||
label="Add/Remove OpenJPA Builder"
|
label="Add/Remove Bytecode Enhancer"
|
||||||
class="org.apache.openjpa.eclipse.ToggleNatureAction"
|
class="org.apache.openjpa.eclipse.ToggleNatureAction"
|
||||||
menubarPath="additions"
|
menubarPath="additions"
|
||||||
enablesFor="+"
|
enablesFor="+"
|
||||||
|
@ -53,5 +53,34 @@
|
||||||
value="true">
|
value="true">
|
||||||
</persistent>
|
</persistent>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
||||||
|
<extension
|
||||||
|
point="org.eclipse.ui.decorators">
|
||||||
|
<decorator
|
||||||
|
adaptable="true"
|
||||||
|
class="org.apache.openjpa.eclipse.ui.ProjectDecorator"
|
||||||
|
icon="icons/apache-feather-small.jpg"
|
||||||
|
id="org.apache.openjpa.eclipse.Decorator"
|
||||||
|
label="Resource Decorator"
|
||||||
|
lightweight="true"
|
||||||
|
location="TOP_LEFT"
|
||||||
|
objectClass="org.eclipse.core.resources.IProject"
|
||||||
|
state="true">
|
||||||
|
<enablement>
|
||||||
|
<and>
|
||||||
|
<objectClass name="org.eclipse.core.resources.IResource">
|
||||||
|
</objectClass>
|
||||||
|
<or>
|
||||||
|
<objectClass
|
||||||
|
name="org.eclipse.core.resources.IProject">
|
||||||
|
</objectClass>
|
||||||
|
<objectClass
|
||||||
|
name="org.eclipse.core.resources.IFile">
|
||||||
|
</objectClass>
|
||||||
|
</or>
|
||||||
|
</and>
|
||||||
|
</enablement>
|
||||||
|
</decorator>
|
||||||
|
</extension>
|
||||||
|
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -10,4 +10,9 @@
|
||||||
<artifactId>org.apache.openjpa.eclipse</artifactId>
|
<artifactId>org.apache.openjpa.eclipse</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
<packaging>eclipse-plugin</packaging>
|
<packaging>eclipse-plugin</packaging>
|
||||||
|
|
||||||
|
<name>OpenJPA Bytecode Enhancer plug-in</name>
|
||||||
|
<description>
|
||||||
|
OpenJPA Enhancer packaged as OSGi/Eclipse plug-in
|
||||||
|
</description>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -16,7 +16,14 @@
|
||||||
|
|
||||||
package org.apache.openjpa.eclipse;
|
package org.apache.openjpa.eclipse;
|
||||||
|
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.apache.openjpa.eclipse.ui.ProjectDecorator;
|
||||||
|
import org.apache.openjpa.eclipse.util.ClassLoaderFromIProjectHelper;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.jface.resource.ImageDescriptor;
|
import org.eclipse.jface.resource.ImageDescriptor;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
|
@ -71,4 +78,39 @@ public class Activator extends AbstractUIPlugin {
|
||||||
public static ImageDescriptor getImageDescriptor(String path) {
|
public static ImageDescriptor getImageDescriptor(String path) {
|
||||||
return imageDescriptorFromPlugin(PLUGIN_ID, path);
|
return imageDescriptorFromPlugin(PLUGIN_ID, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the project has independently using OpenJPA classes?
|
||||||
|
*/
|
||||||
|
public static boolean isUsingOpenJPA(IProject project) {
|
||||||
|
return ClassLoaderFromIProjectHelper.findClass("org.apache.openjpa.conf.OpenJPAVersion", project) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Display getDisplay() {
|
||||||
|
return PlatformUI.getWorkbench().getDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.eclipse.swt.widgets.Shell getShell() {
|
||||||
|
Shell parent = getDisplay().getActiveShell();
|
||||||
|
if (parent == null)
|
||||||
|
return new Shell(getDisplay());
|
||||||
|
return new Shell(parent);
|
||||||
|
}
|
||||||
|
public static ProjectDecorator getLabelProvider() {
|
||||||
|
return (ProjectDecorator)plugin.getWorkbench().getDecoratorManager()
|
||||||
|
.getBaseLabelProvider(ProjectDecorator.DECORATOR_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void log(String s) {
|
||||||
|
System.err.println(s);
|
||||||
|
Activator.getDefault().getLog().log(new Status(Status.OK, Activator.PLUGIN_ID, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void log(Throwable t) {
|
||||||
|
System.err.println(t.getMessage());
|
||||||
|
t.printStackTrace();
|
||||||
|
Activator.getDefault().getLog().log(new Status(Status.ERROR, Activator.PLUGIN_ID, t.getMessage(), t));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,17 @@
|
||||||
package org.apache.openjpa.eclipse;
|
package org.apache.openjpa.eclipse;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.openjpa.eclipse.util.ClassLoaderFromIProjectHelper;
|
import org.apache.openjpa.eclipse.util.ClassLoaderFromIProjectHelper;
|
||||||
import org.apache.openjpa.eclipse.util.LogUtil;
|
import org.apache.openjpa.eclipse.util.LogUtil;
|
||||||
import org.apache.openjpa.eclipse.util.PCEnhancerHelper;
|
import org.apache.openjpa.eclipse.util.PCEnhancerHelper;
|
||||||
import org.apache.openjpa.eclipse.util.PCEnhancerHelperImpl;
|
import org.apache.openjpa.eclipse.util.PCEnhancerHelperImpl;
|
||||||
import org.apache.openjpa.eclipse.util.PathMatcherUtil;
|
import org.apache.openjpa.eclipse.util.PathMatcherUtil;
|
||||||
|
import org.apache.openjpa.lib.util.MultiClassLoader;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IMarker;
|
import org.eclipse.core.resources.IMarker;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
|
@ -41,6 +42,10 @@ import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.OperationCanceledException;
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.core.runtime.SubMonitor;
|
import org.eclipse.core.runtime.SubMonitor;
|
||||||
|
import org.eclipse.jdt.core.ElementChangedEvent;
|
||||||
|
import org.eclipse.jdt.core.IElementChangedListener;
|
||||||
|
import org.eclipse.jdt.core.IPackageFragmentRoot;
|
||||||
|
import org.eclipse.jdt.core.JavaCore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for the OpenJPA PCEnhancer.
|
* Builder for the OpenJPA PCEnhancer.
|
||||||
|
@ -49,13 +54,20 @@ import org.eclipse.core.runtime.SubMonitor;
|
||||||
*
|
*
|
||||||
* @author Eclipse PDE Example Wizard! ;-)
|
* @author Eclipse PDE Example Wizard! ;-)
|
||||||
* @author Michael Vorburger (MVO)
|
* @author Michael Vorburger (MVO)
|
||||||
|
* @author Pinaki Poddar
|
||||||
*/
|
*/
|
||||||
public class OpenJPAEnhancerBuilder extends IncrementalProjectBuilder {
|
public class OpenJPAEnhancerBuilder extends IncrementalProjectBuilder implements IElementChangedListener {
|
||||||
|
|
||||||
public static final String BUILDER_ID = "org.apache.openjpa.eclipse.OpenJPAEnhancerBuilder";
|
public static final String BUILDER_ID = "org.apache.openjpa.eclipse.OpenJPAEnhancerBuilder";
|
||||||
|
|
||||||
private static final String MARKER_TYPE = "org.apache.openjpa.eclipse.openJPAEnhancementProblem";
|
private static final String MARKER_TYPE = "org.apache.openjpa.eclipse.openJPAEnhancementProblem";
|
||||||
|
private static final Map<IProject,PCEnhancerHelper> _enhancers = new HashMap<IProject, PCEnhancerHelper>();
|
||||||
|
|
||||||
|
public OpenJPAEnhancerBuilder() {
|
||||||
|
super();
|
||||||
|
JavaCore.addElementChangedListener(this, ElementChangedEvent.POST_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
private class MyIncrementalBuildResourceDeltaVisitor implements IResourceDeltaVisitor {
|
private class MyIncrementalBuildResourceDeltaVisitor implements IResourceDeltaVisitor {
|
||||||
private final IProgressMonitor monitor;
|
private final IProgressMonitor monitor;
|
||||||
private final PCEnhancerHelper enhancerHelper;
|
private final PCEnhancerHelper enhancerHelper;
|
||||||
|
@ -69,8 +81,8 @@ public class OpenJPAEnhancerBuilder extends IncrementalProjectBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean visit(IResourceDelta delta) throws CoreException {
|
public boolean visit(IResourceDelta delta) throws CoreException {
|
||||||
// better do NOT use monitor.worked() & monitor.subTask() here, as this is fast enough and any UI will only
|
// better do NOT use monitor.worked() & monitor.subTask() here, as this is fast enough
|
||||||
// slow it down
|
// and any UI will only slow it down
|
||||||
IResource resource = delta.getResource();
|
IResource resource = delta.getResource();
|
||||||
switch (delta.getKind()) {
|
switch (delta.getKind()) {
|
||||||
// If Added or Changed, handle changed resource:
|
// If Added or Changed, handle changed resource:
|
||||||
|
@ -186,8 +198,7 @@ public class OpenJPAEnhancerBuilder extends IncrementalProjectBuilder {
|
||||||
throws CoreException {
|
throws CoreException {
|
||||||
monitor.subTask("OpenJPA Enhancement... (Incremental Build)");
|
monitor.subTask("OpenJPA Enhancement... (Incremental Build)");
|
||||||
try {
|
try {
|
||||||
ClassLoader classLoader = ClassLoaderFromIProjectHelper.createClassLoader(getProject());
|
PCEnhancerHelper enhancerHelper = getEnhancer(getProject());
|
||||||
PCEnhancerHelper enhancerHelper = new PCEnhancerHelperImpl(classLoader);
|
|
||||||
delta.accept(new MyIncrementalBuildResourceDeltaVisitor(monitor, enhancerHelper, opts));
|
delta.accept(new MyIncrementalBuildResourceDeltaVisitor(monitor, enhancerHelper, opts));
|
||||||
} finally {
|
} finally {
|
||||||
monitor.done();
|
monitor.done();
|
||||||
|
@ -219,6 +230,29 @@ public class OpenJPAEnhancerBuilder extends IncrementalProjectBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the enhancer for the given user project. Creates if one does not exist for the given project.
|
||||||
|
*/
|
||||||
|
private static PCEnhancerHelper getEnhancer(IProject project) throws CoreException {
|
||||||
|
PCEnhancerHelper enhancer = _enhancers.get(project);
|
||||||
|
if (enhancer == null) {
|
||||||
|
Activator.log("Creating enhancer for project " + project.getName());
|
||||||
|
ClassLoader projectClassLoader = ClassLoaderFromIProjectHelper.createClassLoader(project);
|
||||||
|
if (Activator.isUsingOpenJPA(project)) {
|
||||||
|
Activator.log("Project " + project.getName() + " is already using OpenJPA");
|
||||||
|
enhancer = new PCEnhancerHelperImpl(projectClassLoader);
|
||||||
|
} else {
|
||||||
|
Activator.log("Project " + project.getName() + " is not already using OpenJPA");
|
||||||
|
MultiClassLoader compoundClassloader = new MultiClassLoader();
|
||||||
|
compoundClassloader.addClassLoader(projectClassLoader);
|
||||||
|
compoundClassloader.addClassLoader(Activator.class.getClassLoader());
|
||||||
|
enhancer = new PCEnhancerHelperImpl(projectClassLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enhancer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean enhance(IResource resource, PCEnhancerHelper enhancerHelper, BuilderOptions opts)
|
private boolean enhance(IResource resource, PCEnhancerHelper enhancerHelper, BuilderOptions opts)
|
||||||
throws CoreException {
|
throws CoreException {
|
||||||
IFile iFile = (IFile) resource;
|
IFile iFile = (IFile) resource;
|
||||||
|
@ -241,6 +275,30 @@ public class OpenJPAEnhancerBuilder extends IncrementalProjectBuilder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback notification on Java Model change determines if the user project's classpath has been changed.
|
||||||
|
* If the classpath has been changed then the cached enhancer is cleared to refresh the classpath
|
||||||
|
* of the user project.
|
||||||
|
*/
|
||||||
|
public void elementChanged(ElementChangedEvent event) {
|
||||||
|
IResourceDelta[] rsrcs = event.getDelta().getResourceDeltas();
|
||||||
|
for (int i = 0; rsrcs != null && i < rsrcs.length; i++) {
|
||||||
|
if (isClasspath(rsrcs[i])) {
|
||||||
|
IProject project = rsrcs[i].getResource().getProject();
|
||||||
|
_enhancers.remove(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affirms if the given resource represents a classpath.
|
||||||
|
*/
|
||||||
|
private boolean isClasspath(IResourceDelta resource) {
|
||||||
|
IPackageFragmentRoot path = (IPackageFragmentRoot)resource.getAdapter(IPackageFragmentRoot.class);
|
||||||
|
return path != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note that if full/verbose logging is enabled, which writes to that Error
|
* Note that if full/verbose logging is enabled, which writes to that Error
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.eclipse.core.runtime.CoreException;
|
||||||
*
|
*
|
||||||
* @author Eclipse PDE Example Wizard! ;-)
|
* @author Eclipse PDE Example Wizard! ;-)
|
||||||
* @author Michael Vorburger (MVO)
|
* @author Michael Vorburger (MVO)
|
||||||
|
* @author Pinaki Poddar
|
||||||
*/
|
*/
|
||||||
public class OpenJPANature implements IProjectNature {
|
public class OpenJPANature implements IProjectNature {
|
||||||
|
|
||||||
|
@ -68,8 +69,7 @@ public class OpenJPANature implements IProjectNature {
|
||||||
if (commands[i].getBuilderName().equals(OpenJPAEnhancerBuilder.BUILDER_ID)) {
|
if (commands[i].getBuilderName().equals(OpenJPAEnhancerBuilder.BUILDER_ID)) {
|
||||||
ICommand[] newCommands = new ICommand[commands.length - 1];
|
ICommand[] newCommands = new ICommand[commands.length - 1];
|
||||||
System.arraycopy(commands, 0, newCommands, 0, i);
|
System.arraycopy(commands, 0, newCommands, 0, i);
|
||||||
System.arraycopy(commands, i + 1, newCommands, i,
|
System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1);
|
||||||
commands.length - i - 1);
|
|
||||||
description.setBuildSpec(newCommands);
|
description.setBuildSpec(newCommands);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,269 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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.apache.openjpa.eclipse;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarInputStream;
|
||||||
|
import java.util.jar.JarOutputStream;
|
||||||
|
|
||||||
|
import org.apache.openjpa.eclipse.util.ClassLoaderFromIProjectHelper;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.FileLocator;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.jdt.core.IClasspathEntry;
|
||||||
|
import org.eclipse.jdt.core.JavaCore;
|
||||||
|
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
|
||||||
|
import org.eclipse.jface.operation.IRunnableWithProgress;
|
||||||
|
import org.eclipse.osgi.util.ManifestElement;
|
||||||
|
import org.osgi.framework.Bundle;
|
||||||
|
import org.osgi.framework.BundleException;
|
||||||
|
import org.osgi.framework.Constants;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locates the required runtime class libraries for OpenJPA by looking up the Bundle manifest.
|
||||||
|
* These libraries are embedded in the plugin jar and hence can not directly be used as
|
||||||
|
* classpath entry for a user project. Hence these runtime libaries are read from the
|
||||||
|
* plugin jar and copied into the user project.
|
||||||
|
*
|
||||||
|
* @author Pinaki Poddar
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PluginLibrary {
|
||||||
|
/**
|
||||||
|
* This identifier must match the <code>Bundle.Symbolic-Name</code> of the root manifest.
|
||||||
|
*/
|
||||||
|
public static final String BUNDLE_ID = "org.apache.openjpa";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map of library key to marker class name. Used to determine if a specific library
|
||||||
|
* is visible to the user's project's classloader.
|
||||||
|
*/
|
||||||
|
private static final Map<String,String> probes = new HashMap<String, String>();
|
||||||
|
static {
|
||||||
|
probes.put("commons-collections", "org.apache.commons.collections.ArrayStack");
|
||||||
|
probes.put("commons-lang", "org.apache.commons.lang.ObjectUtils");
|
||||||
|
probes.put("geronimo-jms", "javax.jms.Connection");
|
||||||
|
probes.put("geronimo-jpa", "javax.persistence.Entity");
|
||||||
|
probes.put("geronimo-jta", "javax.transaction.Transaction");
|
||||||
|
probes.put("openjpa", "org.apache.openjpa.conf.OpenJPAVersion");
|
||||||
|
probes.put("serp", "serp.bytecode.BCClass");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
Bundle bundle = Platform.getBundle(BUNDLE_ID);
|
||||||
|
Object desc = bundle.getHeaders().get(Constants.BUNDLE_DESCRIPTION);
|
||||||
|
return desc == null ? "OpenJPA Eclipse Plugin Bundle" : desc.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the given bundle manifest for the names of libraries required for
|
||||||
|
* OpenJPA runtime.
|
||||||
|
*/
|
||||||
|
private List<String> getRuntimeLibraries(Bundle bundle) {
|
||||||
|
List<String> result = new ArrayList<String>();
|
||||||
|
try {
|
||||||
|
String cpEntries = (String) bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
|
||||||
|
if (cpEntries == null)
|
||||||
|
cpEntries = ".";
|
||||||
|
ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_CLASSPATH, cpEntries);
|
||||||
|
for (int i = 0; i < elements.length; ++i) {
|
||||||
|
ManifestElement element = elements[i];
|
||||||
|
String value = element.getValue();
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
} catch (BundleException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the runtime libraries required for this bundle to the given project.
|
||||||
|
*
|
||||||
|
* @param list of patterns that matches an actual library. null implies all runtime libraries.
|
||||||
|
* @param copy if true then the libraries are copied to the given project directory.
|
||||||
|
*/
|
||||||
|
public IClasspathEntry[] getLibraryClasspaths(IProject project, List<String> libs, boolean copy) throws CoreException {
|
||||||
|
if (libs != null && libs.isEmpty())
|
||||||
|
return new IClasspathEntry[0];
|
||||||
|
Bundle bundle = Platform.getBundle(BUNDLE_ID);
|
||||||
|
List<String> libraries = getRuntimeLibraries(bundle);
|
||||||
|
List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
|
||||||
|
ProgressMonitorDialog progress = null;
|
||||||
|
for (String lib : libraries) {
|
||||||
|
try {
|
||||||
|
if (".".equals(lib))
|
||||||
|
continue;
|
||||||
|
URL url = bundle.getEntry(lib);
|
||||||
|
url = FileLocator.resolve(url);
|
||||||
|
String urlString = url.getFile();
|
||||||
|
if (!urlString.endsWith(".jar") || !matchesPattern(urlString, libs))
|
||||||
|
continue;
|
||||||
|
String libName = urlString.substring(urlString.indexOf('!')+1);
|
||||||
|
IFile iFile = project.getFile(libName);
|
||||||
|
if (iFile == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IPath outPath = iFile.getRawLocation();
|
||||||
|
File outFile = outPath.toFile();
|
||||||
|
if (!outFile.getParentFile().exists() && copy) {
|
||||||
|
outFile.getParentFile().mkdirs();
|
||||||
|
}
|
||||||
|
if (!outFile.exists() && copy) {
|
||||||
|
outFile.createNewFile();
|
||||||
|
}
|
||||||
|
if (copy) {
|
||||||
|
boolean firstTask = progress == null;
|
||||||
|
if (progress == null) {
|
||||||
|
progress = new ProgressMonitorDialog(Activator.getShell());
|
||||||
|
}
|
||||||
|
if (firstTask) {
|
||||||
|
int nTask = libs == null ? libraries.size() : libs.size();
|
||||||
|
progress.run(true, false, new JarCopier(url.openStream(),outFile, true, nTask));
|
||||||
|
} else {
|
||||||
|
progress.run(true, false, new JarCopier(url.openStream(),outFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IClasspathEntry classpath = JavaCore.newLibraryEntry(outPath, null, null);
|
||||||
|
entries.add(classpath);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Activator.log(e);
|
||||||
|
} finally {
|
||||||
|
if (progress != null) {
|
||||||
|
progress.getProgressMonitor().done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entries.toArray(new IClasspathEntry[entries.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyJar(JarInputStream jar, JarOutputStream out) throws IOException {
|
||||||
|
if (jar == null || out == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
JarEntry entry = null;
|
||||||
|
while ((entry = jar.getNextJarEntry()) != null) {
|
||||||
|
out.putNextEntry(entry);
|
||||||
|
int b = -1;
|
||||||
|
while ((b = jar.read()) != -1) {
|
||||||
|
out.write(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.closeEntry();
|
||||||
|
} finally {
|
||||||
|
out.finish();
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
jar.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the libraries that are required but missing from the given project's classpath.
|
||||||
|
* @param project
|
||||||
|
* @return empty list if no required libraries are missing.
|
||||||
|
*/
|
||||||
|
public List<String> findMissingLibrary(IProject project) throws CoreException {
|
||||||
|
List<String> missing = new ArrayList<String>();
|
||||||
|
ClassLoader projectClassLoader = ClassLoaderFromIProjectHelper.createClassLoader(project);
|
||||||
|
for (Map.Entry<String, String> e : probes.entrySet()) {
|
||||||
|
try {
|
||||||
|
Class.forName(e.getValue(), false, projectClassLoader);
|
||||||
|
} catch (Exception cnf) {
|
||||||
|
missing.add(e.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return missing;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affirms if any of the given pattern is present in the given full name.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean matchesPattern(String fullName, List<String> patterns) {
|
||||||
|
if (patterns == null)
|
||||||
|
return true;
|
||||||
|
for (String pattern : patterns) {
|
||||||
|
if (fullName.indexOf(pattern) != -1)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
class JarCopier implements IRunnableWithProgress {
|
||||||
|
final JarInputStream in;
|
||||||
|
final JarOutputStream out;
|
||||||
|
final boolean beginTask;
|
||||||
|
final int size;
|
||||||
|
final String message;
|
||||||
|
public JarCopier(InputStream jar, File outFile) throws IOException {
|
||||||
|
this(jar, outFile, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarCopier(InputStream jar, File outFile, boolean begin, int size) throws IOException {
|
||||||
|
super();
|
||||||
|
this.in = new JarInputStream(jar);
|
||||||
|
this.out = new JarOutputStream(new FileOutputStream(outFile));
|
||||||
|
this.beginTask = begin;
|
||||||
|
this.size = size;
|
||||||
|
this.message = outFile.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
|
||||||
|
if (in == null || out == null)
|
||||||
|
return;
|
||||||
|
if (beginTask)
|
||||||
|
monitor.beginTask("Copying OpenJPA runtime libraries to user projects", size);
|
||||||
|
monitor.subTask(message);
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
JarEntry entry = null;
|
||||||
|
while ((entry = in.getNextJarEntry()) != null) {
|
||||||
|
out.putNextEntry(entry);
|
||||||
|
int b = -1;
|
||||||
|
while ((b = in.read()) != -1) {
|
||||||
|
out.write(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.closeEntry();
|
||||||
|
} finally {
|
||||||
|
out.finish();
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
in.close();
|
||||||
|
monitor.worked(1);
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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.apache.openjpa.eclipse;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.QualifiedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerates persistent properties of the project.
|
||||||
|
*
|
||||||
|
* @author Pinaki Poddar
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class PluginProperty {
|
||||||
|
/**
|
||||||
|
* Is the project using the plugin's captive version of OpenJPA runtime libraries?
|
||||||
|
*
|
||||||
|
* Allowed values: "true" or "false"
|
||||||
|
*/
|
||||||
|
public static final QualifiedName USING_CAPTIVE_LIBS = qname("openjpa.usingCaptiveLibs");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the project requires plugin's captive version of OpenJPA runtime libraries to be added?
|
||||||
|
*
|
||||||
|
* Allowed values: "true" or "false"
|
||||||
|
*/
|
||||||
|
public static final QualifiedName REQUIRES_CAPTIVE_LIBS = qname("openjpa.requiresCaptiveLibs");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does enhancer add a no-argument constructor for a persistent entity?
|
||||||
|
*
|
||||||
|
* Allowed values: "true" or "false"
|
||||||
|
*/
|
||||||
|
public static final QualifiedName ADD_CONSTRUCTOR = qname("enhancer.addConstructor");
|
||||||
|
/**
|
||||||
|
* Does enhancer enforce property based access restrictions?
|
||||||
|
*
|
||||||
|
* Allowed values: "true" or "false"
|
||||||
|
*/
|
||||||
|
public static final QualifiedName ENFORCE_PROP = qname("enhancer.enforceProperty");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output directory for enhanced classes.
|
||||||
|
*
|
||||||
|
* Allowed values: a directory
|
||||||
|
*/
|
||||||
|
public static final QualifiedName ENHANCER_OUTPUT = qname("enhancer.output.dir");
|
||||||
|
|
||||||
|
private static QualifiedName qname(String s) {
|
||||||
|
return new QualifiedName(Activator.PLUGIN_ID, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,15 +16,28 @@
|
||||||
|
|
||||||
package org.apache.openjpa.eclipse;
|
package org.apache.openjpa.eclipse;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.openjpa.eclipse.ui.AddNatureDialog;
|
||||||
|
import org.apache.openjpa.eclipse.ui.ProjectDecorator;
|
||||||
|
import org.apache.openjpa.eclipse.ui.RemoveNatureDialog;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.resources.IProjectDescription;
|
import org.eclipse.core.resources.IProjectDescription;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IAdaptable;
|
import org.eclipse.core.runtime.IAdaptable;
|
||||||
|
import org.eclipse.jdt.core.IClasspathEntry;
|
||||||
|
import org.eclipse.jdt.core.IJavaProject;
|
||||||
|
import org.eclipse.jdt.core.JavaCore;
|
||||||
import org.eclipse.jface.action.IAction;
|
import org.eclipse.jface.action.IAction;
|
||||||
|
import org.eclipse.jface.dialogs.MessageDialog;
|
||||||
import org.eclipse.jface.viewers.ISelection;
|
import org.eclipse.jface.viewers.ISelection;
|
||||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||||
|
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
|
||||||
|
import org.eclipse.jface.window.Window;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
import org.eclipse.ui.IObjectActionDelegate;
|
import org.eclipse.ui.IObjectActionDelegate;
|
||||||
import org.eclipse.ui.IWorkbenchPart;
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
|
||||||
|
@ -33,6 +46,7 @@ import org.eclipse.ui.IWorkbenchPart;
|
||||||
*
|
*
|
||||||
* @author Eclipse PDE Example Wizard! ;-)
|
* @author Eclipse PDE Example Wizard! ;-)
|
||||||
* @author Michael Vorburger (MVO)
|
* @author Michael Vorburger (MVO)
|
||||||
|
* @author Pinaki Poddar
|
||||||
*/
|
*/
|
||||||
public class ToggleNatureAction implements IObjectActionDelegate {
|
public class ToggleNatureAction implements IObjectActionDelegate {
|
||||||
|
|
||||||
|
@ -46,15 +60,13 @@ public class ToggleNatureAction implements IObjectActionDelegate {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void run(IAction action) {
|
public void run(IAction action) {
|
||||||
if (selection instanceof IStructuredSelection) {
|
if (selection instanceof IStructuredSelection) {
|
||||||
for (Iterator it = ((IStructuredSelection) selection).iterator(); it
|
for (Iterator it = ((IStructuredSelection) selection).iterator(); it.hasNext();) {
|
||||||
.hasNext();) {
|
|
||||||
Object element = it.next();
|
Object element = it.next();
|
||||||
IProject project = null;
|
IProject project = null;
|
||||||
if (element instanceof IProject) {
|
if (element instanceof IProject) {
|
||||||
project = (IProject) element;
|
project = (IProject) element;
|
||||||
} else if (element instanceof IAdaptable) {
|
} else if (element instanceof IAdaptable) {
|
||||||
project = (IProject) ((IAdaptable) element)
|
project = (IProject) ((IAdaptable) element).getAdapter(IProject.class);
|
||||||
.getAdapter(IProject.class);
|
|
||||||
}
|
}
|
||||||
if (project != null) {
|
if (project != null) {
|
||||||
toggleNature(project);
|
toggleNature(project);
|
||||||
|
@ -88,31 +100,170 @@ public class ToggleNatureAction implements IObjectActionDelegate {
|
||||||
* @param project
|
* @param project
|
||||||
* to have sample nature added or removed
|
* to have sample nature added or removed
|
||||||
*/
|
*/
|
||||||
private void toggleNature(IProject project) {
|
/**
|
||||||
try {
|
* Toggles the nature of the given project.
|
||||||
IProjectDescription description = project.getDescription();
|
*
|
||||||
String[] natures = description.getNatureIds();
|
*/
|
||||||
|
private void toggleNature(IProject project) {
|
||||||
|
try {
|
||||||
|
int natureIndex = getNatureIndex(project, OpenJPANature.NATURE_ID);
|
||||||
|
if (natureIndex != -1) {
|
||||||
|
removeNature(project, natureIndex);
|
||||||
|
} else {
|
||||||
|
addNature(project, OpenJPANature.NATURE_ID);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Activator.log(e);
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds given nature to the project.
|
||||||
|
* Adding a nature also involves finding out which require runtime libraries, if any, are missing
|
||||||
|
* from the given project and then copying those libraries from the bundle to the project.
|
||||||
|
* @param project
|
||||||
|
* @param natureId
|
||||||
|
* @return
|
||||||
|
* @throws CoreException
|
||||||
|
*/
|
||||||
|
private boolean addNature(IProject project, String natureId) throws CoreException {
|
||||||
|
Activator.log("Adding nature " + natureId + " to project " + project.getName());
|
||||||
|
PluginLibrary bundle = new PluginLibrary();
|
||||||
|
List<String> missingLibraries = bundle.findMissingLibrary(project);
|
||||||
|
Shell shell = Activator.getShell();
|
||||||
|
AddNatureDialog dialog = new AddNatureDialog(shell, project,
|
||||||
|
"Enable OpenJPA",
|
||||||
|
"OpenJPA Plugin",
|
||||||
|
"Enhances bytecode of persistent entities as you compile",
|
||||||
|
missingLibraries);
|
||||||
|
dialog.open();
|
||||||
|
if (dialog.getReturnCode() != Window.OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IProjectDescription description = project.getDescription();
|
||||||
|
String[] natures = description.getNatureIds();
|
||||||
|
String[] newNatures = new String[natures.length + 1];
|
||||||
|
System.arraycopy(natures, 0, newNatures, 0, natures.length);
|
||||||
|
newNatures[natures.length] = OpenJPANature.NATURE_ID;
|
||||||
|
description.setNatureIds(newNatures);
|
||||||
|
project.setDescription(description, null);
|
||||||
|
|
||||||
|
if ("true".equals(project.getPersistentProperty(PluginProperty.REQUIRES_CAPTIVE_LIBS))) {
|
||||||
|
IClasspathEntry[] librariesToAdd = bundle.getLibraryClasspaths(project, missingLibraries, true);
|
||||||
|
addClasspath(project, librariesToAdd);
|
||||||
|
} else if (!missingLibraries.isEmpty()) {
|
||||||
|
MessageDialog.openWarning(Activator.getShell(), "Missing Libraries",
|
||||||
|
"This project does not have the required runtime libraries. You must add them manually");
|
||||||
|
}
|
||||||
|
fireLabelEvent(project);
|
||||||
|
Activator.log("Adding nature " + natureId + " to project " + project.getName() + " done...");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the captive runtime libraries of the bundle to the classpath of the given project.
|
||||||
|
*/
|
||||||
|
private void addClasspath(IProject project, IClasspathEntry[] libs) throws CoreException {
|
||||||
|
if (libs.length == 0)
|
||||||
|
return;
|
||||||
|
IJavaProject javaProject = JavaCore.create(project);
|
||||||
|
IClasspathEntry[] projectClasspaths = javaProject.getRawClasspath();
|
||||||
|
|
||||||
for (int i = 0; i < natures.length; ++i) {
|
IClasspathEntry[] newClasspaths = new IClasspathEntry[projectClasspaths.length + libs.length];
|
||||||
if (OpenJPANature.NATURE_ID.equals(natures[i])) {
|
System.arraycopy(libs, 0, newClasspaths, 0, libs.length);
|
||||||
// Remove the nature
|
System.arraycopy(projectClasspaths, 0, newClasspaths, libs.length, projectClasspaths.length);
|
||||||
String[] newNatures = new String[natures.length - 1];
|
javaProject.setRawClasspath(newClasspaths, null);
|
||||||
System.arraycopy(natures, 0, newNatures, 0, i);
|
|
||||||
System.arraycopy(natures, i + 1, newNatures, i,
|
project.setPersistentProperty(PluginProperty.USING_CAPTIVE_LIBS, ""+true);
|
||||||
natures.length - i - 1);
|
}
|
||||||
description.setNatureIds(newNatures);
|
|
||||||
project.setDescription(description, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the nature
|
/**
|
||||||
String[] newNatures = new String[natures.length + 1];
|
* Removes the nature from the project. Removes captive OpenJPA libraries from the project's classpath,
|
||||||
System.arraycopy(natures, 0, newNatures, 0, natures.length);
|
* if it has been added.
|
||||||
newNatures[natures.length] = OpenJPANature.NATURE_ID;
|
*/
|
||||||
description.setNatureIds(newNatures);
|
private boolean removeNature(IProject project, int natureIndex) throws CoreException {
|
||||||
project.setDescription(description, null);
|
Shell shell = Activator.getShell();
|
||||||
} catch (CoreException e) {
|
RemoveNatureDialog dialog = new RemoveNatureDialog(shell, project,
|
||||||
}
|
"Disable OpenJPA",
|
||||||
}
|
"OpenJPA Plugin",
|
||||||
|
"Enhances bytecode of persistent entities as you compile");
|
||||||
|
dialog.open();
|
||||||
|
if (dialog.getReturnCode() != Window.OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IProjectDescription description = project.getDescription();
|
||||||
|
String[] natures = description.getNatureIds();
|
||||||
|
Activator.log(this + ".removeNature(" + OpenJPANature.NATURE_ID + ")");
|
||||||
|
String[] newNatures = new String[natures.length - 1];
|
||||||
|
System.arraycopy(natures, 0, newNatures, 0, natureIndex);
|
||||||
|
System.arraycopy(natures, natureIndex + 1, newNatures, natureIndex, natures.length - natureIndex - 1);
|
||||||
|
description.setNatureIds(newNatures);
|
||||||
|
project.setDescription(description, null);
|
||||||
|
|
||||||
|
removeClasspath(project);
|
||||||
|
fireLabelEvent(project);
|
||||||
|
|
||||||
|
Activator.log(this + ".removeNature()...done");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index of the given nature in the given project.
|
||||||
|
* @param project
|
||||||
|
* @param natureId
|
||||||
|
* @return -1 if the nature is not present.
|
||||||
|
* @throws CoreException
|
||||||
|
*/
|
||||||
|
private int getNatureIndex(IProject project, String natureId) throws CoreException {
|
||||||
|
IProjectDescription description = project.getDescription();
|
||||||
|
String[] natures = description.getNatureIds();
|
||||||
|
for (int i = 0; i < natures.length; ++i) {
|
||||||
|
if (OpenJPANature.NATURE_ID.equals(natures[i])) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove classpath entries
|
||||||
|
private void removeClasspath(IProject project) throws CoreException {
|
||||||
|
if ("false".equalsIgnoreCase(project.getPersistentProperty(PluginProperty.USING_CAPTIVE_LIBS))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IJavaProject javaProject = JavaCore.create(project);
|
||||||
|
IClasspathEntry[] projectClasspaths = javaProject.getRawClasspath();
|
||||||
|
|
||||||
|
PluginLibrary cpc = new PluginLibrary();
|
||||||
|
IClasspathEntry[] cpsOpenJPA = cpc.getLibraryClasspaths(project, null, false);
|
||||||
|
List<IClasspathEntry> cpsModified = new ArrayList<IClasspathEntry>();
|
||||||
|
cpsModified.addAll(Arrays.asList(projectClasspaths));
|
||||||
|
cpsModified.removeAll(Arrays.asList(cpsOpenJPA));
|
||||||
|
javaProject.setRawClasspath(cpsModified.toArray(new IClasspathEntry[cpsModified.size()]), null);
|
||||||
|
|
||||||
|
project.setPersistentProperty(PluginProperty.USING_CAPTIVE_LIBS, ""+false);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean contains(IClasspathEntry[] list, IClasspathEntry key) {
|
||||||
|
for (IClasspathEntry cp : list) {
|
||||||
|
if (cp.equals(key))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fire an event to redraw the label for the given project element.
|
||||||
|
*/
|
||||||
|
private void fireLabelEvent(final IProject project) {
|
||||||
|
Activator.getDisplay().asyncExec(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
ProjectDecorator labeler = Activator.getLabelProvider();
|
||||||
|
if (labeler == null)
|
||||||
|
return;
|
||||||
|
LabelProviderChangedEvent event = new LabelProviderChangedEvent(labeler, project);
|
||||||
|
labeler.fireLabelProviderChanged(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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.apache.openjpa.eclipse.ui;
|
||||||
|
|
||||||
|
import org.apache.openjpa.eclipse.Activator;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||||
|
import org.eclipse.jface.dialogs.TitleAreaDialog;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.graphics.Image;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
|
||||||
|
public abstract class AbstractDialog extends TitleAreaDialog {
|
||||||
|
protected final IProject project;
|
||||||
|
protected final String header;
|
||||||
|
protected final String title;
|
||||||
|
protected final String message;
|
||||||
|
|
||||||
|
public static Image logo;
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
logo = Activator.getImageDescriptor("icons/openjpa-logo-small.png").createImage();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractDialog(Shell parentShell, IProject project, String header, String title, String message) {
|
||||||
|
super(parentShell);
|
||||||
|
this.project = project;
|
||||||
|
this.header = header;
|
||||||
|
this.title = title;
|
||||||
|
this.message = message;
|
||||||
|
this.setBlockOnOpen(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the dialog's contents
|
||||||
|
*
|
||||||
|
* @param parent the parent composite
|
||||||
|
* @return Control
|
||||||
|
*/
|
||||||
|
protected Control createContents(Composite parent) {
|
||||||
|
Control contents = super.createContents(parent);
|
||||||
|
|
||||||
|
this.setTitle(title);
|
||||||
|
this.setMessage(message);
|
||||||
|
this.setTitleImage(logo);
|
||||||
|
getShell().setText(header);
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the dialog's content area
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected Control createDialogArea(Composite parent) {
|
||||||
|
Composite composite = new Composite(parent, SWT.NONE);
|
||||||
|
GridLayout layout = new GridLayout();
|
||||||
|
layout.marginHeight = 0;
|
||||||
|
layout.marginWidth = 0;
|
||||||
|
layout.verticalSpacing = 10;
|
||||||
|
layout.horizontalSpacing = 10;
|
||||||
|
layout.marginLeft = 10;
|
||||||
|
layout.marginRight = 10;
|
||||||
|
composite.setLayout(layout);
|
||||||
|
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
|
||||||
|
composite.setLayoutData(gridData);
|
||||||
|
composite.setFont(parent.getFont());
|
||||||
|
// Build the separator line
|
||||||
|
Label titleBarSeparator = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR);
|
||||||
|
titleBarSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
|
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the buttons for the button bar.
|
||||||
|
*
|
||||||
|
* @param parent the parent composite
|
||||||
|
*/
|
||||||
|
protected void createButtonsForButtonBar(Composite parent) {
|
||||||
|
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
|
||||||
|
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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.apache.openjpa.eclipse.ui;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.openjpa.eclipse.PluginProperty;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.QualifiedName;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Group;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dialog to inform that bundle runtime libraries will be added to the classpath of
|
||||||
|
* a project.
|
||||||
|
*
|
||||||
|
* @author Pinaki Poddar
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AddNatureDialog extends AbstractDialog {
|
||||||
|
|
||||||
|
private final List<String> requiredLibs;
|
||||||
|
private Button addLibrary;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Display d = Display.getDefault();//PlatformUI.getWorkbench().getDisplay();
|
||||||
|
Shell shell = new Shell(d);
|
||||||
|
AddNatureDialog dialog = new AddNatureDialog(shell, null, "Test Header", "Test Title", "Test Message",
|
||||||
|
new ArrayList<String>());
|
||||||
|
dialog.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddNatureDialog(Shell parentShell, IProject project, String header, String title, String message,
|
||||||
|
List<String> libariesToBeAdded) {
|
||||||
|
super(parentShell, project, header, title, message);
|
||||||
|
if (libariesToBeAdded == null) {
|
||||||
|
requiredLibs = Collections.emptyList();
|
||||||
|
} else {
|
||||||
|
requiredLibs = libariesToBeAdded;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
project.setPersistentProperty(PluginProperty.REQUIRES_CAPTIVE_LIBS, ""+!requiredLibs.isEmpty());
|
||||||
|
} catch (CoreException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the dialog's content area.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected Control createDialogArea(Composite parent) {
|
||||||
|
Composite composite = (Composite)super.createDialogArea(parent);
|
||||||
|
|
||||||
|
boolean requiresCaptiveLibs = !requiredLibs.isEmpty();
|
||||||
|
String message = requiresCaptiveLibs
|
||||||
|
? "Following libraries are missing from the project's classpath. \r\n" +
|
||||||
|
"The plugin's captive version of these libraries will be added to the project's classpath.\r\n" +
|
||||||
|
"If you want to add the libraries manually later, please uncheck the box."
|
||||||
|
: "Required libraries are already available to the project's classpath";
|
||||||
|
|
||||||
|
addLibrary = createCheckBox(composite, message, PluginProperty.REQUIRES_CAPTIVE_LIBS);
|
||||||
|
addLibrary.setSelection(requiresCaptiveLibs);
|
||||||
|
addLibrary.setEnabled(requiresCaptiveLibs);
|
||||||
|
if (requiresCaptiveLibs) {
|
||||||
|
org.eclipse.swt.widgets.List libList = new
|
||||||
|
org.eclipse.swt.widgets.List(composite, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL);
|
||||||
|
for (String lib : requiredLibs)
|
||||||
|
libList.add(lib);
|
||||||
|
libList.setEnabled(false);
|
||||||
|
}
|
||||||
|
final Group enhanceOptions = new Group(composite, SWT.NONE);
|
||||||
|
enhanceOptions.setText("Bytecode Enhancement Options");
|
||||||
|
GridLayout layout = new GridLayout();
|
||||||
|
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
|
||||||
|
layout.marginTop = 10;
|
||||||
|
layout.marginBottom = 10;
|
||||||
|
enhanceOptions.setLayout(layout);
|
||||||
|
enhanceOptions.setLayoutData(gridData);
|
||||||
|
|
||||||
|
Button overwrite = createCheckBox(enhanceOptions, "Overwrite *.class files");
|
||||||
|
overwrite.setSelection(true);
|
||||||
|
overwrite.setGrayed(true);
|
||||||
|
overwrite.setEnabled(false);
|
||||||
|
|
||||||
|
Button output = createCheckBox(enhanceOptions, "Write enhanced classes", null);
|
||||||
|
output.setSelection(true);
|
||||||
|
output.setGrayed(true);
|
||||||
|
output.setEnabled(false);
|
||||||
|
|
||||||
|
createCheckBox(enhanceOptions, "Add no-arg constructor to persistent entity", PluginProperty.ADD_CONSTRUCTOR);
|
||||||
|
createCheckBox(enhanceOptions, "Enforce Property Restriction", PluginProperty.ENFORCE_PROP);
|
||||||
|
|
||||||
|
new Label(parent, SWT.NONE); // empty space
|
||||||
|
Label endBar = new Label(parent, SWT.HORIZONTAL | SWT.SEPARATOR);
|
||||||
|
endBar.setLayoutData(new GridData(GridData.GRAB_VERTICAL|GridData.FILL_HORIZONTAL));
|
||||||
|
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getAddLibrary() {
|
||||||
|
return addLibrary.getSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
Button createCheckBox(Composite parent, String text) {
|
||||||
|
return createCheckBox(parent, text, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Button createCheckBox(Composite parent, String text, QualifiedName prop) {
|
||||||
|
Button b = new Button(parent, SWT.CHECK);
|
||||||
|
b.setText(text);
|
||||||
|
GridData gridData = new GridData(GridData.FILL, GridData.CENTER, true, false);
|
||||||
|
b.setLayoutData(gridData);
|
||||||
|
if (prop != null) {
|
||||||
|
b.addSelectionListener(new BooleanPropertyRegister(b, prop));
|
||||||
|
try {
|
||||||
|
boolean selected = "true".equals(project.getPersistentProperty(prop));
|
||||||
|
b.setSelection(selected);
|
||||||
|
} catch (CoreException ex) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks the given boolean property of a project by selection state of the given button.
|
||||||
|
*
|
||||||
|
* @author Pinaki Poddar
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private class BooleanPropertyRegister implements SelectionListener {
|
||||||
|
private Button button;
|
||||||
|
private QualifiedName property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the state of the given button according to the boolean value of the given property.
|
||||||
|
* @param b the button to attach to the given property.
|
||||||
|
* @param p the property to track
|
||||||
|
*/
|
||||||
|
public BooleanPropertyRegister(Button b, QualifiedName p) {
|
||||||
|
button = b;
|
||||||
|
property = p;
|
||||||
|
if (property != null) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void widgetDefaultSelected(SelectionEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
if (property != null) {
|
||||||
|
try {
|
||||||
|
project.setPersistentProperty(property, ""+button.getSelection());
|
||||||
|
} catch (CoreException ex) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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.apache.openjpa.eclipse.ui;
|
||||||
|
|
||||||
|
import org.apache.openjpa.eclipse.Activator;
|
||||||
|
import org.apache.openjpa.eclipse.OpenJPANature;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.jface.resource.ImageDescriptor;
|
||||||
|
import org.eclipse.jface.viewers.IDecoration;
|
||||||
|
import org.eclipse.jface.viewers.ILabelProviderListener;
|
||||||
|
import org.eclipse.jface.viewers.ILightweightLabelDecorator;
|
||||||
|
import org.eclipse.jface.viewers.LabelProvider;
|
||||||
|
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the project root node with an image if OpenJPA nature is enabled for the project.
|
||||||
|
*
|
||||||
|
* @author Pinaki Poddar
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ProjectDecorator extends LabelProvider implements ILightweightLabelDecorator, ILabelProviderListener {
|
||||||
|
public static final String DECORATOR_ID = "org.apache.openjpa.eclipse.Decorator";
|
||||||
|
public static final ImageDescriptor decor = Activator.getImageDescriptor("icons/apache-feather-small.jpg");
|
||||||
|
|
||||||
|
public ProjectDecorator() {
|
||||||
|
addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorate the project root if it has the OpenJPA nature.
|
||||||
|
*/
|
||||||
|
public void decorate(Object element, IDecoration decoration) {
|
||||||
|
if (!(element instanceof IProject)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (((IProject)element).hasNature(OpenJPANature.NATURE_ID)) {
|
||||||
|
decoration.addOverlay(decor);
|
||||||
|
} else {
|
||||||
|
decoration.addOverlay(null);
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
removeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the label will be affected by the change in the given property of the given element.
|
||||||
|
* Always returns false.
|
||||||
|
*/
|
||||||
|
public boolean isLabelProperty(Object element, String property) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fireLabelProviderChanged(LabelProviderChangedEvent e) {
|
||||||
|
super.fireLabelProviderChanged(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void labelProviderChanged(LabelProviderChangedEvent event) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 the original author or authors.
|
||||||
|
*
|
||||||
|
* 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.apache.openjpa.eclipse.ui;
|
||||||
|
|
||||||
|
import org.apache.openjpa.eclipse.PluginProperty;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dialog to confirm removing the nature from user project.
|
||||||
|
*
|
||||||
|
* @author Pinaki Poddar
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class RemoveNatureDialog extends AbstractDialog {
|
||||||
|
|
||||||
|
public RemoveNatureDialog(Shell parentShell, IProject project, String header, String title, String message) {
|
||||||
|
super(parentShell, project, header, title, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the dialog's content area.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected Control createDialogArea(Composite parent) {
|
||||||
|
Composite composite = (Composite)super.createDialogArea(parent);
|
||||||
|
boolean warn = false;
|
||||||
|
try {
|
||||||
|
warn = "true".equalsIgnoreCase(project.getPersistentProperty(PluginProperty.USING_CAPTIVE_LIBS));
|
||||||
|
} catch (CoreException e) {
|
||||||
|
}
|
||||||
|
String message = warn
|
||||||
|
? "Disabling OpenJPA will remove runtime libraries added to " + project.getName() + ".\r\n" +
|
||||||
|
"This project may not build after removing these libraries.\r\n" +
|
||||||
|
"Are you sure you want to remove OpenJPA nature from " + project.getName() + "?"
|
||||||
|
: "Remove OpenJPA nature from" + project.getName() + "?";
|
||||||
|
new Label(composite, SWT.NONE).setText(message);
|
||||||
|
|
||||||
|
Label endBar = new Label(parent, SWT.HORIZONTAL | SWT.SEPARATOR);
|
||||||
|
endBar.setLayoutData(new GridData(GridData.GRAB_VERTICAL|GridData.FILL_HORIZONTAL));
|
||||||
|
|
||||||
|
return composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test
|
||||||
|
* @param args
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Display d = Display.getDefault();//PlatformUI.getWorkbench().getDisplay();
|
||||||
|
Shell shell = new Shell(d);
|
||||||
|
RemoveNatureDialog dialog = new RemoveNatureDialog(shell, null, "Test Header", "Test Title", "Test Message");
|
||||||
|
dialog.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.openjpa.eclipse.Activator;
|
import org.apache.openjpa.eclipse.Activator;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
@ -37,18 +36,31 @@ import org.eclipse.jdt.launching.JavaRuntime;
|
||||||
* @author Michael Vorburger
|
* @author Michael Vorburger
|
||||||
*/
|
*/
|
||||||
public class ClassLoaderFromIProjectHelper {
|
public class ClassLoaderFromIProjectHelper {
|
||||||
|
private static final char BACKSLASH = '\\';
|
||||||
|
private static final char FORWARDSLASH = '/';
|
||||||
|
private static final String PROTOCOL_FILE = "file:///";
|
||||||
|
private static final String JAR_EXTENSION = ".jar";
|
||||||
|
private static final String DIRECTORY_MARKER = "/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a classloader for the given Eclipse Project.
|
||||||
|
*
|
||||||
|
* @param project a Eclipse Java Project
|
||||||
|
* @return a URLClassLoader with the configured classpath of the given project
|
||||||
|
* @throws CoreException
|
||||||
|
*/
|
||||||
public static ClassLoader createClassLoader(IProject project) throws CoreException {
|
public static ClassLoader createClassLoader(IProject project) throws CoreException {
|
||||||
IJavaProject javaProject = JavaCore.create(project);
|
IJavaProject javaProject = JavaCore.create(project);
|
||||||
String[] classPath = JavaRuntime.computeDefaultRuntimeClassPath(javaProject);
|
String[] classPath = JavaRuntime.computeDefaultRuntimeClassPath(javaProject);
|
||||||
URL[] urls = new URL[classPath.length];
|
URL[] urls = new URL[classPath.length];
|
||||||
for(int i=0;i<classPath.length;i++) {
|
for(int i=0; i < classPath.length; i++) {
|
||||||
try {
|
try {
|
||||||
String urlString = "file:///" + classPath[i].replace('\\', '/');
|
String urlString = PROTOCOL_FILE + classPath[i].replace(BACKSLASH, FORWARDSLASH);
|
||||||
|
|
||||||
// make sure that directory URLs end with a slash as they are otherwise not
|
// make sure that directory URLs end with a slash as they are otherwise not
|
||||||
// treated as directories but as libraries by the URLClassLoader
|
// treated as directories but as libraries by the URLClassLoader
|
||||||
if(!classPath[i].endsWith(".jar") && !classPath[i].endsWith("/")) urlString += "/";
|
if(!classPath[i].endsWith(JAR_EXTENSION) && !classPath[i].endsWith(DIRECTORY_MARKER))
|
||||||
|
urlString += DIRECTORY_MARKER;
|
||||||
urls[i] = new URL(urlString);
|
urls[i] = new URL(urlString);
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
|
throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
|
||||||
|
@ -57,4 +69,18 @@ public class ClassLoaderFromIProjectHelper {
|
||||||
}
|
}
|
||||||
return URLClassLoader.newInstance(urls);
|
return URLClassLoader.newInstance(urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the class of the given name by loading it using the given project's classpath.
|
||||||
|
*
|
||||||
|
* @return null if the given class can not be loaded.
|
||||||
|
*/
|
||||||
|
public static Class<?> findClass(String className, IProject project) {
|
||||||
|
try {
|
||||||
|
return Class.forName(className, false, createClassLoader(project));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import serp.bytecode.BCClass;
|
||||||
import serp.bytecode.Project;
|
import serp.bytecode.Project;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OpenJPA Enhancer helper, for efficient invocation from an Eclipse builder.
|
* OpenJPA Enhancer for efficient invocation from an Eclipse builder.
|
||||||
*
|
*
|
||||||
* @author Pinaki Poddar
|
* @author Pinaki Poddar
|
||||||
* @author Michael Vorburger (refactoring and extensions)
|
* @author Michael Vorburger (refactoring and extensions)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 794 B |
Binary file not shown.
After Width: | Height: | Size: 8.7 KiB |
|
@ -42,7 +42,7 @@
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -67,4 +67,5 @@
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
Loading…
Reference in New Issue