diff options
author | Jose <jose@zeroc.com> | 2011-12-10 01:57:19 +0100 |
---|---|---|
committer | Jose <jose@zeroc.com> | 2011-12-10 01:57:19 +0100 |
commit | 42e31f18dc2f34c6b0c427ca0a976ac795349864 (patch) | |
tree | 91f81872e55f06c5d6b859039e3c2a633c70c684 /eclipse/java/Slice2javaPlugin/src | |
parent | ICE-4705 voip glacier2 configuration (diff) | |
download | ice-42e31f18dc2f34c6b0c427ca0a976ac795349864.tar.bz2 ice-42e31f18dc2f34c6b0c427ca0a976ac795349864.tar.xz ice-42e31f18dc2f34c6b0c427ca0a976ac795349864.zip |
Eclipse plug-in updates for release 3.4.2.20111024
Diffstat (limited to 'eclipse/java/Slice2javaPlugin/src')
17 files changed, 4981 insertions, 0 deletions
diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/Activator.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/Activator.java new file mode 100644 index 00000000000..8a4c847b031 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/Activator.java @@ -0,0 +1,181 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; +import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; +import org.eclipse.jdt.core.IJavaModel; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +import com.zeroc.slice2javaplugin.builder.Slice2JavaBuilder; +import com.zeroc.slice2javaplugin.builder.Slice2JavaNature; +import com.zeroc.slice2javaplugin.internal.IceClasspathContainerIntializer; +import com.zeroc.slice2javaplugin.internal.IceClasspathVariableInitializer; +import com.zeroc.slice2javaplugin.preferences.PluginPreferencePage; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin +{ + + // The plug-in ID + public static final String PLUGIN_ID = "com.zeroc.Slice2JavaPlugin"; + + /** + * The constructor + */ + public Activator() + { + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext + * ) + */ + public void start(BundleContext context) + throws Exception + { + super.start(context); + _plugin = this; + + IEclipsePreferences prefs = new InstanceScope().getNode(PLUGIN_ID); + // set the listener for the preference change + //Preferences prefs = getPluginPreferences(); + prefs.addPreferenceChangeListener(new IPreferenceChangeListener() + { + public List<IJavaProject> getSlice2JavaProjects(IJavaModel javaModel) + { + ArrayList<IJavaProject> pl = new ArrayList<IJavaProject>(); + try + { + for(IJavaProject p : javaModel.getJavaProjects()) + { + try + { + if(p.getProject().hasNature(Slice2JavaNature.NATURE_ID)) + { + pl.add(p); + } + } + catch(CoreException e) + { + // The project isn't opened, or does not exist. + } + } + } + catch(JavaModelException jme) + { + } + + return pl; + } + + public void preferenceChange(PreferenceChangeEvent event) + { + String property = event.getKey(); + if(PluginPreferencePage.SDK_PATH.equals(property)) + { + IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + IJavaModel javaModel = JavaCore.create(workspaceRoot); + List<IJavaProject> projects = getSlice2JavaProjects(javaModel); + String value = (String)event.getNewValue(); + IceClasspathContainerIntializer.updateProjects(value, projects); + IceClasspathVariableInitializer.update(value); + // Need to trigger a clean build of the projects. + for(final IJavaProject p : projects) + { + Job job = new Job("Rebuild") + { + protected IStatus run(IProgressMonitor monitor) + { + try + { + p.getProject().build(IncrementalProjectBuilder.FULL_BUILD, Slice2JavaBuilder.BUILDER_ID, null, + monitor); + } + catch(CoreException e) + { + return new Status(Status.ERROR, Activator.PLUGIN_ID, 0, "rebuild failed", e); + } + return Status.OK_STATUS; + } + }; + job.setPriority(Job.BUILD); + job.schedule(); // start as soon as possible + } + } + + } + }); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext + * ) + */ + public void stop(BundleContext context) + throws Exception + { + _plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() + { + return _plugin; + } + + /** + * Returns an image descriptor for the image file at the given plug-in + * relative path + * + * @param path + * the path + * @return the image descriptor + */ + public static ImageDescriptor getImageDescriptor(String path) + { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } + + // The shared instance + private static Activator _plugin; +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/Slice2JavaBuilder.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/Slice2JavaBuilder.java new file mode 100644 index 00000000000..d65596deb95 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/Slice2JavaBuilder.java @@ -0,0 +1,1282 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.builder; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IResourceVisitor; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.console.ConsolePlugin; +import org.eclipse.ui.console.IConsole; +import org.eclipse.ui.console.IConsoleManager; +import org.eclipse.ui.console.MessageConsole; +import org.eclipse.ui.console.MessageConsoleStream; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import com.zeroc.slice2javaplugin.Activator; +import com.zeroc.slice2javaplugin.internal.Configuration; +import com.zeroc.slice2javaplugin.internal.Dependencies; + +public class Slice2JavaBuilder extends IncrementalProjectBuilder +{ + public static final String BUILDER_ID = "com.zeroc.Slice2JavaPlugin.Slice2JavaBuilder"; + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.internal.events.InternalBuilder#build(int, + * java.util.Map, org.eclipse.core.runtime.IProgressMonitor) + */ + protected IProject[] build(int kind, @SuppressWarnings("rawtypes")Map args, IProgressMonitor monitor) + throws CoreException + { + long start = System.currentTimeMillis(); + + IResourceDelta delta = getDelta(getProject()); + BuildState state = new BuildState(getProject(), delta, monitor); + state.dependencies.read(); + + try + { + if(kind == FULL_BUILD) + { + fullBuild(state, monitor); + } + else + { + if(delta == null) + { + fullBuild(state, monitor); + } + else + { + incrementalBuild(state, monitor); + } + } + } + finally + { + long end = System.currentTimeMillis(); + if(state.out != null) + { + state.out.println("Build complete. Elapsed time: " + (end - start) / 1000 + "s."); + } + state.dependencies.write(); + } + return null; + } + + protected void clean(IProgressMonitor monitor) + throws CoreException + { + BuildState state = new BuildState(getProject(), null, monitor); + + // Don't read the existing dependencies. That will have the + // effect of trashing them. + + try + { + // Now, clean the generated sub-directory. + Set<IFile> files = new HashSet<IFile>(); + getResources(files, state.generated.members()); + + for(IFile file : files) + { + // Don't delete "." files (such as .gitignore). + if(!file.getName().startsWith(".")) + { + file.delete(true, false, monitor); + } + } + } + finally + { + state.dependencies.write(); + } + } + + static class StreamReaderThread extends Thread + { + public StreamReaderThread(InputStream in, StringBuffer out) + { + _in = new BufferedReader(new InputStreamReader(in), 1024); + _out = out; + } + + public void run() + { + try + { + char[] buf = new char[1024]; + while(true) + { + int read = _in.read(buf); + if(read == -1) + { + break; + } + _out.append(buf, 0, read); + } + } + catch(Exception e) + { + } + finally + { + try + { + _in.close(); + } + catch(IOException e1) + { + e1.printStackTrace(); + } + } + } + + private StringBuffer _out; + private BufferedReader _in; + } + + static class BuildState + { + BuildState(IProject project, IResourceDelta delta, IProgressMonitor monitor) throws CoreException + { + config = new Configuration(project); + + if(config.getConsole()) + { + initializeConsole(); + out = _consoleout; + err = _consoleerr; + } + + generated = project.getFolder(config.getGeneratedDir()); + if(!generated.exists()) + { + generated.create(false, true, monitor); + } + + _sourceLocations = new HashSet<IFolder>(); + for(Iterator<String> p = config.getSliceSourceDirs().iterator(); p.hasNext();) + { + _sourceLocations.add(project.getFolder(p.next())); + } + + project.accept(new IResourceVisitor() + { + public boolean visit(IResource resource) + throws CoreException + { + if(resource instanceof IFile) + { + IFile file = (IFile) resource; + if(filter(file)) + { + _resources.add((IFile) resource); + } + } + return true; + } + }); + + if(delta != null) + { + delta.accept(new IResourceDeltaVisitor() + { + public boolean visit(IResourceDelta delta) + throws CoreException + { + IResource resource = delta.getResource(); + if(resource instanceof IFile) + { + IFile file = (IFile) resource; + if(filter(file)) + { + switch (delta.getKind()) + { + case IResourceDelta.ADDED: + case IResourceDelta.CHANGED: + _deltaCandidates.add(file); + break; + case IResourceDelta.REMOVED: + _removed.add(file); + break; + } + } + } + return true; + } + }); + } + + dependencies = new Dependencies(project, _resources, err); + } + + public Set<IFile> deltas() + { + return _deltaCandidates; + } + + public List<IFile> removed() + { + return _removed; + } + + public Set<IFile> resources() + { + return _resources; + } + + public boolean filter(IFile file) + { + String ext = file.getFileExtension(); + if(ext != null && ext.equals("ice")) + { + // + // The parent may not be an IFolder (e.g., it could be a Project). + // + if(file.getParent() instanceof IFolder) + { + IFolder folder = (IFolder)file.getParent(); + if(_sourceLocations.contains(folder)) + { + return true; + } + } + } + return false; + } + + synchronized static private void initializeConsole() + { + if(_consoleout == null) + { + MessageConsole console = new MessageConsole("slice2java", null); + IConsole[] ics = new IConsole[1]; + ics[0] = console; + IConsoleManager csmg = ConsolePlugin.getDefault().getConsoleManager(); + csmg.addConsoles(ics); + csmg.showConsoleView(console); + + _consoleout = console.newMessageStream(); + _consoleerr = console.newMessageStream(); + + final Display display = PlatformUI.getWorkbench().getDisplay(); + display.syncExec(new Runnable() { + public void run() { + _consoleerr.setColor(display.getSystemColor(SWT.COLOR_RED)); + } + }); + } + } + + Configuration config; + Dependencies dependencies; + IFolder generated; + private Set<IFolder> _sourceLocations; + + private Set<IFile> _resources = new HashSet<IFile>(); + private Set<IFile> _deltaCandidates = new HashSet<IFile>(); + private List<IFile> _removed = new ArrayList<IFile>(); + + private MessageConsoleStream out = null; + private MessageConsoleStream err = null; + + static private MessageConsoleStream _consoleout = null; + static private MessageConsoleStream _consoleerr = null; + } + + private int build(BuildState state, Set<IFile> files, boolean depend, StringBuffer out, StringBuffer err) + throws CoreException + { + // Clear the output buffer. + out.setLength(0); + if(err != null) + { + err.setLength(0); + } + + List<String> cmd = new LinkedList<String>(); + String translator = state.config.getTranslator(); + if(translator == null) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Cannot locate slice2java translator: please fix Ice install location", null)); + } + + cmd.add(translator); + if(depend) + { + cmd.add("--depend-xml"); + } + else + { + cmd.add("--output-dir=" + state.generated.getProjectRelativePath().toString()); + cmd.add("--list-generated"); + } + List<String> cmdBase = new LinkedList<String>(); + cmdBase.addAll(cmd); + + cmd.addAll(state.config.getCommandLine()); + + Set<IFile> resourcesWithArguments = new HashSet<IFile>(); + + boolean allHasOptions = true; + for(Iterator<IFile> p = files.iterator(); p.hasNext();) + { + IFile f = p.next(); + if(!Configuration.resourceHasOptions(f)) + { + allHasOptions = false; + cmd.add(f.getLocation().toOSString()); + } + else + { + resourcesWithArguments.add(f); + } + } + + ProcessBuilder builder; + IPath rootLocation = getProject().getLocation(); + Map<String, String> env; + int status = 0; + + if(!allHasOptions) + { + builder = new ProcessBuilder(cmd); + if(err == null) + { + builder.redirectErrorStream(true); + } + + builder.directory(rootLocation.toFile()); + env = builder.environment(); + Configuration.setupSharedLibraryPath(env); + + status = runSliceCompiler(builder, state, out, err); + } + + for(Iterator<IFile> p = resourcesWithArguments.iterator(); p.hasNext();) + { + IFile f = p.next(); + cmd = new LinkedList<String>(); + cmd.addAll(cmdBase); + cmd.addAll(state.config.getCommandLine(f)); + + cmd.add(f.getLocation().toOSString()); + + builder = new ProcessBuilder(cmd); + if(err == null) + { + builder.redirectErrorStream(true); + } + builder.directory(rootLocation.toFile()); + env = builder.environment(); + Configuration.setupSharedLibraryPath(env); + + status = runSliceCompiler(builder, state, out, err); + } + + return status; + } + + private int + runSliceCompiler(ProcessBuilder builder, BuildState state, StringBuffer out, StringBuffer err) + throws CoreException + { + try + { + + + if(state.out != null) + { + for(Iterator<String> p = builder.command().iterator(); p.hasNext();) + { + state.out.print(p.next()); + state.out.print(" "); + } + state.out.println(""); + } + + Process proc = builder.start(); + + StreamReaderThread outThread = new StreamReaderThread(proc.getInputStream(), out); + outThread.start(); + StreamReaderThread errThread = null; + if(err != null) + { + errThread = new StreamReaderThread(proc.getErrorStream(), err); + errThread.start(); + } + + int status = proc.waitFor(); + + outThread.join(); + if(errThread != null) + { + errThread.join(); + } + + if(status != 0 && state.err != null) + { + state.err.println("slice2java status: " + status); + } + + return status; + } + catch(Exception e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.toString(), null)); + } + } + + private void + createMarker(BuildState state, IFile source, IPath filename, int line, String msg) + throws CoreException + { + // Process the error. + IPath dir = getProject().getLocation(); + + IFile file = null; + if(filename != null && dir.isPrefixOf(filename)) + { + // Locate the file within the project. + file = getProject().getFile(filename.removeFirstSegments(dir.segmentCount())); + + // If the file is not the current source file, and the file exists in the project + // then it must already contain a marker, so don't place another. + if(!file.equals(source) && state.filter(file)) + { + return; + } + } + + // If the message isn't contained in the source file, then identify the + // file:line in the message itself. + if(file == null) + { + if(line != -1) + { + msg = filename + ":" + line + ": " + msg; + } + else + { + msg = filename + ": " + msg; + } + } + + IMarker marker = source.createMarker(IMarker.PROBLEM); + marker.setAttribute(IMarker.MESSAGE, msg); + if(msg.toLowerCase().indexOf("warning:") >= 0) + { + marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); + } + else + { + marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); + } + if(line != -1) + { + if(file != null && file.equals(source)) + { + marker.setAttribute(IMarker.LINE_NUMBER, line); + } + else + { + marker.setAttribute(IMarker.LINE_NUMBER, 1); + } + } + } + + private void createMarkers(BuildState state, IFile source, String output) + throws CoreException + { + output = output.trim(); + if(output.length() == 0) + { + return; + } + + String[] lines = output.split("\n"); + + IPath filename = null; + int line = -1; + StringBuffer msg = new StringBuffer(); + + boolean continuation = false; + + for(int i = 0; i < lines.length; ++i) + { + if(continuation) + { + if(lines[i].startsWith(" ")) + { + // Continuation of the previous message. + msg.append(lines[i]); + continue; + } + else + { + // Process the message. + createMarker(state, source, filename, line, msg.toString()); + } + } + + // We're on a new message. + msg.setLength(0); + continuation = false; + + // Ignore. + if(lines[i].contains("errors in preprocessor") || lines[i].contains("error in preprocessor")) + { + continue; + } + + // + // Parse a line of the form: + // + // file:[line:] message + // + int start = 0; + int end; + // Handle drive letters. + if(lines[i].length() > 2 && lines[i].charAt(1) == ':') + { + end = lines[i].indexOf(':', 2); + } + else + { + end = lines[i].indexOf(':'); + } + if(end != -1) + { + filename = new Path(lines[i].substring(start, end)); + start = end + 1; + end = lines[i].indexOf(':', start); + if(end != -1) + { + try + { + line = Integer.parseInt(lines[i].substring(start, end)); + start = end + 1; + } + catch(NumberFormatException e) + { + // The message may not have a line number. + line = -1; + } + msg.append(lines[i].substring(start, lines[i].length())); + + continuation = true; + continue; + } + } + // Unknown format. + createMarker(state, source, null, -1, lines[i]); + } + + if(continuation) + { + createMarker(state, source, filename, line, msg.toString()); + } + } + + private void getResources(Set<IFile> files, IResource[] members) + throws CoreException + { + for(int i = 0; i < members.length; ++i) + { + if(members[i] instanceof IFile) + { + files.add((IFile) members[i]); + } + else if(members[i] instanceof IFolder) + { + getResources(files, ((IFolder) members[i]).members()); + } + } + } + + private void fullBuild(BuildState state, final IProgressMonitor monitor) + throws CoreException + { + clean(monitor); + Set<IFile> candidates = state.resources(); + if(candidates.isEmpty()) + { + return; + } + + if(state.out != null) + { + java.util.Date date = new java.util.Date(); + state.out.println("Start full build at " + new SimpleDateFormat("HH:mm:ss").format(date)); + + state.out.println("Candidate list:"); + // This is a complete list of Slice files. + for(Iterator<IFile> p = candidates.iterator(); p.hasNext();) + { + state.out.println(" " + p.next().getProjectRelativePath().toString()); + } + state.out.println("Regenerating java source files."); + } + + StringBuffer out = new StringBuffer(); + + Set<IFile> depends = new HashSet<IFile>(); + + // Delete each marker. + for(Iterator<IFile> p = candidates.iterator(); p.hasNext();) + { + IFile file = p.next(); + file.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); + } + + // Do the build. + build(state, candidates, false, out, null); + + out = mergeXmls(out, false); + + // Refresh the generated subdirectory prior to processing the + // generated files list. + state.generated.refreshLocal(IResource.DEPTH_INFINITE, monitor); + + // Parse the output. + Slice2JavaGeneratedParser parser = getGeneratedFiles(state, candidates, out); + for(Map.Entry<IFile, Slice2JavaGeneratedParser.Entry> entry : parser.output.entrySet()) + { + IFile source = entry.getKey(); + + Slice2JavaGeneratedParser.Entry outputEntry = entry.getValue(); + Set<IFile> newGeneratedJavaFiles = outputEntry.files; + + for(IFile f : newGeneratedJavaFiles) + { + // Mark the resource as derived. + f.setDerived(true, null); + } + + if(!outputEntry.error) + { + depends.add(source); + if(state.out != null) + { + if(newGeneratedJavaFiles.isEmpty()) + { + state.out.println(source.getProjectRelativePath().toString() + ": No java files emitted."); + } + else + { + state.out.println(source.getProjectRelativePath().toString() + ": Emitted:"); + for(Iterator<IFile> q = newGeneratedJavaFiles.iterator(); q.hasNext();) + { + state.out.println(" " + q.next().getProjectRelativePath().toString()); + } + } + } + } + else + { + state.dependencies.errorSliceFiles.add(source); + if(state.out != null) + { + state.out.println(source.getProjectRelativePath().toString() + ": Error."); + } + } + + // Update the set of slice -> java dependencies. + state.dependencies.sliceJavaDependencies.put(source, newGeneratedJavaFiles); + + // Create markers for each warning/error. + createMarkers(state, source, outputEntry.output); + } + + // Update the slice->slice dependencies. + // Only update the dependencies for those files with no build problems. + if(!depends.isEmpty()) + { + if(state.out != null) + { + state.out.println("Updating dependencies."); + } + + StringBuffer err = new StringBuffer(); + if(build(state, depends, true, out, err) == 0) + { + out = mergeXmls(out, true); + // Parse the new dependency set. + state.dependencies.updateDependencies(out.toString()); + } + else if(state.err != null) + { + state.err.println("Dependencies not updated due to error."); + state.err.println(err.toString()); + } + } + } + + private void incrementalBuild(BuildState state, IProgressMonitor monitor) + throws CoreException + { + Set<IFile> candidates = state.deltas(); + List<IFile> removed = state.removed(); + + if(state.out != null) + { + java.util.Date date = new java.util.Date(); + state.out.println("Start incremental build at " + new SimpleDateFormat("HH:mm:ss").format(date)); + + state.out.println("Candidate list:"); + // This is a complete list of slice files. + for(Iterator<IFile> p = candidates.iterator(); p.hasNext();) + { + state.out.println(" + " + p.next().getProjectRelativePath().toString()); + } + for(Iterator<IFile> p = removed.iterator(); p.hasNext();) + { + state.out.println(" - " + p.next().getProjectRelativePath().toString()); + } + } + + // The orphan candidate set. + Set<IFile> orphanCandidateSet = new HashSet<IFile>(); + + // Go through the removed list, removing the dependencies. + for(Iterator<IFile> p = removed.iterator(); p.hasNext();) + { + IFile f = p.next(); + + // Remove the file from the error list, if necessary. + if(state.dependencies.errorSliceFiles.contains(f)) + { + state.dependencies.errorSliceFiles.remove(f); + } + + Set<IFile> dependents = state.dependencies.sliceSliceDependencies.remove(f); + if(dependents != null) + { + Iterator<IFile> dependentsIterator = dependents.iterator(); + while(dependentsIterator.hasNext()) + { + IFile dependent = dependentsIterator.next(); + Set<IFile> files = state.dependencies.reverseSliceSliceDependencies.get(dependent); + if(files != null) + { + files.remove(f); + } + } + } + + Set<IFile> oldJavaFiles = state.dependencies.sliceJavaDependencies.remove(f); + if(state.out != null) + { + if(oldJavaFiles == null || oldJavaFiles.isEmpty()) + { + state.out.println(f.getProjectRelativePath().toString() + ": No orphans."); + } + else + { + state.out.println(f.getProjectRelativePath().toString() + ": Orphans:"); + for(Iterator<IFile> q = oldJavaFiles.iterator(); q.hasNext();) + { + state.out.println(" " + q.next().getProjectRelativePath().toString()); + } + } + } + + if(oldJavaFiles != null) + { + orphanCandidateSet.addAll(oldJavaFiles); + } + } + + // Add the removed files to the candidates set + // prior to determining additional candidates. + candidates.addAll(removed); + + // Add to the candidate set any slice files that are in error. Clear the + // error list. + candidates.addAll(state.dependencies.errorSliceFiles); + state.dependencies.errorSliceFiles.clear(); + + Set<IFile> candidatesTmp = new HashSet<IFile>(); + + for(Iterator<IFile> p = candidates.iterator(); p.hasNext();) + { + IFile f = p.next(); + + Set<IFile> files = state.dependencies.reverseSliceSliceDependencies.get(f); + if(files != null) + { + for(Iterator<IFile> q = files.iterator(); q.hasNext();) + { + IFile potentialCandidate = q.next(); + if(potentialCandidate.exists()) + { + candidatesTmp.add(potentialCandidate); + } + } + } + + // If this is a file in the contained list, then remove the + // dependency entry. + if(removed.contains(f)) + { + state.dependencies.reverseSliceSliceDependencies.remove(f); + } + } + candidates.addAll(candidatesTmp); + + // Remove all the removed files from the candidates list. + candidates.removeAll(removed); + + if(state.out != null) + { + if(candidates.isEmpty()) + { + state.out.println("No remaining candidates."); + } + else + { + state.out.println("Expanded candidate list:"); + // This is a complete list of slice files. + for(Iterator<IFile> p = candidates.iterator(); p.hasNext();) + { + state.out.println(" " + p.next().getProjectRelativePath().toString()); + } + } + } + + StringBuffer out = new StringBuffer(); + + // The set of files that we'll generate dependencies for. + Set<IFile> depends = new HashSet<IFile>(); + + if(!candidates.isEmpty()) + { + if(state.out != null) + { + state.out.println("Regenerating java source files."); + } + + // The complete set of generated java files by this build. + Set<IFile> generatedJavaFiles = new HashSet<IFile>(); + + // Remove all markers for the candidate list. + for(Iterator<IFile> p = candidates.iterator(); p.hasNext();) + { + IFile file = p.next(); + file.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); + } + + // Do the build. + build(state, candidates, false, out, null); + out = mergeXmls(out, false); + + // Refresh the generated directory prior to processing the generated + // files list. + state.generated.refreshLocal(IResource.DEPTH_INFINITE, monitor); + + // Parse the emitted XML file that describes what was produced by + // the build. + Slice2JavaGeneratedParser parser = getGeneratedFiles(state, candidates, out); + for(Map.Entry<IFile, Slice2JavaGeneratedParser.Entry> entry : parser.output.entrySet()) + { + IFile source = entry.getKey(); + + Slice2JavaGeneratedParser.Entry outputEntry = entry.getValue(); + + Set<IFile> newGeneratedJavaFiles = outputEntry.files; + for(IFile f : newGeneratedJavaFiles) + { + // Mark the resource as derived. + f.setDerived(true, null); + } + + // If the build of the file didn't result in an error, add to + // the dependencies list. Otherwise, add to the error list. + if(!outputEntry.error) + { + depends.add(source); + } + else + { + if(state.out != null) + { + state.out.println(source.getProjectRelativePath().toString() + ": Error."); + } + state.dependencies.errorSliceFiles.add(source); + } + + // Compute the set difference between the old set and new set + // of generated files. The difference should be added to the + // orphan candidate set. + Set<IFile> oldJavaFiles = state.dependencies.sliceJavaDependencies.get(source); + if(oldJavaFiles != null) + { + // Compute the set difference. + oldJavaFiles.removeAll(newGeneratedJavaFiles); + if(state.out != null) + { + if(oldJavaFiles.isEmpty()) + { + state.out.println(source.getProjectRelativePath().toString() + ": No orphans."); + } + else + { + state.out.println(source.getProjectRelativePath().toString() + ": Orphans:"); + for(Iterator<IFile> q = oldJavaFiles.iterator(); q.hasNext();) + { + state.out.println(" " + q.next().getProjectRelativePath().toString()); + } + } + } + orphanCandidateSet.addAll(oldJavaFiles); + } + + // Update the set of slice -> java dependencies. + state.dependencies.sliceJavaDependencies.put(source, newGeneratedJavaFiles); + + // If the build resulted in an error, there will be no java source files. + if(state.out != null && !outputEntry.error) + { + if(newGeneratedJavaFiles.isEmpty()) + { + state.out.println(source.getProjectRelativePath().toString() + ": No java files emitted."); + } + else + { + state.out.println(source.getProjectRelativePath().toString() + ": Emitted:"); + for(Iterator<IFile> q = newGeneratedJavaFiles.iterator(); q.hasNext();) + { + state.out.println(" " + q.next().getProjectRelativePath().toString()); + } + } + } + + generatedJavaFiles.addAll(newGeneratedJavaFiles); + + // Create markers for each warning/error. + createMarkers(state, source, outputEntry.output); + } + + // Do a set difference between the orphan candidate set + // and the complete set of generated java source files. + // Any remaining are complete orphans and should + // be removed. + orphanCandidateSet.removeAll(generatedJavaFiles); + } + + if(state.out != null) + { + if(orphanCandidateSet.isEmpty()) + { + state.out.println("No orphans from this build."); + } + else + { + state.out.println("Orphans from this build:"); + for(Iterator<IFile> p = orphanCandidateSet.iterator(); p.hasNext();) + { + state.out.println(" " + p.next().getProjectRelativePath().toString()); + } + } + } + + // + // Remove orphans. + // + for(Iterator<IFile> p = orphanCandidateSet.iterator(); p.hasNext();) + { + p.next().delete(true, false, monitor); + } + + // The dependencies of any files without build errors should be updated. + if(!depends.isEmpty()) + { + if(state.out != null) + { + state.out.println("Updating dependencies."); + } + + StringBuffer err = new StringBuffer(); + + // We've already added markers for any errors... Only update the + // dependencies if no problems resulted in the build. + if(build(state, depends, true, out, err) == 0) + { + out = mergeXmls(out, true); + // Parse the new dependency set. + state.dependencies.updateDependencies(out.toString()); + } + else if(state.err != null) + { + state.err.println("Dependencies not updated due to error."); + state.err.println(err.toString()); + } + } + } + + // + // This method merge the XML produced by multiple Slice translator + // invocations in a single XML. If depend argument is true, the input + // buffer is treated as a dependencies XML, otherwise is treated as + // a generated list XML. + // + private StringBuffer + mergeXmls(StringBuffer input, boolean depend) + { + // + // Merge depend XMLs in a single XML + // + String v = input.toString(); + StringTokenizer lines = new StringTokenizer(v, System.getProperty("line.separator")); + boolean firstLine = true; + boolean firstGenerated = true; + StringBuffer out = new StringBuffer(); + while(lines.hasMoreTokens()) + { + String line = lines.nextToken(); + if(line.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") && + !firstLine) + { + continue; + } + + if(depend) + { + if(line.equals("<dependencies>")) + { + if(firstGenerated) + { + firstGenerated = false; + } + else + { + continue; + } + } + else if(line.equals("</dependencies>") && lines.hasMoreTokens()) + { + continue; + } + } + else + { + if(line.equals("<generated>")) + { + if(firstGenerated) + { + firstGenerated = false; + } + else + { + continue; + } + } + else if(line.equals("</generated>") && lines.hasMoreTokens()) + { + continue; + } + } + + out.append(line + "\n"); + firstLine = false; + } + return out; + } + + private static class Slice2JavaGeneratedParser + { + static class Entry + { + boolean error; // Did the build result in an error. + String output; // Any warnings/errors from the build. + Set<IFile> files; // The set of java source files associated with the source file. + } + Map<IFile, Entry> output = new HashMap<IFile, Entry>(); // Map of source files to build entry. + + private IFolder _generated; + private IPath _generatedPath; + // Map of absolute path to project location. + private Map<IPath, IFile> _sources = new HashMap<IPath, IFile>(); + + Slice2JavaGeneratedParser(IFolder generated, Set<IFile> candidates) + { + _generated = generated; + _generatedPath = generated.getProjectRelativePath(); + for(IFile f : candidates) + { + _sources.put(f.getLocation(), f); + } + } + + private Node findNode(Node n, String qName) + throws SAXException + { + NodeList children = n.getChildNodes(); + for(int i = 0; i < children.getLength(); ++i) + { + Node child = children.item(i); + if(child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(qName)) + { + return child; + } + } + throw new SAXException("no such node: " + qName); + } + + private IFile convert(String fname) + { + IPath p = new Path(fname); // fname contains "generated/...". + int match = p.matchingFirstSegments(_generatedPath); + return _generated.getFile(p.removeFirstSegments(match)); + } + + public Set<IFile> visitSource(Node source) throws SAXException + { + Set<IFile> files = new HashSet<IFile>(); + NodeList sourceNodes = source.getChildNodes(); + for(int j = 0; j < sourceNodes.getLength(); ++j) + { + if(sourceNodes.item(j).getNodeType() == Node.ELEMENT_NODE && sourceNodes.item(j).getNodeName().equals("file")) + { + Element file = (Element)sourceNodes.item(j); + String name = file.getAttribute("name"); + if(name.length() == 0) + { + throw new SAXException("empty name attribute"); + } + files.add(convert(name)); + } + } + return files; + } + + private String getText(Node n) throws SAXException + { + NodeList children = n.getChildNodes(); + if(children.getLength() == 1 && children.item(0).getNodeType() == Node.TEXT_NODE) + { + return children.item(0).getNodeValue(); + } + return ""; + } + + public void visit(Node doc) throws SAXException + { + Node n = findNode(doc, "generated"); + NodeList fileNodes = n.getChildNodes(); + for(int j = 0; j < fileNodes.getLength(); ++j) + { + if(fileNodes.item(j).getNodeType() == Node.ELEMENT_NODE && fileNodes.item(j).getNodeName().equals("source")) + { + Element sourceElement = (Element)fileNodes.item(j); + String name = sourceElement.getAttribute("name"); + if(name.length() == 0) + { + throw new SAXException("empty name attribute"); + } + + // The source file + IFile source = _sources.get(new Path(name)); + if(source == null) + { + throw new SAXException("unknown source file: " + name); + } + + Entry e = new Entry(); + e.error = true; + e.output = getText(findNode(sourceElement, "output")); + + String error = sourceElement.getAttribute("error"); + if(error.equals("true")) + { + e.error = true; + e.files = new HashSet<IFile>(); + } + else + { + e.error = false; + e.files = visitSource(sourceElement); + } + output.put(source, e); + } + } + } + } + + private Slice2JavaGeneratedParser getGeneratedFiles(BuildState state, Set<IFile> candidates, StringBuffer out) + throws CoreException + { + Slice2JavaGeneratedParser parser = new Slice2JavaGeneratedParser(state.generated, candidates); + try + { + InputStream in = new ByteArrayInputStream(out.toString().getBytes()); + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new BufferedInputStream(in)); + parser.visit(doc); + } + catch(SAXException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading the generated output list", e)); + } + catch(ParserConfigurationException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading the generated output list", e)); + } + catch(IOException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading the generated output list", e)); + } + return parser; + } +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/Slice2JavaNature.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/Slice2JavaNature.java new file mode 100644 index 00000000000..af9710ee4b8 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/Slice2JavaNature.java @@ -0,0 +1,108 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.builder; + +import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IProjectNature; +import org.eclipse.core.runtime.CoreException; + +import com.zeroc.slice2javaplugin.internal.Configuration; + +public class Slice2JavaNature implements IProjectNature +{ + /** + * ID of this project nature + */ + public static final String NATURE_ID = "com.zeroc.Slice2JavaPlugin.Slice2JavaNature"; + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.resources.IProjectNature#configure() + */ + public void configure() + throws CoreException + { + IProjectDescription desc = _project.getDescription(); + ICommand[] commands = desc.getBuildSpec(); + + for(int i = 0; i < commands.length; ++i) + { + if(commands[i].getBuilderName().equals(Slice2JavaBuilder.BUILDER_ID)) + { + return; + } + } + + ICommand[] newCommands = new ICommand[commands.length + 1]; + System.arraycopy(commands, 0, newCommands, 1, commands.length); + ICommand command = desc.newCommand(); + command.setBuilderName(Slice2JavaBuilder.BUILDER_ID); + newCommands[0] = command; + desc.setBuildSpec(newCommands); + + _project.setDescription(desc, null); + + // Initialize a new configuration for this project. + Configuration config = new Configuration(_project); + config.initialize(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.resources.IProjectNature#deconfigure() + */ + public void deconfigure() + throws CoreException + { + IProjectDescription description = getProject().getDescription(); + ICommand[] commands = description.getBuildSpec(); + for(int i = 0; i < commands.length; ++i) + { + if(commands[i].getBuilderName().equals(Slice2JavaBuilder.BUILDER_ID)) + { + ICommand[] newCommands = new ICommand[commands.length - 1]; + System.arraycopy(commands, 0, newCommands, 0, i); + System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1); + description.setBuildSpec(newCommands); + return; + } + } + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.resources.IProjectNature#getProject() + */ + public IProject getProject() + { + return _project; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core + * .resources.IProject) + */ + public void setProject(IProject project) + { + _project = project; + } + + + private IProject _project; +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/ToggleNatureAction.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/ToggleNatureAction.java new file mode 100644 index 00000000000..dbeaf33a359 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/builder/ToggleNatureAction.java @@ -0,0 +1,128 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.builder; + +import java.util.Iterator; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +import com.zeroc.slice2javaplugin.internal.Configuration; + +public class ToggleNatureAction implements IObjectActionDelegate +{ + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) + */ + + public void run(IAction action) + { + if(_selection instanceof IStructuredSelection) + { + for(Iterator<?> it = ((IStructuredSelection) _selection).iterator(); it.hasNext();) + { + Object element = it.next(); + IProject project = null; + if(element instanceof IProject) + { + project = (IProject) element; + } + else if(element instanceof IAdaptable) + { + project = (IProject) ((IAdaptable) element).getAdapter(IProject.class); + } + if(project != null) + { + toggleNature(project); + } + } + } + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action + * .IAction, org.eclipse.jface.viewers.ISelection) + */ + public void selectionChanged(IAction action, ISelection selection) + { + this._selection = selection; + //action.setEnabled(false); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface. + * action.IAction, org.eclipse.ui.IWorkbenchPart) + */ + public void setActivePart(IAction action, IWorkbenchPart targetPart) + { + //action.setEnabled(false); + } + + /** + * Toggles sample nature on a project + * + * @param project + * to have sample nature added or removed + */ + private void toggleNature(IProject project) + { + try + { + IProjectDescription description = project.getDescription(); + String[] natures = description.getNatureIds(); + + for(int i = 0; i < natures.length; ++i) + { + if(Slice2JavaNature.NATURE_ID.equals(natures[i])) + { + // Remove the nature + String[] newNatures = new String[natures.length - 1]; + System.arraycopy(natures, 0, newNatures, 0, i); + System.arraycopy(natures, i + 1, newNatures, i, natures.length - i - 1); + description.setNatureIds(newNatures); + project.setDescription(description, null); + + Configuration c = new Configuration(project); + c.deinstall(); + + return; + } + } + + // Add the nature + String[] newNatures = new String[natures.length + 1]; + System.arraycopy(natures, 0, newNatures, 0, natures.length); + newNatures[natures.length] = Slice2JavaNature.NATURE_ID; + description.setNatureIds(newNatures); + project.setDescription(description, null); + } + catch(CoreException e) + { + } + } + + private ISelection _selection; +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/decorator/GeneratedDecorator.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/decorator/GeneratedDecorator.java new file mode 100644 index 00000000000..ec832072a01 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/decorator/GeneratedDecorator.java @@ -0,0 +1,67 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.decorator; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.swt.graphics.Image; + +import com.zeroc.slice2javaplugin.internal.Configuration; + +public class GeneratedDecorator implements ILabelDecorator +{ + + public void addListener(ILabelProviderListener arg0) + { + } + + public void dispose() + { + } + + public boolean isLabelProperty(Object arg0, String arg1) + { + return false; + } + + public void removeListener(ILabelProviderListener arg0) + { + } + + public Image decorateImage(Image arg0, Object arg1) + { + return null; + } + + public String decorateText(String label, Object object) + { + IResource resource = (IResource) object; + if(resource.getType() != IResource.FOLDER) + { + // Only folders are decorated. + return null; + } + IProject project = resource.getProject(); + Configuration configuration = new Configuration(project); + IFolder generated = project.getFolder(configuration.getGeneratedDir()); + if(!generated.getLocation().toOSString().equals(resource.getLocation().toOSString())) + { + // We just need to decorate the slice2java generated folder. + return null; + } + + return label + " [Generated slice2java sources]"; + } + +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/decorator/SliceDecorator.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/decorator/SliceDecorator.java new file mode 100644 index 00000000000..bd8336f03e8 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/decorator/SliceDecorator.java @@ -0,0 +1,75 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.decorator; + +import java.util.List; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.swt.graphics.Image; + +import com.zeroc.slice2javaplugin.internal.Configuration; + +public class SliceDecorator implements ILabelDecorator +{ + + public void addListener(ILabelProviderListener arg0) + { + } + + public void dispose() + { + } + + public boolean isLabelProperty(Object arg0, String arg1) + { + return false; + } + + public void removeListener(ILabelProviderListener arg0) + { + } + + public Image decorateImage(Image arg0, Object arg1) + { + return null; + } + + public String decorateText(String label, Object object) + { + IResource resource = (IResource) object; + if(resource.getType() != IResource.FOLDER) + { + // Only folders are decorated. + return null; + } + IProject project = resource.getProject(); + Configuration configuration = new Configuration(project); + List<String> slices = configuration.getSliceSourceDirs(); + + boolean decorated = false; + for(int i = 0; i < slices.size(); ++i) + { + IFolder f = project.getFolder(slices.get(i)); + if(f.getLocation().toOSString().equals(resource.getLocation().toOSString())) + { + decorated = true; + break; + } + } + + return decorated ? label + " [Slice sources]": label; + } + +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/Configuration.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/Configuration.java new file mode 100644 index 00000000000..ad50b474c14 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/Configuration.java @@ -0,0 +1,1021 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.internal; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.ui.preferences.ScopedPreferenceStore; + +import com.zeroc.slice2javaplugin.Activator; +import com.zeroc.slice2javaplugin.preferences.PluginPreferencePage; + +public class Configuration +{ + public Configuration(IProject project) + { + _project = project; + + _instanceStore = new ScopedPreferenceStore(new InstanceScope(), Activator.PLUGIN_ID + "." + _project.getName()); + + _store = new ScopedPreferenceStore(new ProjectScope(project), Activator.PLUGIN_ID); + + _androidProject = false; + try + { + _androidProject = project.hasNature("com.android.ide.eclipse.adt.AndroidNature"); + } + catch(CoreException e) + { + } + + _store.setDefault(GENERATED_KEY, GENERATED_KEY); + _store.setDefault(DEFINES_KEY, ""); + _store.setDefault(TIE_KEY, false); + _store.setDefault(ICE_KEY, false); + _store.setDefault(STREAM_KEY, false); + _store.setDefault(ICE_INCLUDE_KEY, false); + _store.setDefault(META_KEY, ""); + _store.setDefault(CONSOLE_KEY, false); + _store.setDefault(SLICE_SOURCE_DIRS_KEY, "slice"); + _store.setDefault(INCLUDES_KEY, ""); + _store.setDefault(ADD_JARS_KEY, true); + _store.setDefault(UNDERSCORE_KEY, false); + + _store.setDefault(JARS_KEY, "Ice.jar"); + } + + /** + * Turns list of strings into a single ';' delimited string. ';' in the + * string values are escaped with a leading '\'. '\' are turned into '\\'. + * + * @param l + * List of strings. + * @return Semicolon delimited string. + */ + static public String fromList(List<String> l) + { + StringBuffer sb = new StringBuffer(); + for(Iterator<String> p = l.iterator(); p.hasNext();) + { + if(sb.length() > 0) + { + sb.append(";"); + } + sb.append(escape(p.next())); + } + return sb.toString(); + } + + /** + * Turn a semicolon delimited string into a list of strings. Escaped values + * are preserved (characters prefixed with a '\'). + * + * @param s + * Semicolon delimited string. + * @return List of strings. + */ + static public List<String> toList(String s) + { + java.util.List<String> l = new ArrayList<String>(); + int curr = 0; + int end = s.length(); + boolean escape = false; + StringBuffer sb = new StringBuffer(); + for(curr = 0; curr < end; ++curr) + { + char ch = s.charAt(curr); + if(escape) + { + sb.append(ch); + escape = false; + } + else + { + if(ch == ';') + { + String tok = sb.toString().trim(); + sb.setLength(0); + if(tok.length() > 0) + { + l.add(tok); + } + } + else if(ch == '\\') + { + escape = true; + } + else + { + sb.append(ch); + } + } + } + String tok = sb.toString().trim(); + if(tok.length() > 0) + { + l.add(tok); + } + return l; + } + + public boolean write() + throws CoreException, IOException + { + boolean rc = false; + if(_store.needsSaving()) + { + _store.save(); + rc = true; + } + if(_instanceStore.needsSaving()) + { + _instanceStore.save(); + rc = true; + } + + if(rc) + { + IJavaProject javaProject = JavaCore.create(_project); + if(getAddJars()) + { + addLibrary(javaProject); + } + else + { + removeLibrary(javaProject); + } + } + + return rc; + } + + public void initialize() + throws CoreException + { + // Create the slice source directories, if necessary. + for(Iterator<String> p = getSliceSourceDirs().iterator(); p.hasNext();) + { + IFolder slice = _project.getFolder(p.next()); + if(!slice.exists()) + { + slice.create(false, true, null); + } + } + + // Create the generated directory, if necessary. + IFolder generated = _project.getFolder(getGeneratedDir()); + if(!generated.exists()) + { + generated.create(false, true, null); + } + + fixGeneratedCP(null, getGeneratedDir()); + + IJavaProject javaProject = JavaCore.create(_project); + addLibrary(javaProject); + } + + public void deinstall() + throws CoreException + { + IJavaProject javaProject = JavaCore.create(_project); + removeLibrary(javaProject); + removedGeneratedCP(); + IFolder generatedFolder = _project.getFolder(getGeneratedDir()); + if(generatedFolder != null && generatedFolder.exists()) + { + generatedFolder.delete(true, null); + } + } + + public boolean isAndroidProject() + { + return _androidProject; + } + + public List<String> getSliceSourceDirs() + { + return toList(_store.getString(SLICE_SOURCE_DIRS_KEY)); + } + + public void setSliceSourceDirs(List<String> sliceSourceDirs) + { + setValue(SLICE_SOURCE_DIRS_KEY, fromList(sliceSourceDirs)); + } + + public String getGeneratedDir() + { + return _store.getString(GENERATED_KEY); + } + + public void fixGeneratedCP(String oldG, String newG) + throws CoreException + { + IJavaProject javaProject = JavaCore.create(_project); + + IFolder newGenerated = _project.getFolder(newG); + + IClasspathEntry[] entries = javaProject.getRawClasspath(); + IClasspathEntry newEntry = JavaCore.newSourceEntry(newGenerated.getFullPath()); + + if(oldG != null) + { + IFolder oldGenerated = _project.getFolder(oldG); + IClasspathEntry oldEntry = JavaCore.newSourceEntry(oldGenerated.getFullPath()); + for(int i = 0; i < entries.length; ++i) + { + if(entries[i].equals(oldEntry)) + { + entries[i] = newEntry; + javaProject.setRawClasspath(entries, null); + oldGenerated.delete(true, null); + return; + } + } + } + + IClasspathEntry[] newEntries = new IClasspathEntry[entries.length + 1]; + System.arraycopy(entries, 0, newEntries, 1, entries.length); + newEntries[0] = newEntry; + + newGenerated.setDerived(true, null); + + try + { + javaProject.setRawClasspath(newEntries, null); + } + catch(JavaModelException e) + { + // This can occur if a duplicate CLASSPATH entry is made. + // + // throw new CoreException(new Status(IStatus.ERROR, + // Activator.PLUGIN_ID, e.toString(), null)); + } + } + + public void removedGeneratedCP() + throws CoreException + { + IJavaProject javaProject = JavaCore.create(_project); + + IFolder generated = _project.getFolder(getGeneratedDir()); + + IClasspathEntry generatedEntry = JavaCore.newSourceEntry(generated.getFullPath()); + + IClasspathEntry[] entries = javaProject.getRawClasspath(); + IClasspathEntry[] newEntries = new IClasspathEntry[entries.length - 1]; + + for(int i = 0, j = 0; i < entries.length; i++) + { + if(entries[i].equals(generatedEntry)) + { + continue; + } + newEntries[j] = entries[i]; + j++; + } + + try + { + javaProject.setRawClasspath(newEntries, null); + } + catch(JavaModelException e) + { + // This can occur if a duplicate CLASSPATH entry is made. + // + // throw new CoreException(new Status(IStatus.ERROR, + // Activator.PLUGIN_ID, e.toString(), null)); + } + } + + public void setGeneratedDir(String generated) + throws CoreException + { + String oldGenerated = getGeneratedDir(); + if(setValue(GENERATED_KEY, generated)) + { + fixGeneratedCP(oldGenerated, generated); + } + } + + public List<String> getCommandLine() + { + List<String> cmds = new ArrayList<String>(); + for(Iterator<String> p = getIncludes().iterator(); p.hasNext();) + { + cmds.add("-I" + p.next()); + } + for(Iterator<String> p = getDefines().iterator(); p.hasNext();) + { + cmds.add("-D" + p.next()); + } + for(Iterator<String> p = getMeta().iterator(); p.hasNext();) + { + cmds.add("--meta"); + cmds.add(p.next()); + } + if(getStream()) + { + cmds.add("--stream"); + } + if(getTie()) + { + cmds.add("--tie"); + } + if(getIce()) + { + cmds.add("--ice"); + } + if(getUnderscore()) + { + cmds.add("--underscore"); + } + + StringTokenizer tokens = new StringTokenizer(getExtraArguments()); + while(tokens.hasMoreTokens()) + { + cmds.add(tokens.nextToken()); + } + + return cmds; + } + + public List<String> getCommandLine(IResource resource) + { + List<String> cmds = getCommandLine(); + for(Iterator<String> p = getBareIncludes(resource).iterator(); p.hasNext();) + { + cmds.add("-I" + p.next()); + } + for(Iterator<String> p = getDefines(resource).iterator(); p.hasNext();) + { + cmds.add("-D" + p.next()); + } + for(Iterator<String> p = getMeta(resource).iterator(); p.hasNext();) + { + cmds.add("--meta"); + cmds.add(p.next()); + } + if(!getStream() && getStream(resource)) + { + cmds.add("--stream"); + } + if(!getTie() && getTie(resource)) + { + cmds.add("--tie"); + } + if(!getIce() && getIce(resource)) + { + cmds.add("--ice"); + } + if(!getUnderscore() && getUnderscore(resource)) + { + cmds.add("--underscore"); + } + + StringTokenizer tokens = new StringTokenizer(getExtraArguments(resource)); + while(tokens.hasMoreTokens()) + { + cmds.add(tokens.nextToken()); + } + + return cmds; + } + + public List<String> getIncludes() + { + List<String> s = toList(_store.getString(INCLUDES_KEY)); + + String iceHome = getIceHome(); + String os = System.getProperty("os.name"); + String path = null; + if(os.equals("Linux") && iceHome.equals("/usr")) + { + String version = getIceVersion(); + if(version != null) + { + File f = new File("/usr/share/Ice-" + version + "/slice"); + if(f.exists()) + { + path = f.toString(); + } + } + } + + if(path == null) + { + path = new File(iceHome + File.separator + "slice").toString(); + } + + s.add(path); + return s; + } + + // The bare include list. + public List<String> getBareIncludes() + { + return toList(_store.getString(INCLUDES_KEY)); + } + + public List<String> getBareIncludes(IResource resource) + { + return toList(_store.getString(resourceKey(resource, INCLUDES_KEY))); + } + + public void setIncludes(List<String> includes) + { + setValue(INCLUDES_KEY, fromList(includes)); + } + + public void setIncludes(IResource resource, List<String> includes) + { + setValue(resourceKey(resource, INCLUDES_KEY), fromList(includes)); + } + + public boolean getAddJars() + { + return _store.getBoolean(ADD_JARS_KEY); + } + + public void setAddJars(boolean b) + { + _store.setValue(ADD_JARS_KEY, b); + } + + public List<String> getJars() + { + return toList(_store.getString(JARS_KEY)); + } + + public void setJars(List<String> jars) throws CoreException + { + if(setValue(JARS_KEY, fromList(jars))) + { + IceClasspathContainerIntializer.reinitialize(_project, this); + } + } + + public List<String> getDefines() + { + return toList(_store.getString(DEFINES_KEY)); + } + + public List<String> getDefines(IResource resource) + { + return toList(_store.getString(resourceKey(resource, DEFINES_KEY))); + } + + public void setDefines(List<String> defines) + { + setValue(DEFINES_KEY, fromList(defines)); + } + + public void setDefines(IResource resource, List<String> defines) + { + setValue(resourceKey(resource, DEFINES_KEY), fromList(defines)); + } + + public boolean getStream() + { + return _store.getBoolean(STREAM_KEY); + } + + public boolean getStream(IResource resource) + { + return _store.getBoolean(resourceKey(resource, STREAM_KEY)); + } + + public void setStream(boolean stream) + { + _store.setValue(STREAM_KEY, stream); + } + + public void setStream(IResource resource, boolean stream) + { + _store.setValue(resourceKey(resource, STREAM_KEY), stream); + } + + public boolean getTie() + { + return _store.getBoolean(TIE_KEY); + } + + public boolean getTie(IResource resource) + { + return _store.getBoolean(resourceKey(resource, TIE_KEY)); + } + + public void setTie(boolean tie) + { + _store.setValue(TIE_KEY, tie); + } + + public void setTie(IResource resource, boolean tie) + { + _store.setValue(resourceKey(resource, TIE_KEY), tie); + } + + public boolean getIce() + { + return _store.getBoolean(ICE_KEY); + } + + public boolean getIce(IResource resource) + { + return _store.getBoolean(resourceKey(resource, ICE_KEY)); + } + + public void setIce(boolean ice) + { + _store.setValue(ICE_KEY, ice); + } + + public void setIce(IResource resource, boolean ice) + { + _store.setValue(resourceKey(resource, ICE_KEY), ice); + } + + public boolean getUnderscore() + { + return _store.getBoolean(UNDERSCORE_KEY); + } + + public boolean getUnderscore(IResource resource) + { + return _store.getBoolean(resourceKey(resource, UNDERSCORE_KEY)); + } + + public void setUnderscore(boolean underscore) + { + _store.setValue(UNDERSCORE_KEY, underscore); + } + + public void setUnderscore(IResource resource, boolean underscore) + { + _store.setValue(resourceKey(resource, UNDERSCORE_KEY), underscore); + } + + public boolean getConsole() + { + return _store.getBoolean(CONSOLE_KEY); + } + + public void setConsole(boolean console) + { + _store.setValue(CONSOLE_KEY, console); + } + + public List<String> getMeta() + { + return toList(_store.getString(META_KEY)); + } + + public List<String> getMeta(IResource resource) + { + return toList(_store.getString(resourceKey(resource, META_KEY))); + } + + public void setMeta(List<String> meta) + { + setValue(META_KEY, fromList(meta)); + } + + public void setMeta(IResource resource, List<String> meta) + { + setValue(resourceKey(resource, META_KEY), fromList(meta)); + } + + public String getExtraArguments() + { + return _store.getString(EXTRA_ARGUMENTS_KEY); + } + + public String getExtraArguments(IResource resource) + { + return _store.getString(resourceKey(resource, EXTRA_ARGUMENTS_KEY)); + } + + public void setExtraArguments(String arguments) + { + setValue(EXTRA_ARGUMENTS_KEY, arguments); + } + + public void setExtraArguments(IResource resource, String arguments) + { + setValue(resourceKey(resource, EXTRA_ARGUMENTS_KEY), arguments); + } + + public static void setupSharedLibraryPath(Map<String, String> env) + { + String iceHome = getIceHome(); + + String libPath; + boolean srcdist = false; + if(new File(iceHome + File.separator + "cpp" + File.separator + "bin").exists()) + { + // iceHome points at a source distribution. + libPath = new File(iceHome + File.separator + "cpp" + File.separator + "lib").toString(); + srcdist = true; + } + else + { + libPath = new File(iceHome + File.separator + "lib").toString(); + } + + String ldLibPathEnv = null; + String ldLib64PathEnv = null; + String lib64Path = null; + + String os = System.getProperty("os.name"); + if(os.equals("Mac OS X")) + { + ldLibPathEnv = "DYLD_LIBRARY_PATH"; + } + else if(os.equals("AIX")) + { + ldLibPathEnv = "LIBPATH"; + } + else if(os.equals("HP-UX")) + { + ldLibPathEnv = "SHLIB_PATH"; + ldLib64PathEnv = "LD_LIBRARY_PATH"; + if(srcdist) + { + lib64Path = libPath; + } + else + { + lib64Path = new File(iceHome + File.separator + "lib" + File.separator + "pa20_64").toString(); + } + } + else if(os.startsWith("Windows")) + { + // + // No need to change the PATH environment variable on Windows, the + // DLLs should be found + // in the translator local directory. + // + // ldLibPathEnv = "PATH"; + } + else if(os.equals("SunOS")) + { + ldLibPathEnv = "LD_LIBRARY_PATH"; + ldLib64PathEnv = "LD_LIBRARY_PATH_64"; + String arch = System.getProperty("os.arch"); + if(srcdist) + { + lib64Path = libPath; + } + else if(arch.equals("x86")) + { + lib64Path = new File(iceHome + File.separator + "lib" + File.separator + "amd64").toString(); + } + else + // Sparc + { + lib64Path = new File(iceHome + File.separator + "lib" + File.separator + "sparcv9").toString(); + } + } + else + { + ldLibPathEnv = "LD_LIBRARY_PATH"; + ldLib64PathEnv = "LD_LIBRARY_PATH"; + if(srcdist) + { + lib64Path = libPath; + } + else + { + lib64Path = new File(iceHome + File.separator + "lib64").toString(); + } + } + + if(ldLibPathEnv != null) + { + if(ldLibPathEnv.equals(ldLib64PathEnv)) + { + libPath = libPath + File.pathSeparator + lib64Path; + } + + String envLibPath = env.get(ldLibPathEnv); + if(envLibPath != null) + { + libPath = libPath + File.pathSeparator + envLibPath; + } + + env.put(ldLibPathEnv, libPath); + } + + if(ldLib64PathEnv != null && !ldLib64PathEnv.equals(ldLibPathEnv)) + { + String envLib64Path = env.get(ldLib64PathEnv); + if(envLib64Path != null) + { + lib64Path = lib64Path + File.pathSeparator + envLib64Path; + } + env.put(ldLib64PathEnv, lib64Path); + } + } + + public String getTranslator() + { + return getTranslatorForHome(getIceHome()); + } + + static public boolean verifyIceHome(String dir) + { + return getTranslatorForHome(dir) != null; + } + + public String getJarDir() + { + String iceHome = getIceHome(); + String os = System.getProperty("os.name"); + if(os.equals("Linux") && iceHome.equals("/usr")) + { + File f = new File(iceHome + File.separator + "share" + File.separator + "java"); + if(f.exists()) + { + return f.toString(); + } + } + + File f = new File(iceHome + File.separator + "lib"); + if(!f.exists()) + { + File f2 = new File(iceHome + File.separator + "java" + File.separator + "lib"); + if(f2.exists()) + { + return f2.toString(); + } + } + // Add the platform default even if it cannot be found. + return f.toString(); + } + + private static String getIceHome() + { + return Activator.getDefault().getPreferenceStore().getString(PluginPreferencePage.SDK_PATH); + } + + // For some reason ScopedPreferenceStore.setValue(String, String) + // doesn't check to see whether the stored value is the same as + // the new value. + private boolean setValue(String key, String value) + { + return setValue(_store, key, value); + } + + private boolean setValue(ScopedPreferenceStore store, String key, String value) + { + if(!store.getString(key).equals(value)) + { + store.setValue(key, value); + return true; + } + return false; + } + + static private String escape(String s) + { + int curr = 0; + int end = s.length(); + StringBuffer sb = new StringBuffer(); + for(curr = 0; curr < end; ++curr) + { + char ch = s.charAt(curr); + if(ch == '\\' || ch == ';') + { + sb.append('\\'); + } + sb.append(ch); + } + return sb.toString(); + } + + // Obtain the Ice version by executing the translator with the -v option. + private String getIceVersion() + { + String version = null; + String exec = getTranslatorForHome(getIceHome()); + if(exec != null) + { + try + { + ProcessBuilder b = new ProcessBuilder(exec, "-v"); + b.redirectErrorStream(true); + Map<String, String> env = b.environment(); + setupSharedLibraryPath(env); + Process p = b.start(); + int status = p.waitFor(); + if(status == 0) + { + BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line = r.readLine(); + version = line.trim(); + } + } + catch(Throwable ex) + { + // Ignore. + } + } + return version; + } + + private static String getTranslatorForHome(String dir) + { + String suffix = ""; + String os = System.getProperty("os.name"); + if(os.startsWith("Windows")) + { + suffix = ".exe"; + } + File f = new File(dir + File.separator + "bin" + File.separator + "slice2java" + suffix); + if(f.exists()) + { + return f.toString(); + } + f = new File(dir + File.separator + "cpp" + File.separator + "bin" + File.separator + "slice2java" + suffix); + if(f.exists()) + { + return f.toString(); + } + return null; + } + + private void addLibrary(IJavaProject project) + throws CoreException + { + IClasspathEntry cpEntry = null; + if(!isAndroidProject()) + { + cpEntry = IceClasspathContainerIntializer.getContainerEntry(); + } + else + { + cpEntry = JavaCore.newVariableEntry(new Path("ICE_HOME/lib/Ice.jar"), null, null); + } + + IClasspathEntry[] entries = project.getRawClasspath(); + boolean found = false; + for(int i = 0; i < entries.length; ++i) + { + if(entries[i].equals(cpEntry)) + { + found = true; + break; + } + } + + if(!found) + { + IClasspathEntry[] newEntries = new IClasspathEntry[entries.length + 1]; + System.arraycopy(entries, 0, newEntries, 0, entries.length); + newEntries[entries.length] = cpEntry; + + try + { + project.setRawClasspath(newEntries, null); + } + catch(JavaModelException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.toString(), null)); + } + } + } + + public void removeLibrary(IJavaProject project) + throws CoreException + { + IClasspathEntry cpEntry = null; + if(!isAndroidProject()) + { + cpEntry = IceClasspathContainerIntializer.getContainerEntry(); + } + else + { + cpEntry = JavaCore.newVariableEntry(new Path("ICE_HOME/lib/Ice.jar"), null, null); + } + IClasspathEntry[] entries = project.getRawClasspath(); + + for(int i = 0; i < entries.length; ++i) + { + if(entries[i].equals(cpEntry)) + { + IClasspathEntry[] newEntries = new IClasspathEntry[entries.length - 1]; + System.arraycopy(entries, 0, newEntries, 0, i); + System.arraycopy(entries, i + 1, newEntries, i, entries.length - i - 1); + + try + { + project.setRawClasspath(newEntries, null); + } + catch(JavaModelException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.toString(), null)); + } + break; + } + } + } + + // + // Check if the given resource has any Slice compiler options set. + // + public static boolean resourceHasOptions(IResource resource) + { + Configuration configuration = new Configuration(resource.getProject()); + if(configuration.getDefines(resource) != null && configuration.getDefines(resource).size() > 0) + { + return true; + } + if(configuration.getMeta(resource) != null && configuration.getMeta(resource).size() > 0) + { + return true; + } + if(!configuration.getStream() && configuration.getStream(resource)) + { + return true; + } + if(!configuration.getTie() && configuration.getTie(resource)) + { + return true; + } + if(!configuration.getIce() && configuration.getIce(resource)) + { + return true; + } + if(!configuration.getUnderscore() && configuration.getUnderscore(resource)) + { + return true; + } + if(configuration.getExtraArguments(resource) != null && !configuration.getExtraArguments(resource).isEmpty()) + { + return true; + } + return false; + } + + public static String resourceKey(IResource resource, String key) + { + return resource.getFullPath().toString() + "." + key; + } + + private static final String JARS_KEY = "jars"; + private static final String INCLUDES_KEY = "includes"; + private static final String SLICE_SOURCE_DIRS_KEY = "sliceSourceDirs"; + private static final String CONSOLE_KEY = "console"; + private static final String META_KEY = "meta"; + private static final String STREAM_KEY = "stream"; + private static final String ICE_INCLUDE_KEY = "iceIncludes"; + private static final String ICE_KEY = "ice"; + private static final String TIE_KEY = "tie"; + private static final String DEFINES_KEY = "defines"; + private static final String GENERATED_KEY = "generated"; + private static final String ADD_JARS_KEY = "addJars"; + private static final String UNDERSCORE_KEY = "underscore"; + + private static final String EXTRA_ARGUMENTS_KEY = "extraArguments"; + + // Preferences store for items which should go in SCM. This includes things + // like build flags. + private ScopedPreferenceStore _store; + + // Preferences store per project items which should not go in SCM, such as + // the location of the Ice installation. + private ScopedPreferenceStore _instanceStore; + + private IProject _project; + + private boolean _androidProject; +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/Dependencies.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/Dependencies.java new file mode 100644 index 00000000000..4204a676d69 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/Dependencies.java @@ -0,0 +1,528 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.internal; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Status; +import org.eclipse.ui.console.MessageConsoleStream; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.SAXException; + +import com.zeroc.slice2javaplugin.Activator; + +public class Dependencies +{ + public Dependencies(IProject project, Set<IFile> LprojectResources, MessageConsoleStream err) + { + _project = project; + _projectResources = LprojectResources; + _err = err; + + // Build a map of location to project resource. + + for(IFile f : _projectResources) + { + _locationToResource.put(f.getLocation(), f); + } + } + + /** + * + * @param allDependencies The string of all dependencies. + * @throws CoreException + */ + public void updateDependencies(String allDependencies) + throws CoreException + { + Slice2JavaDependenciesParser parser = new Slice2JavaDependenciesParser(); + try + { + InputStream in = new ByteArrayInputStream(allDependencies.getBytes()); + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new BufferedInputStream(in)); + parser.visit(doc); + } + catch(SAXException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading dependencies", e)); + } + catch(ParserConfigurationException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading dependencies", e)); + } + catch(IOException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading dependencies", e)); + } + + for(Map.Entry<String, List<String>> entry : parser.dependencies.entrySet()) + { + Path sourcePath = new Path(entry.getKey()); + assert sourcePath.isAbsolute(); + + IFile sourceFile = _locationToResource.get(sourcePath); + if(sourceFile == null) + { + if(_err != null) + { + _err.println("Dependencies: ignoring non-project resource " + sourcePath.toString()); + } + // This should not occur. + continue; + } + + for(String s : entry.getValue()) + { + IFile f = getProjectResource(new Path(s)); + // Ignore any resources not in the project. + if(f != null) + { + Set<IFile> dependents = reverseSliceSliceDependencies.get(f); + if(dependents == null) + { + dependents = new HashSet<IFile>(); + reverseSliceSliceDependencies.put(f, dependents); + } + dependents.add(sourceFile); + } + } + + Set<IFile> dependents = new HashSet<IFile>(); + sliceSliceDependencies.put(sourceFile, dependents); + for(String s : entry.getValue()) + { + IFile f = getProjectResource(new Path(s)); + // Ignore any resources not in the project. + if(f != null) + { + dependents.add(f); + } + } + } + } + + private IFile getProjectResource(Path path) + { + IFile f = null; + if(path.isAbsolute()) + { + f = _locationToResource.get(path); + } + else + { + f = _project.getFile(path.toString()); + if(!f.exists()) + { + f = null; + } + } + if(_projectResources.contains(f)) + { + return f; + } + return null; + } + + public void read() + throws CoreException + { + IFileStore dependencies = getDependenciesStore(); + if(!dependencies.fetchInfo(EFS.NONE, null).exists()) + { + return; + } + InputStream in = dependencies.openInputStream(EFS.NONE, null); + + try + { + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new BufferedInputStream(in)); + DependenciesParser parser = new DependenciesParser(_project); + parser.visit(doc); + sliceSliceDependencies = parser.sliceSliceDependencies; + reverseSliceSliceDependencies = parser.reverseSliceSliceDependencies; + sliceJavaDependencies = parser.sliceJavaDependencies; + errorSliceFiles = parser.errorSliceFiles; + } + catch(SAXException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading dependencies", e)); + } + catch(ParserConfigurationException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading dependencies", e)); + } + catch(IOException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error reading dependencies", e)); + } + } + + public void write() + throws CoreException + { + // Create a DOM of the map. + Document doc = null; + try + { + doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + } + catch(ParserConfigurationException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error writing dependencies", e)); + } + + Element root = doc.createElement("dependencies"); + doc.appendChild(root); + + writeDependencies(sliceSliceDependencies, doc, "sliceSliceDependencies", root); + writeDependencies(reverseSliceSliceDependencies, doc, "reverseSliceSliceDependencies", root); + writeDependencies(sliceJavaDependencies, doc, "sliceJavaDependencies", root); + writeErrorSliceFiles(errorSliceFiles, doc, "errorSliceFiles", root); + + // Write the DOM to the dependencies.xml file. + TransformerFactory transfac = TransformerFactory.newInstance(); + Transformer trans = null; + try + { + trans = transfac.newTransformer(); + } + catch(TransformerConfigurationException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error writing dependencies", e)); + } + // tf.setAttribute("indent-number", 4); + + // trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + trans.setOutputProperty(OutputKeys.INDENT, "yes"); + trans.setOutputProperty(OutputKeys.ENCODING, "UTF8"); + trans.setOutputProperty(OutputKeys.INDENT, "yes"); + trans.setOutputProperty(OutputKeys.METHOD, "XML"); + + IFileStore dependencies = getDependenciesStore(); + OutputStream out = dependencies.openOutputStream(EFS.NONE, null); + StreamResult result = new StreamResult(new BufferedOutputStream(out)); + DOMSource source = new DOMSource(doc); + try + { + trans.transform(source, result); + } + catch(TransformerException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error writing dependencies", e)); + } + try + { + out.close(); + } + catch(IOException e) + { + throw new CoreException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + "internal error writing dependencies", e)); + } + } + + private void writeErrorSliceFiles(Set<IFile> s, Document doc, String name, Element root) + { + Element jsd = doc.createElement(name); + root.appendChild(jsd); + + for(IFile f : s) + { + Element elem = doc.createElement("file"); + jsd.appendChild(elem); + Text text = doc.createTextNode(f.getProjectRelativePath().toString()); + elem.appendChild(text); + } + } + + private void writeDependencies(Map<IFile, Set<IFile>> map, Document doc, String name, Element root) + { + Element jsd = doc.createElement(name); + root.appendChild(jsd); + + Iterator<Map.Entry<IFile, Set<IFile>>> p = map.entrySet().iterator(); + while(p.hasNext()) + { + Map.Entry<IFile, Set<IFile>> e = p.next(); + Element entry = doc.createElement("entry"); + jsd.appendChild(entry); + + Element key = doc.createElement("key"); + entry.appendChild(key); + Text text = doc.createTextNode(e.getKey().getProjectRelativePath().toString()); + key.appendChild(text); + + Element value = doc.createElement("value"); + entry.appendChild(value); + + Iterator<IFile> q = e.getValue().iterator(); + while(q.hasNext()) + { + IFile f = q.next(); + Element elem = doc.createElement("file"); + value.appendChild(elem); + text = doc.createTextNode(f.getProjectRelativePath().toString()); + elem.appendChild(text); + } + } + } + + private IFileStore getDependenciesStore() + throws CoreException + { + IPath name = new Path(_project.getName()); + IFileStore store = EFS.getLocalFileSystem().getStore(Activator.getDefault().getStateLocation()).getFileStore( + name); + if(!store.fetchInfo(EFS.NONE, null).exists()) + { + store.mkdir(EFS.NONE, null); + } + return store.getFileStore(new Path("dependencies.xml")); + } + + private static class Slice2JavaDependenciesParser + { + Map<String, List<String>> dependencies = new java.util.HashMap<String, List<String>>(); + + private Node findNode(Node n, String qName) + throws SAXException + { + NodeList children = n.getChildNodes(); + for(int i = 0; i < children.getLength(); ++i) + { + Node child = children.item(i); + if(child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(qName)) + { + return child; + } + } + throw new SAXException("no such node: " + qName); + } + + private void visitDependencies(Node n) throws SAXException + { + NodeList children = n.getChildNodes(); + for(int i = 0; i < children.getLength(); ++i) + { + if(children.item(i).getNodeType() == Node.ELEMENT_NODE && children.item(i).getNodeName().equals("source")) + { + String source = ((Element)children.item(i)).getAttribute("name"); + if(source.length() == 0) + { + throw new SAXException("empty name attribute"); + } + List<String> dependsOn = visitDependsOn(children.item(i)); + dependencies.put(source, dependsOn); + } + } + } + + private List<String> visitDependsOn(Node source) throws SAXException + { + List<String> depends = new ArrayList<String>(); + NodeList dependencies = source.getChildNodes(); + for(int j = 0; j < dependencies.getLength(); ++j) + { + if(dependencies.item(j).getNodeType() == Node.ELEMENT_NODE && dependencies.item(j).getNodeName().equals("dependsOn")) + { + Element dependsOn = (Element)dependencies.item(j); + String name = dependsOn.getAttribute("name"); + if(name.length() == 0) + { + throw new SAXException("empty name attribute"); + } + depends.add(name); + } + } + return depends; + } + + public void visit(Node doc) throws SAXException + { + Node n = findNode(doc, "dependencies"); + visitDependencies(n); + } + } + + private static class DependenciesParser + { + private IProject _project; + + Map<IFile, Set<IFile>> sliceSliceDependencies = new java.util.HashMap<IFile, Set<IFile>>(); + Map<IFile, Set<IFile>> reverseSliceSliceDependencies = new java.util.HashMap<IFile, Set<IFile>>(); + Map<IFile, Set<IFile>> sliceJavaDependencies = new java.util.HashMap<IFile, Set<IFile>>(); + Set<IFile> errorSliceFiles = new java.util.HashSet<IFile>(); + + private Node findNode(Node n, String qName) + throws SAXException + { + NodeList children = n.getChildNodes(); + for(int i = 0; i < children.getLength(); ++i) + { + Node child = children.item(i); + if(child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(qName)) + { + return child; + } + } + throw new SAXException("no such node: " + qName); + } + + private String getText(Node n) + throws SAXException + { + NodeList children = n.getChildNodes(); + if(children.getLength() == 1 && children.item(0).getNodeType() == Node.TEXT_NODE) + { + return children.item(0).getNodeValue(); + } + throw new SAXException("no text element"); + } + + private List<String> processFiles(Node n) + throws SAXException + { + List<String> files = new ArrayList<String>(); + NodeList children = n.getChildNodes(); + for(int i = 0; i < children.getLength(); ++i) + { + Node child = children.item(i); + if(child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals("file")) + { + files.add(getText(child)); + } + } + return files; + } + + public void visitDependencies(Map<IFile, Set<IFile>> map, Node n) + throws SAXException + { + NodeList children = n.getChildNodes(); + for(int i = 0; i < children.getLength(); ++i) + { + Node child = children.item(i); + if(child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals("entry")) + { + IFile key = _project.getFile(new Path(getText(findNode(child, "key")))); + + Node value = findNode(child, "value"); + List<String> files = processFiles(value); + Set<IFile> f = new HashSet<IFile>(); + for(String s : files) + { + f.add(_project.getFile(new Path(s))); + } + + map.put(key, f); + } + } + } + + public void visitErrorList(Set<IFile> s, Node n) throws SAXException + { + NodeList children = n.getChildNodes(); + for(int i = 0; i < children.getLength(); ++i) + { + Node child = children.item(i); + if(child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals("file")) + { + s.add(_project.getFile(new Path(getText(child)))); + } + } + } + + public void visit(Node doc) + throws SAXException + { + Node dependencies = findNode(doc, "dependencies"); + visitDependencies(sliceSliceDependencies, findNode(dependencies, "sliceSliceDependencies")); + visitDependencies(reverseSliceSliceDependencies, findNode(dependencies, "reverseSliceSliceDependencies")); + visitDependencies(sliceJavaDependencies, findNode(dependencies, "sliceJavaDependencies")); + try + { + visitErrorList(errorSliceFiles, findNode(dependencies, "errorSliceFiles")); + } + catch(SAXException e) + { + // Optional. + } + } + + DependenciesParser(IProject project) + { + _project = project; + } + } + + // A map of slice to dependencies. + // + // sliceSliceDependencies is the set of slice files that depend on the IFile + // (the output of slice2java --depend). + // + // _reverseSliceSliceDependencies is the reverse. + public Map<IFile, Set<IFile>> sliceSliceDependencies = new java.util.HashMap<IFile, Set<IFile>>(); + public Map<IFile, Set<IFile>> reverseSliceSliceDependencies = new java.util.HashMap<IFile, Set<IFile>>(); + + // A map of slice file to java source files. + public Map<IFile, Set<IFile>> sliceJavaDependencies = new java.util.HashMap<IFile, Set<IFile>>(); + + // A set of slice files that have not, or cannot be built. + public Set<IFile> errorSliceFiles = new java.util.HashSet<IFile>(); + + private IProject _project; + private MessageConsoleStream _err; + private Set<IFile> _projectResources; + private Map<IPath, IFile> _locationToResource = new HashMap<IPath, IFile>(); +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathContainer.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathContainer.java new file mode 100644 index 00000000000..915234c1304 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathContainer.java @@ -0,0 +1,47 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.internal; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.IClasspathContainer; +import org.eclipse.jdt.core.IClasspathEntry; + +public class IceClasspathContainer implements IClasspathContainer +{ + private IClasspathEntry[] _cpEntry; + private IPath _path; + + IceClasspathContainer(IClasspathEntry[] entries, IPath path) + { + _cpEntry = entries; + _path = path; + } + + public IClasspathEntry[] getClasspathEntries() + { + return _cpEntry; + } + + public String getDescription() + { + return "Ice Library"; + } + + public int getKind() + { + return IClasspathContainer.K_APPLICATION; + } + + public IPath getPath() + { + return _path; + } +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathContainerIntializer.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathContainerIntializer.java new file mode 100644 index 00000000000..7d16cb2983c --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathContainerIntializer.java @@ -0,0 +1,95 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.internal; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.ClasspathContainerInitializer; +import org.eclipse.jdt.core.IAccessRule; +import org.eclipse.jdt.core.IClasspathAttribute; +import org.eclipse.jdt.core.IClasspathContainer; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; + +public class IceClasspathContainerIntializer extends ClasspathContainerInitializer +{ + private final static String CONTAINER_ID = "com.zeroc.Slice2JavaPlugin.ICE_FRAMEWORK"; + + @Override + public void initialize(IPath containerPath, IJavaProject project) + throws CoreException + { + if(containerPath.toString().equals(CONTAINER_ID)) + { + Configuration c = new Configuration(project.getProject()); + configure(c, project, containerPath); + } + } + + public static IClasspathEntry getContainerEntry() + { + return JavaCore.newContainerEntry(new Path(CONTAINER_ID)); + } + + public static void reinitialize(IProject project, Configuration c) + throws CoreException + { + IJavaProject javaProject = JavaCore.create(project); + IPath containerPath = new Path(CONTAINER_ID); + + configure(c, javaProject, containerPath); + } + + private static void configure(Configuration c, IJavaProject javaProject, IPath containerPath) + throws JavaModelException + { + if(c.getAddJars()) + { + Path dir = new Path(c.getJarDir()); + List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>(); + for(String jar : c.getJars()) + { + IPath path = dir.append(new Path(jar)); + IClasspathEntry classpathEntry = JavaCore.newLibraryEntry(path, null, null, new IAccessRule[0], new IClasspathAttribute[0], false); + entries.add(classpathEntry); + } + + IClasspathContainer container = new IceClasspathContainer(entries.toArray(new IClasspathEntry[0]), containerPath); + JavaCore.setClasspathContainer(containerPath, new IJavaProject[] { javaProject }, + new IClasspathContainer[] { container }, new NullProgressMonitor()); + } + } + + public static void updateProjects(String value, List<IJavaProject> projects) + { + for(IJavaProject p : projects) + { + IPath containerPath = new Path(CONTAINER_ID); + Configuration c = new Configuration(p.getProject()); + try + { + configure(c, p, containerPath); + } + catch(JavaModelException e) + { + e.printStackTrace(); + } + } + } +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathVariableInitializer.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathVariableInitializer.java new file mode 100644 index 00000000000..06af5b796a9 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/internal/IceClasspathVariableInitializer.java @@ -0,0 +1,47 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.internal; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.jdt.core.ClasspathVariableInitializer; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; + +import com.zeroc.slice2javaplugin.Activator; +import com.zeroc.slice2javaplugin.preferences.PluginPreferencePage; + +public class IceClasspathVariableInitializer extends ClasspathVariableInitializer +{ + private final static String VARIABLE_NAME = "ICE_HOME"; + + @Override + public void initialize(String variable) + { + if(variable.equals(VARIABLE_NAME)) + { + update(Activator.getDefault().getPreferenceStore().getString(PluginPreferencePage.SDK_PATH)); + } + } + + public static void update(String value) + { + IPath path = new Path(value); + try + { + JavaCore.setClasspathVariable(VARIABLE_NAME, path, null); + } + catch(JavaModelException e) + { + e.printStackTrace(); + } + } +}
\ No newline at end of file diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/preferences/PluginPreferencePage.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/preferences/PluginPreferencePage.java new file mode 100644 index 00000000000..e478f3d037d --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/preferences/PluginPreferencePage.java @@ -0,0 +1,102 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.preferences; + +import org.eclipse.jface.preference.*; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchPreferencePage; +import org.eclipse.ui.IWorkbench; + +import com.zeroc.slice2javaplugin.Activator; +import com.zeroc.slice2javaplugin.internal.Configuration; + +/** + * This class represents a preference page that is contributed to the + * Preferences dialog. By subclassing <samp>FieldEditorPreferencePage</samp>, we + * can use the field support built into JFace that allows us to create a page + * that is small and knows how to save, restore and apply itself. + * <p> + * This page is used to modify preferences only. They are stored in the + * preference store that belongs to the main plug-in class. That way, + * preferences can be accessed directly via the preference store. + */ + +public class PluginPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage +{ + public static final String SDK_PATH = "pathPreference"; + + public PluginPreferencePage() + { + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("Slice2Java Preferences"); + } + + /** + * Creates the field editors. Field editors are abstractions of the common + * GUI blocks needed to manipulate various types of preferences. Each field + * editor knows how to save and restore itself. + */ + public void createFieldEditors() + { + addField(new SdkDirectoryFieldEditor(SDK_PATH, "&SDK Location:", getFieldEditorParent())); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + public void init(IWorkbench workbench) + { + } + + private static class SdkDirectoryFieldEditor extends DirectoryFieldEditor + { + + public SdkDirectoryFieldEditor(String name, String labelText, Composite parent) + { + super(name, labelText, parent); + setEmptyStringAllowed(false); + } + + /** + * Method declared on StringFieldEditor and overridden in + * DirectoryFieldEditor. Checks whether the text input field contains a + * valid directory. + * + * @return True if the apply/ok button should be enabled in the pref + * panel + */ + @Override + protected boolean doCheckState() + { + String dir = getTextControl().getText(); + dir = dir.trim(); + if(!Configuration.verifyIceHome(dir)) + { + setErrorMessage("Invalid SDK Location"); + return false; + } + clearMessage(); + return true; + } + + @Override + public Text getTextControl(Composite parent) + { + setValidateStrategy(VALIDATE_ON_KEY_STROKE); + return super.getTextControl(parent); + } + } +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/preferences/PreferenceInitializer.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/preferences/PreferenceInitializer.java new file mode 100644 index 00000000000..2e953b343a5 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/preferences/PreferenceInitializer.java @@ -0,0 +1,65 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.preferences; + +import java.io.File; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + +import com.zeroc.slice2javaplugin.Activator; + +/** + * Class used to initialize default preference values. + */ +public class PreferenceInitializer extends AbstractPreferenceInitializer +{ + private String getDefaultHome() + { + String os = System.getProperty("os.name"); + if(os.startsWith("Windows")) + { + File f = new File("C:\\Program Files\\ZeroC\\Ice-3.4.2"); + if(!f.exists()) + { + File f2 = new File("C:\\Program Files (x86)\\ZeroC\\Ice-3.4.2"); + if(f2.exists()) + { + return f2.toString(); + } + } + return f.toString(); + } + if(os.equals("Linux")) + { + File f = new File("/usr/bin/slice2java"); + if(f.exists()) + { + return "/usr"; + } + } + return "/opt/Ice-3.4.2"; + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.core.runtime.preferences.AbstractPreferenceInitializer# + * initializeDefaultPreferences() + */ + public void initializeDefaultPreferences() + { + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + + store.setDefault(PluginPreferencePage.SDK_PATH, getDefaultHome() ); + } + +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/ProjectProperties.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/ProjectProperties.java new file mode 100644 index 00000000000..28611e45fcd --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/ProjectProperties.java @@ -0,0 +1,387 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.properties; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IncrementalProjectBuilder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +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.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.dialogs.ContainerSelectionDialog; + +import com.zeroc.slice2javaplugin.Activator; +import com.zeroc.slice2javaplugin.builder.Slice2JavaBuilder; +import com.zeroc.slice2javaplugin.internal.Configuration; + +public class ProjectProperties extends PropertyPage +{ + public ProjectProperties() + { + super(true); + setTitle("Slice2Java Settings"); + noDefaultAndApplyButton(); + } + + public void performApply() + { + super.performApply(); + } + + public boolean performOk() + { + final IProject project = getProject(); + + try + { + _config.setGeneratedDir(_generatedDir.getText()); + _config.setSliceSourceDirs(Arrays.asList(_sourceDirectories.getItems())); + _config.setIncludes(Arrays.asList(_includes.getItems())); + _config.setDefines(Configuration.toList(_defines.getText())); + _config.setMeta(Configuration.toList(_meta.getText())); + _config.setStream(_stream.getSelection()); + _config.setTie(_tie.getSelection()); + _config.setIce(_ice.getSelection()); + _config.setUnderscore(_underscore.getSelection()); + _config.setConsole(_console.getSelection()); + _config.setExtraArguments(_extraArguments.getText()); + if(_config.getAddJars()) + { + java.util.List<String> jars = new ArrayList<String>(); + jars.add("Ice.jar"); + if(_freezeJar.getSelection()) + { + jars.add("Freeze.jar"); + } + _config.setJars(jars); + } + + if(_config.write()) + { + // The configuration properties were changed. We need to rebuild + // the slice files. + Job job = new Job("Rebuild") + { + protected IStatus run(IProgressMonitor monitor) + { + try + { + project.build(IncrementalProjectBuilder.FULL_BUILD, Slice2JavaBuilder.BUILDER_ID, null, + monitor); + } + catch(CoreException e) + { + return new Status(Status.ERROR, Activator.PLUGIN_ID, 0, "rebuild failed", e); + } + return Status.OK_STATUS; + } + }; + job.setPriority(Job.BUILD); + job.schedule(); // start as soon as possible + } + } + catch(CoreException e) + { + return false; + } + catch(IOException e) + { + ErrorDialog.openError(getShell(), "Error", "Error saving preferences", + new Status(Status.ERROR, Activator.PLUGIN_ID, 0, null, e)); + return false; + } + return true; + } + + protected void createPostOptions(Composite composite) + { + _jarsGroup = new Group(composite, SWT.NONE); + _jarsGroup.setText("Add references to the following JAR files:"); + + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + + _jarsGroup.setLayout(gridLayout); + _jarsGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); + + _freezeJar = new Button(_jarsGroup, SWT.CHECK); + _freezeJar.setText("Freeze.jar"); + } + /** + * @see PreferencePage#createContents(Composite) + */ + protected Control createContents(Composite parent) + { + // Composite composite = new Composite(parent, SWT.NONE); + + TabFolder tabFolder = new TabFolder(parent, SWT.NONE); + { + TabItem tabItem = new TabItem(tabFolder, SWT.NONE); + tabItem.setText("Source"); + Control source = createSource(tabFolder); + tabItem.setControl(source); + } + { + TabItem tabItem = new TabItem(tabFolder, SWT.NONE); + tabItem.setText("Options"); + Control source = createOptions(tabFolder); + tabItem.setControl(source); + } + tabFolder.pack(); + + loadPrefs(); + + return tabFolder; + } + + private void loadPrefs() + { + IProject project = getProject(); + _config = new Configuration(project); + + _generatedDir.setText(_config.getGeneratedDir()); + for(Iterator<String> iter = _config.getSliceSourceDirs().iterator(); iter.hasNext();) + { + _sourceDirectories.add(iter.next()); + } + for(Iterator<String> iter = _config.getBareIncludes().iterator(); iter.hasNext();) + { + _includes.add(iter.next()); + } + for(Iterator<String> iter = _config.getJars().iterator(); iter.hasNext();) + { + String jarFile = iter.next(); + if(jarFile.equals("Freeze.jar")) + { + _freezeJar.setSelection(true); + } + } + _defines.setText(Configuration.fromList(_config.getDefines())); + _meta.setText(Configuration.fromList(_config.getMeta())); + _stream.setSelection(_config.getStream()); + _tie.setSelection(_config.getTie()); + _ice.setSelection(_config.getIce()); + _underscore.setSelection(_config.getUnderscore()); + _console.setSelection(_config.getConsole()); + _extraArguments.setText(_config.getExtraArguments()); + + // + // Android projects don't support extra Jar. + // + _jarsGroup.setEnabled(!_config.isAndroidProject()); + _freezeJar.setEnabled(!_config.isAndroidProject()); + + checkValid(); + } + + private void checkValid() + { + IProject project = getProject(); + IFolder folder = project.getFolder(_generatedDir.getText()); + if(!folder.exists()) + { + setErrorMessage("Generated folder does not exist"); + setValid(false); + return; + } + setValid(true); + setErrorMessage(null); + } + + private Control createSource(Composite parent) + { + Composite composite = new Composite(parent, SWT.NONE); + + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + composite.setLayout(gridLayout); + + Group sourceGroup = new Group(composite, SWT.NONE); + sourceGroup.setText("Location of Slice Source Files"); + gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + sourceGroup.setLayout(gridLayout); + sourceGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); + + Composite c1 = new Composite(sourceGroup, SWT.NONE); + + gridLayout = new GridLayout(); + gridLayout.numColumns = 2; + c1.setLayout(gridLayout); + c1.setLayoutData(new GridData(GridData.FILL_BOTH)); + + _sourceDirectories = new List(c1, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.BORDER); + _sourceDirectories.setLayoutData(new GridData(GridData.FILL_BOTH)); + + Composite c2 = new Composite(c1, SWT.NONE); + + gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + c2.setLayout(gridLayout); + + Button but1 = new Button(c2, SWT.PUSH); + but1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + but1.setText("Add Folder"); + but1.addSelectionListener(new SelectionAdapter() + { + public void widgetSelected(SelectionEvent e) + { + IProject project = getProject(); + + SourceSelectionDialog dialog = new SourceSelectionDialog(getShell(), project, "Select Source Location"); + String[] items = _sourceDirectories.getItems(); + IFolder[] resources = new IFolder[items.length]; + for(int i = 0; i < items.length; ++i) + { + resources[i] = project.getFolder(items[i]); + } + dialog.setInitialSelections(resources); + if(dialog.open() == ContainerSelectionDialog.OK) + { + Object[] selection = dialog.getResult(); + for(int i = 0; i < selection.length; ++i) + { + IFolder path = (IFolder) selection[i]; + _sourceDirectories.add(path.getProjectRelativePath().toString()); + } + } + } + }); + + Button but2 = new Button(c2, SWT.PUSH); + but2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + but2.setText("Remove"); + but2.addSelectionListener(new SelectionAdapter() + { + public void widgetSelected(SelectionEvent e) + { + _sourceDirectories.remove(_sourceDirectories.getSelectionIndices()); + } + }); + + Group gclGroup = new Group(composite, SWT.NONE); + gclGroup.setText("Generated Code Location"); + gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + gclGroup.setLayout(gridLayout); + gclGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Composite tc = new Composite(gclGroup, SWT.NONE); + gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + tc.setLayout(gridLayout); + tc.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label l = new Label(tc, SWT.WRAP); + l.setForeground(new Color(null, 255, 0, 0)); + l.setText("This subdirectory is used by the plug-in to manage the source files generated from " + + "your Slice definitions. It should not be used for any other purpose. " + + "Files added manually are removed during project rebuilds."); + + GridData gridData = new GridData(GridData.FILL_BOTH); + gridData.widthHint = 400; + l.setLayoutData(gridData); + + Composite c = new Composite(tc, SWT.NONE); + + GridLayout gridLayout2 = new GridLayout(); + gridLayout2.numColumns = 2; + gridLayout2.marginLeft = 0; + gridLayout2.marginTop = 0; + gridLayout2.marginBottom = 0; + c.setLayout(gridLayout2); + + c.setLayoutData(new GridData(GridData.FILL_BOTH)); + + _generatedDir = new Text(c, SWT.BORDER | SWT.READ_ONLY); + gridData = new GridData(GridData.FILL_HORIZONTAL); + // gridData.horizontalSpan = 2; + _generatedDir.setLayoutData(gridData); + + Button but3 = new Button(c, SWT.PUSH); + but3.setText("Browse"); + but3.addSelectionListener(new SelectionAdapter() + { + public void widgetSelected(SelectionEvent e) + { + IProject project = getProject(); + + SourceSelectionDialog dialog = new SourceSelectionDialog(getShell(), project, + "Select Generated Code Location"); + dialog.setMultiple(false); + if(dialog.open() == ContainerSelectionDialog.OK) + { + Object[] selection = dialog.getResult(); + if(selection.length == 1) + { + IFolder path = (IFolder) selection[0]; + String oldPath = _generatedDir.getText(); + String newPath = path.getProjectRelativePath().toString(); + if(oldPath.equals(newPath)) + { + return; + } + try + { + if(path.members().length > 0) + { + ErrorDialog.openError(getShell(), "Error", + "Generated code location should be an empty folder", + new Status(Status.ERROR, Activator.PLUGIN_ID, "The chosen directory '" + + path.getFullPath().toOSString() + "' is not empty." )); + return; + } + } + catch(CoreException ex) + { + ErrorDialog.openError(getShell(), "Error", ex.toString(), + new Status(Status.ERROR, Activator.PLUGIN_ID, 0, "Failed to set generated code location.", ex)); + return; + } + _generatedDir.setText(newPath); + } + } + } + }); + + return composite; + } + + private Button _freezeJar; + + private Text _generatedDir; + private List _sourceDirectories; + private Group _jarsGroup; +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/PropertyPage.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/PropertyPage.java new file mode 100644 index 00000000000..48281f575da --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/PropertyPage.java @@ -0,0 +1,484 @@ +// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This plug-in is provided to you under the terms and conditions
+// of the Eclipse Public License Version 1.0 ("EPL"). A copy of
+// the EPL is available at http://www.eclipse.org/legal/epl-v10.html.
+//
+// **********************************************************************
+
+package com.zeroc.slice2javaplugin.properties;
+
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.DirectoryDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Text;
+
+import com.zeroc.slice2javaplugin.Activator;
+import com.zeroc.slice2javaplugin.builder.Slice2JavaBuilder;
+import com.zeroc.slice2javaplugin.internal.Configuration;
+
+public abstract class PropertyPage extends org.eclipse.ui.dialogs.PropertyPage
+{
+ public PropertyPage(boolean projectPage)
+ {
+ super();
+ _projectPage = projectPage;
+ noDefaultAndApplyButton();
+ }
+
+ public void performApply()
+ {
+ super.performApply();
+ }
+
+ protected Control createIncludes(Composite parent)
+ {
+ Composite composite = new Composite(parent, SWT.NONE);
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 2;
+ composite.setLayout(gridLayout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ _includes = new List(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.BORDER);
+ _includes.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Composite c2 = new Composite(composite, SWT.NONE);
+
+ gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ c2.setLayout(gridLayout);
+
+ Button but1 = new Button(c2, SWT.PUSH);
+ but1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ but1.setText("Add");
+ but1.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ IProject project = getProject();
+ DirectoryDialog dialog = new DirectoryDialog(getShell());
+ String dir = dialog.open();
+ if(dir != null)
+ {
+ IPath projectLocation = project.getLocation();
+ IPath includeLocation = new Path(dir);
+ String dev1 = projectLocation.getDevice();
+ if(dev1 == null)
+ {
+ dev1 = "";
+ }
+ String dev2 = includeLocation.getDevice();
+ if(dev2 == null)
+ {
+ dev2 = "";
+ }
+ IPath result;
+
+ // If the directories are on different devices, then we have
+ // no choice but to use an absolute path.
+ if(!dev1.equals(dev2))
+ {
+ result = includeLocation;
+ }
+ else
+ {
+
+ // Convert the absolute path to a relative path.
+ int n = projectLocation.matchingFirstSegments(includeLocation);
+ result = includeLocation.removeFirstSegments(n);
+
+ IPath up = new Path("..");
+ for(n = projectLocation.segmentCount() - n; n > 0; --n)
+ {
+ result = up.append(result);
+ }
+ // The devices must match, so remove it.
+ result = result.setDevice(null);
+ }
+ _includes.add(result.toString());
+ }
+ }
+ });
+ Button but2 = new Button(c2, SWT.PUSH);
+ but2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ but2.setText("Remove");
+ but2.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ _includes.remove(_includes.getSelectionIndices());
+ }
+ });
+ Button but3 = new Button(c2, SWT.PUSH);
+ but3.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ but3.setText("Up");
+ but3.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int index = _includes.getSelectionIndex();
+ if(index > 0)
+ {
+ String[] items = _includes.getItems();
+ String tmp = items[index-1];
+ items[index-1] = items[index];
+ items[index] = tmp;
+ _includes.setItems(items);
+ _includes.setSelection(index-1);
+ }
+ }
+ });
+ Button but4 = new Button(c2, SWT.PUSH);
+ but4.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ but4.setText("Down");
+ but4.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int index = _includes.getSelectionIndex();
+ if(index != -1)
+ {
+ String[] items = _includes.getItems();
+ if(index != items.length-1)
+ {
+ String tmp = items[index+1];
+ items[index+1] = items[index];
+ items[index] = tmp;
+ _includes.setItems(items);
+ _includes.setSelection(index+1);
+ }
+ }
+ }
+ });
+
+ return composite;
+ }
+
+ private String semiFilter(String text)
+ {
+ java.util.List<String> l = Arrays.asList(text.split(";"));
+ StringBuffer sb = new StringBuffer();
+ for(Iterator<String> p = l.iterator(); p.hasNext();)
+ {
+ String n = p.next().trim();
+ if(n.length() > 0)
+ {
+ if(sb.length() != 0)
+ {
+ sb.append(';');
+ }
+ sb.append(n);
+ }
+ }
+ return sb.toString();
+ }
+
+ protected Control createDefines(Composite parent)
+ {
+ Composite composite = new Composite(parent, SWT.NONE);
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ gridLayout.marginLeft = 0;
+ gridLayout.marginTop = 0;
+ gridLayout.marginBottom = 0;
+ composite.setLayout(gridLayout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label l = new Label(composite, SWT.WRAP);
+ l.setText("Enter macros (';' separated). For example, enter FOO;BAR to define -DFOO -DBAR.");
+ GridData gridData = new GridData(GridData.FILL_BOTH);
+ gridData.widthHint = 400;
+ l.setLayoutData(gridData);
+
+ _defines = new Text(composite, SWT.BORDER);
+ _defines.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ _defines.addFocusListener(new FocusListener()
+ {
+ public void focusGained(FocusEvent e)
+ {
+ }
+
+ public void focusLost(FocusEvent e)
+ {
+ Text t = (Text)e.widget;
+ String f = t.getText();
+ String filtered = semiFilter(f);
+ if(!f.equals(filtered))
+ {
+ t.setText(filtered);
+ }
+ }
+ });
+
+ return composite;
+ }
+
+ protected Control createMeta(Composite parent)
+ {
+ Composite composite = new Composite(parent, SWT.NONE);
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ gridLayout.marginLeft = 0;
+ gridLayout.marginTop = 0;
+ gridLayout.marginBottom = 0;
+ composite.setLayout(gridLayout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label l = new Label(composite, SWT.WRAP);
+ l.setText("Enter metadata (';' separated). For example, enter as:package:com.acme to define --meta=as:package:com.acme.");
+ GridData gridData = new GridData(GridData.FILL_BOTH);
+ gridData.widthHint = 400;
+ l.setLayoutData(gridData);
+
+ _meta = new Text(composite, SWT.BORDER);
+ _meta.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ _meta.addFocusListener(new FocusListener()
+ {
+ public void focusGained(FocusEvent e)
+ {
+ }
+
+ public void focusLost(FocusEvent e)
+ {
+ Text t = (Text)e.widget;
+ String f = t.getText();
+ String filtered = semiFilter(f);
+ if(!f.equals(filtered))
+ {
+ t.setText(filtered);
+ }
+ }
+ });
+
+ return composite;
+ }
+
+ protected void createPreOptions(Composite parent)
+ {
+ }
+
+ protected void createPostOptions(Composite parent)
+ {
+ }
+
+ protected Control createOptions(Composite parent)
+ {
+ Composite composite = new Composite(parent, SWT.NONE);
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ composite.setLayout(gridLayout);
+
+ createPreOptions(composite);
+
+ Group includesGroup = new Group(composite, SWT.NONE);
+ includesGroup.setText("Location of Include Files");
+ gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ includesGroup.setLayout(gridLayout);
+ includesGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ createIncludes(includesGroup);
+
+ Group definesGroup = new Group(composite, SWT.NONE);
+ definesGroup.setText("Preprocessor Definitions");
+ gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ definesGroup.setLayout(gridLayout);
+ definesGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ createDefines(definesGroup);
+
+ Group metaGroup = new Group(composite, SWT.NONE);
+ metaGroup.setText("Metadata Definitions");
+ gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ metaGroup.setLayout(gridLayout);
+ metaGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ createMeta(metaGroup);
+
+ Group optionsGroup = new Group(composite, SWT.NONE);
+
+ gridLayout = new GridLayout();
+ gridLayout.numColumns = 5;
+ optionsGroup.setText("Options");
+ optionsGroup.setLayout(gridLayout);
+ optionsGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ _stream = new Button(optionsGroup, SWT.CHECK);
+ _stream.setText("Enable streaming");
+ _tie = new Button(optionsGroup, SWT.CHECK);
+ _tie.setText("Enable tie");
+ _ice = new Button(optionsGroup, SWT.CHECK);
+ _ice.setText("Enable ice");
+ if(_projectPage)
+ {
+ _console = new Button(optionsGroup, SWT.CHECK);
+ _console.setText("Enable console");
+ }
+ _underscore = new Button(optionsGroup, SWT.CHECK);
+ _underscore.setText("Enable underscore");
+
+ Group extraArgumentsGroup = new Group(composite, SWT.NONE);
+ extraArgumentsGroup.setText("Extra Compiler Arguments");
+ gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ extraArgumentsGroup.setLayout(gridLayout);
+ extraArgumentsGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
+ createExtraArguments(extraArgumentsGroup);
+
+ createPostOptions(composite);
+
+ return composite;
+ }
+
+ public Control createExtraArguments(Composite parent)
+ {
+ Composite composite = new Composite(parent, SWT.NONE);
+
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 1;
+ gridLayout.marginLeft = 0;
+ gridLayout.marginTop = 0;
+ gridLayout.marginBottom = 0;
+ composite.setLayout(gridLayout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label l = new Label(composite, SWT.WRAP);
+ l.setText("Enter extra arguments for the Slice compiler, such as --checksum=foo.Bar.SliceChecksums. " +
+ "These arguments are appended to the compiler command line.");
+ GridData gridData = new GridData(GridData.FILL_BOTH);
+ gridData.widthHint = 400;
+ l.setLayoutData(gridData);
+
+ _extraArguments = new Text(composite, SWT.BORDER);
+ _extraArguments.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ return composite;
+ }
+
+ protected IProject getProject()
+ {
+ IAdaptable a = getElement();
+ if(a instanceof IProject)
+ {
+ return (IProject)a;
+ }
+ else if(a instanceof IJavaProject)
+ {
+ return ((IJavaProject) a).getProject();
+ }
+ else if(a instanceof IResource)
+ {
+ return ((IResource)a).getProject();
+ }
+ else
+ {
+ assert(false);
+ return null;
+ }
+ }
+
+ protected IResource getResource()
+ {
+ IAdaptable a = getElement();
+ if(a instanceof IResource)
+ {
+ return (IResource)a;
+ }
+ else
+ {
+ assert(false);
+ return null;
+ }
+ }
+
+ protected boolean configSaveAndRebuild()
+ {
+ final IProject project = getProject();
+ try
+ {
+ if(_config.write())
+ {
+ // The configuration properties were changed. We need to rebuild
+ // the slice files.
+ Job job = new Job("Rebuild")
+ {
+ protected IStatus run(IProgressMonitor monitor)
+ {
+ try
+ {
+ project.build(IncrementalProjectBuilder.FULL_BUILD, Slice2JavaBuilder.BUILDER_ID, null,
+ monitor);
+ }
+ catch(CoreException e)
+ {
+ return new Status(Status.ERROR, Activator.PLUGIN_ID, 0, "rebuild failed", e);
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ job.setPriority(Job.BUILD);
+ job.schedule(); // start as soon as possible
+ }
+ }
+ catch(CoreException e)
+ {
+ return false;
+ }
+ catch(IOException e)
+ {
+ ErrorDialog.openError(getShell(), "Error", "Error saving preferences",
+ new Status(Status.ERROR, Activator.PLUGIN_ID, 0, null, e));
+ return false;
+ }
+ return true;
+ }
+
+ protected Configuration _config;
+ protected Button _console;
+ protected List _includes;
+
+ protected Text _defines;
+ protected Button _stream;
+ protected Button _tie;
+ protected Button _ice;
+ protected Button _underscore;
+ protected Text _meta;
+ protected Text _extraArguments;
+ protected boolean _projectPage;
+}
diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/SliceFilePropertyPage.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/SliceFilePropertyPage.java new file mode 100644 index 00000000000..b1509ae3b6f --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/SliceFilePropertyPage.java @@ -0,0 +1,110 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.properties; + +import java.util.Arrays; +import java.util.Iterator; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.swt.SWT; +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.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Text; + +import com.zeroc.slice2javaplugin.internal.Configuration; + +public class SliceFilePropertyPage extends PropertyPage +{ + public SliceFilePropertyPage() + { + super(false); + setTitle("Slice2as Settings"); + } + + protected void createPreOptions(Composite parent) + { + Composite composite = new Composite(parent, SWT.NONE); + + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + gridLayout.marginLeft = 0; + gridLayout.marginTop = 0; + gridLayout.marginBottom = 0; + composite.setLayout(gridLayout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label l = new Label(composite, SWT.WRAP); + l.setText("File:"); + GridData gridData = new GridData(GridData.FILL_HORIZONTAL); + l.setLayoutData(gridData); + + Text pathValueText = new Text(composite, SWT.WRAP | SWT.READ_ONLY); + pathValueText.setText(getResource().getFullPath().toString()); + pathValueText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + } + + protected Control createContents(Composite parent) + { + TabFolder tabFolder = new TabFolder(parent, SWT.NONE); + { + TabItem tabItem = new TabItem(tabFolder, SWT.NONE); + + + Control source = createOptions(tabFolder); + tabItem.setText("Options"); + tabItem.setControl(source); + } + + tabFolder.pack(); + loadPrefs(); + return tabFolder; + } + + public boolean performOk() + { + final IResource resource = getResource(); + _config.setIncludes(resource, Arrays.asList(_includes.getItems())); + _config.setDefines(resource, Configuration.toList(_defines.getText())); + _config.setStream(_stream.getSelection()); + _config.setMeta(resource, Configuration.toList(_meta.getText())); + _config.setTie(resource, _tie.getSelection()); + _config.setIce(resource, _ice.getSelection()); + _config.setUnderscore(resource, _underscore.getSelection()); + _config.setExtraArguments(resource, _extraArguments.getText()); + return configSaveAndRebuild(); + } + + private void loadPrefs() + { + IProject project = getProject(); + IResource resource = getResource(); + _config = new Configuration(project); + + for(Iterator<String> iter = _config.getBareIncludes(resource).iterator(); iter.hasNext();) + { + _includes.add(iter.next()); + } + + _defines.setText(Configuration.fromList(_config.getDefines(resource))); + _meta.setText(Configuration.fromList(_config.getMeta(resource))); + _stream.setSelection(_config.getStream()); + _tie.setSelection(_config.getTie(resource)); + _ice.setSelection(_config.getIce(resource)); + _underscore.setSelection(_config.getUnderscore(resource)); + _extraArguments.setText(_config.getExtraArguments(resource)); + } +} diff --git a/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/SourceSelectionDialog.java b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/SourceSelectionDialog.java new file mode 100644 index 00000000000..b9634da3415 --- /dev/null +++ b/eclipse/java/Slice2javaPlugin/src/com/zeroc/slice2javaplugin/properties/SourceSelectionDialog.java @@ -0,0 +1,254 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This plug-in is provided to you under the terms and conditions +// of the Eclipse Public License Version 1.0 ("EPL"). A copy of +// the EPL is available at http://www.eclipse.org/legal/epl-v10.html. +// +// ********************************************************************** + +package com.zeroc.slice2javaplugin.properties; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TreeSelection; +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.Shell; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.ui.dialogs.SelectionDialog; +import org.eclipse.ui.model.WorkbenchContentProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; + +class SourceSelectionDialog extends SelectionDialog +{ + // Do we allow multiple selections? + private boolean multiple = true; + + // the root element to populate the viewer with + private IProject root; + + // the visual selection widget group + private CheckboxTreeViewer selectionGroup; + + // constants + private final static int SIZING_SELECTION_WIDGET_WIDTH = 400; + + private final static int SIZING_SELECTION_WIDGET_HEIGHT = 300; + + /** + * Creates a resource selection dialog rooted at the given element. + * + * @param parentShell + * the parent shell + * @param rootElement + * the root element to populate this dialog with + * @param message + * the message to be displayed at the top of this dialog, or + * <code>null</code> to display a default message + */ + public SourceSelectionDialog(Shell parentShell, IProject project, String message) + { + super(parentShell); + setTitle("Source Folder Selection"); + root = project; + if(message != null) + { + setMessage(message); + } + else + { + setMessage("Select source folder:"); + } + } + + public void setMultiple(boolean m) + { + multiple = m; + } + + /* + * (non-Javadoc) Method declared in Window. + */ + protected void configureShell(Shell shell) + { + super.configureShell(shell); + //PlatformUI.getWorkbench().getHelpSystem().setHelp(shell, IIDEHelpContextIds.RESOURCE_SELECTION_DIALOG); + } + + public void create() + { + super.create(); + initializeDialog(); + } + + /* + * (non-Javadoc) Method declared on Dialog. + */ + protected Control createDialogArea(Composite parent) + { + // page group + Composite composite = (Composite) super.createDialogArea(parent); + + // create the input element, which has the root resource + // as its only child + ArrayList<IProject> input = new ArrayList<IProject>(); + input.add(root); + + createMessageArea(composite); + + Tree tree = new Tree(composite, ((multiple) ? SWT.CHECK : SWT.SINGLE) | SWT.BORDER); + GridData data = new GridData(GridData.FILL_BOTH); + data.widthHint = SIZING_SELECTION_WIDGET_WIDTH; + data.heightHint = SIZING_SELECTION_WIDGET_HEIGHT; + tree.setLayoutData(data); + tree.setFont(parent.getFont()); + + selectionGroup = new CheckboxTreeViewer(tree); + selectionGroup.setContentProvider(getResourceProvider(IResource.FILE | IResource.PROJECT)); + selectionGroup.setLabelProvider(WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider()); + selectionGroup.setInput(input); + + selectionGroup.expandToLevel(2); + + return composite; + } + + /** + * Returns a content provider for <code>IResource</code>s that returns only + * children of the given resource type. + */ + private ITreeContentProvider getResourceProvider(final int resourceType) + { + return new WorkbenchContentProvider() + { + @SuppressWarnings("unchecked") + public Object[] getChildren(Object o) + { + if(o instanceof IContainer) + { + IResource[] members = null; + try + { + members = ((IContainer) o).members(); + } + catch(CoreException e) + { + // just return an empty set of children + return new Object[0]; + } + + // filter out the desired resource types + ArrayList<Object> results = new ArrayList<Object>(); + for(int i = 0; i < members.length; i++) + { + if(members[i] instanceof IFolder) + { + results.add(members[i]); + } + } + return results.toArray(); + } + // input element case + if(o instanceof ArrayList) + { + return ((ArrayList<Object>) o).toArray(); + } + return new Object[0]; + } + }; + } + + /** + * Initializes this dialog's controls. + */ + private void initializeDialog() + { + getOkButton().setEnabled(false); + if(multiple) + { + selectionGroup.addCheckStateListener(new ICheckStateListener() + { + public void checkStateChanged(CheckStateChangedEvent event) + { + if(!event.getChecked() && selectionGroup.getGrayed(event.getElement())) + { + selectionGroup.setChecked(event.getElement(), true); + } + else + { + int count = selectionGroup.getCheckedElements().length - getInitialElementSelections().size(); + getOkButton().setEnabled(count > 0); + } + } + }); + + for(Iterator<?> iter = getInitialElementSelections().iterator(); iter.hasNext(); ) + { + IResource cur = (IResource)iter.next(); + selectionGroup.setGrayChecked(cur, true); + } + } + else + { + selectionGroup.addSelectionChangedListener(new ISelectionChangedListener() + { + public void selectionChanged(SelectionChangedEvent event) + { + getOkButton().setEnabled(true); + } + }); + } + } + + /** + * The <code>ResourceSelectionDialog</code> implementation of this + * <code>Dialog</code> method builds a list of the selected resources for + * later retrieval by the client and closes this dialog. + */ + protected void okPressed() + { + /* + * Iterator resultEnum = selectionGroup.getAllCheckedListItems(); + * ArrayList list = new ArrayList(); while (resultEnum.hasNext()) { + * list.add(resultEnum.next()); } setResult(list); + */ + ArrayList<Object> list = new ArrayList<Object>(); + if(multiple) + { + Object[] objs = selectionGroup.getCheckedElements(); + for(int i = 0; i < objs.length; ++i) + { + if(!selectionGroup.getGrayed(objs[i])) + { + list.add(objs[i]); + } + } + } + else + { + TreeSelection obj = (TreeSelection)selectionGroup.getSelection(); + if(!obj.isEmpty()) + { + list.add(obj.getFirstElement()); + } + } + setResult(list); + super.okPressed(); + } +} |