diff options
8 files changed, 584 insertions, 12 deletions
diff --git a/plugins/org.eclipse.emf.cdo.migrator/plugin.xml b/plugins/org.eclipse.emf.cdo.migrator/plugin.xml index 7ddf71bc50..a721ec82f9 100644 --- a/plugins/org.eclipse.emf.cdo.migrator/plugin.xml +++ b/plugins/org.eclipse.emf.cdo.migrator/plugin.xml @@ -59,10 +59,12 @@ </extension> <extension point="org.eclipse.ant.core.antTasks"> - <antTask library="ant_tasks/cdo.ant.tasks.jar" name="cdo.ProjectImport" headless="true" class="org.eclipse.emf.cdo.internal.migrator.tasks.ProjectImportTask" /> - <antTask library="ant_tasks/cdo.ant.tasks.jar" name="cdo.ProjectDelete" headless="true" class="org.eclipse.emf.cdo.internal.migrator.tasks.ProjectDeleteTask" /> + <antTask library="ant_tasks/cdo.ant.tasks.jar" name="cdo.ImportProject" headless="true" class="org.eclipse.emf.cdo.internal.migrator.tasks.ImportProjectTask" /> + <antTask library="ant_tasks/cdo.ant.tasks.jar" name="cdo.DeleteProject" headless="true" class="org.eclipse.emf.cdo.internal.migrator.tasks.DeleteProjectTask" /> <antTask library="ant_tasks/cdo.ant.tasks.jar" name="cdo.MigrateModel" headless="true" class="org.eclipse.emf.cdo.internal.migrator.tasks.MigrateModelTask" /> <antTask library="ant_tasks/cdo.ant.tasks.jar" name="cdo.GenerateModel" headless="true" class="org.eclipse.emf.cdo.internal.migrator.tasks.GenerateModelTask" /> + <antTask library="ant_tasks/cdo.ant.tasks.jar" name="cdo.ExpandTemplate" headless="true" class="org.eclipse.emf.cdo.internal.migrator.tasks.ExpandTemplateTask" /> + <antTask library="ant_tasks/cdo.ant.tasks.jar" name="cdo.TransferMembers" headless="true" class="org.eclipse.emf.cdo.internal.migrator.tasks.TransferMembersTask" /> </extension> </plugin> diff --git a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/CDOTask.java b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/CDOTask.java index ed83e6d210..fa7c26366c 100644 --- a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/CDOTask.java +++ b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/CDOTask.java @@ -20,15 +20,38 @@ import org.eclipse.core.runtime.NullProgressMonitor; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.CharArrayReader; +import java.io.CharArrayWriter; +import java.io.Closeable; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; + /** * @author Eike Stepper */ public abstract class CDOTask extends Task { + public static final String NL = System.getProperty("line.separator"); + + public static final int EOF = -1; + protected final IWorkspace workspace = ResourcesPlugin.getWorkspace(); protected final IWorkspaceRoot root = workspace.getRoot(); + protected boolean verbose = true; + + public void setVerbose(boolean verbose) + { + this.verbose = verbose; + } + @Override public final void execute() throws BuildException { @@ -62,6 +85,14 @@ public abstract class CDOTask extends Task protected abstract void doExecute() throws Exception; + protected final void log(Object object) + { + if (verbose) + { + System.out.println(object); + } + } + protected final IProgressMonitor getProgressMonitor() { try @@ -90,4 +121,76 @@ public abstract class CDOTask extends Task throw new BuildException(message); } } + + public static String readTextFile(File file) throws IOException + { + Reader input = new FileReader(file); + + try + { + CharArrayWriter output = new CharArrayWriter(); + copyCharacter(input, output); + return output.toString(); + } + finally + { + closeSilent(input); + } + } + + public static void writeTextFile(File file, String content) throws IOException + { + Writer output = new FileWriter(file); + + try + { + CharArrayReader input = new CharArrayReader(content.toCharArray()); + copyCharacter(input, output); + } + finally + { + closeSilent(output); + } + } + + private static Exception closeSilent(Closeable closeable) + { + try + { + if (closeable != null) + { + closeable.close(); + } + + return null; + } + catch (Exception ex) + { + return ex; + } + } + + private static long copyCharacter(Reader reader, Writer writer) throws IOException + { + if (!(reader instanceof BufferedReader) && !(reader instanceof CharArrayReader)) + { + reader = new BufferedReader(reader); + } + + if (!(writer instanceof BufferedWriter) && !(writer instanceof CharArrayWriter)) + { + writer = new BufferedWriter(writer); + } + + long size = 0; + int c; + while ((c = reader.read()) != EOF) + { + writer.write(c); + ++size; + } + + writer.flush(); + return size; + } } diff --git a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ProjectDeleteTask.java b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/DeleteProjectTask.java index cce0df56a8..2f4482cee8 100644 --- a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ProjectDeleteTask.java +++ b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/DeleteProjectTask.java @@ -18,7 +18,7 @@ import org.apache.tools.ant.BuildException; /** * @author Eike Stepper */ -public class ProjectDeleteTask extends CDOTask +public class DeleteProjectTask extends CDOTask { private String projectName; @@ -46,11 +46,11 @@ public class ProjectDeleteTask extends CDOTask IProject project = root.getProject(projectName); if (!project.exists()) { - System.out.println("Project " + projectName + " does not exist."); + log("Project " + projectName + " does not exist."); return; } - System.out.println("Deleting project " + projectName + " ..."); + log("Deleting project " + projectName + " ..."); project.delete(deleteContent, true, new NullProgressMonitor()); } } diff --git a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ExpandTemplateTask.java b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ExpandTemplateTask.java new file mode 100644 index 0000000000..d610d68109 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ExpandTemplateTask.java @@ -0,0 +1,172 @@ +package org.eclipse.emf.cdo.internal.migrator.tasks; + +import org.apache.tools.ant.BuildException; + +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Eike Stepper + */ +public class ExpandTemplateTask extends CDOTask +{ + private final List<Property> properties = new ArrayList<Property>(); + + private File template; + + private File target; + + private String placeholderPrefix = "%%"; + + private String placeholderSuffix = "%%"; + + public Property createProperty() + { + Property property = new Property(); + properties.add(property); + return property; + } + + public void setTemplate(File template) + { + this.template = template; + } + + public void setPlaceholderPrefix(String placeholderPrefix) + { + this.placeholderPrefix = placeholderPrefix; + } + + public void setPlaceholderSuffix(String placeholderSuffix) + { + this.placeholderSuffix = placeholderSuffix; + } + + public void setTarget(File target) + { + this.target = target; + } + + @Override + protected void checkAttributes() throws BuildException + { + assertTrue("'template' must be specified.", template != null); + assertTrue("'template' must be point to an existing file.", template.isFile()); + assertTrue("'target' must be specified.", target != null); + assertTrue("'placeholderPrefix' must be specified.", placeholderPrefix != null && placeholderPrefix.length() != 0); + assertTrue("'placeholderSuffix' must be specified.", placeholderSuffix != null && placeholderSuffix.length() != 0); + + for (Property property : properties) + { + String name = property.getName(); + assertTrue("'name' of property must be specified.", name != null && name.length() != 0); + } + } + + @Override + protected void doExecute() throws Exception + { + String content = readTextFile(template); + Map<String, String> properties = getProperties(); + + String result = generate(content, properties); + writeTextFile(target, result); + } + + protected String generate(String content, Map<String, String> properties) throws Exception + { + StringBuilder result = new StringBuilder(content); + + for (Map.Entry<String, String> entry : properties.entrySet()) + { + String placeholder = formatPlaceholder(entry.getKey()); + String value = entry.getValue(); + if (value == null) + { + value = ""; + } + + int placeholderLength = placeholder.length(); + int valueLength = value.length(); + int start = 0; + + for (;;) + { + int pos = result.indexOf(placeholder, start); + if (pos == -1) + { + break; + } + + result.replace(pos, pos + placeholderLength, value); + start = pos + valueLength; + } + } + + return result.toString(); + } + + protected String formatPlaceholder(String name) + { + return placeholderPrefix + name + placeholderSuffix; + } + + protected Map<String, String> getProperties() + { + Map<String, String> result = new LinkedHashMap<String, String>(); + + for (Property property : properties) + { + result.put(property.getName(), property.getValue()); + } + + return result; + } + + /** + * @author Eike Stepper + */ + public static final class Property + { + private String name; + + private String value; + + public Property() + { + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getValue() + { + return value; + } + + public void setValue(String value) + { + this.value = value; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append(name); + builder.append(" = "); + builder.append(value); + return builder.toString(); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/GenerateModelTask.java b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/GenerateModelTask.java index 89f420ce49..9eedadc207 100644 --- a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/GenerateModelTask.java +++ b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/GenerateModelTask.java @@ -19,6 +19,9 @@ import org.eclipse.emf.codegen.ecore.genmodel.generator.GenBaseGeneratorAdapter; import org.eclipse.emf.codegen.ecore.genmodel.util.GenModelUtil; import org.eclipse.emf.common.util.BasicMonitor; import org.eclipse.emf.common.util.Diagnostic; +import org.eclipse.emf.common.util.Monitor; + +import org.eclipse.core.runtime.NullProgressMonitor; import org.apache.tools.ant.BuildException; @@ -54,8 +57,9 @@ public class GenerateModelTask extends CDOTask throw new BuildException(diagnostic.getException()); } + Monitor monitor = verbose ? new BasicMonitor.Printing(System.out) : BasicMonitor.toMonitor(new NullProgressMonitor()); + Generator generator = GenModelUtil.createGenerator(genModel); - generator.generate(genModel, GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE, CodeGenEcorePlugin.INSTANCE.getString("_UI_ModelProject_name"), - new BasicMonitor.Printing(System.out)); + generator.generate(genModel, GenBaseGeneratorAdapter.MODEL_PROJECT_TYPE, CodeGenEcorePlugin.INSTANCE.getString("_UI_ModelProject_name"), monitor); } } diff --git a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ProjectImportTask.java b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ImportProjectTask.java index 4b23ee759d..c95b6ada2f 100644 --- a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ProjectImportTask.java +++ b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/ImportProjectTask.java @@ -23,7 +23,7 @@ import java.io.File; /** * @author Eike Stepper */ -public class ProjectImportTask extends CDOTask +public class ImportProjectTask extends CDOTask { private String projectName; @@ -59,11 +59,11 @@ public class ProjectImportTask extends CDOTask throw new BuildException("Project " + projectName + " exists in different location: " + existingLocation); } - System.out.println("Project " + fromLocation + " is already imported."); + log("Project " + fromLocation + " is already imported."); return; } - System.out.println("Importing project " + fromLocation + " ..."); + log("Importing project " + fromLocation + " ..."); IPath locationPath = new Path(fromLocation.getAbsolutePath()); IProjectDescription projectDescription = workspace.newProjectDescription(projectName); diff --git a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/MigrateModelTask.java b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/MigrateModelTask.java index 01e24de19d..cb9033d41e 100644 --- a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/MigrateModelTask.java +++ b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/MigrateModelTask.java @@ -52,12 +52,12 @@ public class MigrateModelTask extends CDOTask String msg = CDOMigratorUtil.adjustGenModel(genModel, featureDelegation); if (msg == null) { - System.out.println(Messages.getString("MigrateAction_3")); + log(Messages.getString("MigrateAction_3")); } else { genModel.eResource().save(null); - System.out.println(Messages.getString("MigrateAction_4") + msg); + log(Messages.getString("MigrateAction_4") + msg); } } } diff --git a/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/TransferMembersTask.java b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/TransferMembersTask.java new file mode 100644 index 0000000000..30b6b0f2c1 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.migrator/src/org/eclipse/emf/cdo/internal/migrator/tasks/TransferMembersTask.java @@ -0,0 +1,291 @@ +package org.eclipse.emf.cdo.internal.migrator.tasks; + +import org.apache.tools.ant.BuildException; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Eike Stepper + */ +public class TransferMembersTask extends ExpandTemplateTask +{ + private File sourceClass; + + private String importsPlaceholder = "IMPORTS"; + + private String fieldsPlaceholder = "FIELDS"; + + private String methodsPlaceholder = "METHODS"; + + private boolean transferImports = true; + + private final List<TransferField> transferFields = new ArrayList<TransferField>(); + + private final List<TransferMethod> transferMethods = new ArrayList<TransferMethod>(); + + public void setSourceClass(File sourceClass) + { + this.sourceClass = sourceClass; + } + + public void setImportsPlaceholder(String importsPlaceholder) + { + this.importsPlaceholder = importsPlaceholder; + } + + public void setFieldsPlaceholder(String fieldsPlaceholder) + { + this.fieldsPlaceholder = fieldsPlaceholder; + } + + public void setMethodsPlaceholder(String methodsPlaceholder) + { + this.methodsPlaceholder = methodsPlaceholder; + } + + public void setTransferImports(boolean transferImports) + { + this.transferImports = transferImports; + } + + public TransferField createTransferField() + { + TransferField transferField = new TransferField(); + transferFields.add(transferField); + return transferField; + } + + public TransferMethod createTransferMethod() + { + TransferMethod transferMethod = new TransferMethod(); + transferMethods.add(transferMethod); + return transferMethod; + } + + @Override + protected void checkAttributes() throws BuildException + { + super.checkAttributes(); + assertTrue("'sourceClass' must be specified.", sourceClass != null); + assertTrue("'sourceClass' must be point to an existing file.", sourceClass.isFile()); + assertTrue("'importsPlaceholder' must be specified.", importsPlaceholder != null && importsPlaceholder.length() != 0); + assertTrue("'fieldsPlaceholder' must be specified.", fieldsPlaceholder != null && fieldsPlaceholder.length() != 0); + assertTrue("'methodsPlaceholder' must be specified.", methodsPlaceholder != null && methodsPlaceholder.length() != 0); + + checkTransferMembers(transferFields); + checkTransferMembers(transferMethods); + } + + private void checkTransferMembers(List<? extends TransferMember> transferMembers) + { + for (TransferMember transferMember : transferMembers) + { + String pattern = transferMember.getPattern(); + assertTrue("'pattern' must be specified.", pattern != null && pattern.length() != 0); + } + } + + @Override + protected String generate(String content, Map<String, String> properties) throws Exception + { + Collector collector = new Collector(sourceClass); + + StringBuilder imports = new StringBuilder(); + if (transferImports) + { + for (String name : collector.imports.keySet()) + { + imports.append("import "); + imports.append(name); + imports.append(";"); + imports.append(NL); + } + } + + properties.put(importsPlaceholder, imports.toString()); + properties.put(fieldsPlaceholder, formatMembers(collector.fields, transferFields)); + properties.put(methodsPlaceholder, formatMembers(collector.methods, transferMethods)); + + return super.generate(content, properties); + } + + private String formatMembers(Map<String, List<String>> members, List<? extends TransferMember> transferMembers) + { + if (transferMembers.isEmpty()) + { + return ""; + } + + List<Pattern> patterns = new ArrayList<Pattern>(); + for (TransferMember transferMember : transferMembers) + { + patterns.add(Pattern.compile(transferMember.getPattern())); + } + + StringBuilder builder = new StringBuilder(); + boolean first = true; + + for (Map.Entry<String, List<String>> entry : members.entrySet()) + { + String name = entry.getKey(); + for (Pattern pattern : patterns) + { + if (pattern.matcher(name).matches()) + { + List<String> texts = entry.getValue(); + for (String text : texts) + { + if (first) + { + first = false; + } + else + { + builder.append(NL); + builder.append(NL); + } + + builder.append(text); + } + + break; + } + } + } + + return builder.toString(); + } + + /** + * @author Eike Stepper + */ + public static abstract class TransferMember + { + private String pattern; + + public String getPattern() + { + return pattern; + } + + public void setPattern(String pattern) + { + this.pattern = pattern; + } + } + + /** + * @author Eike Stepper + */ + public static final class TransferField extends TransferMember + { + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("TransferField["); + builder.append(getPattern()); + builder.append("]"); + return builder.toString(); + } + } + + /** + * @author Eike Stepper + */ + public static final class TransferMethod extends TransferMember + { + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("TransferMethod["); + builder.append(getPattern()); + builder.append("]"); + return builder.toString(); + } + } + + /** + * @author Eike Stepper + */ + private static final class Collector + { + private static final Pattern IMPORT_PATTERN = Pattern.compile("[\\\\t ]*import\\s+([^;]+);"); + + private static final Pattern FIELD_PATTERN = Pattern + .compile("[\\\\t ]*((public|private|protected|static|final|transient|volatile)+\\s)+[\\$_\\w\\<\\>\\[\\]]*\\s+([\\$_\\w]+)\\s*(;|=[^;]*;)"); + + private static final Pattern METHOD_PATTERN = Pattern.compile( + "[\\t ]*((public|private|protected|static|final|native|synchronized|abstract|strictfp)+\\s)+[\\$_\\w\\<\\>\\[\\]]*\\s+(([\\$_\\w]+)\\([^\\)]*\\)?)[^\\{;]*(.)"); + + public final Map<String, List<String>> imports = new LinkedHashMap<String, List<String>>(); + + public final Map<String, List<String>> fields = new LinkedHashMap<String, List<String>>(); + + public final Map<String, List<String>> methods = new LinkedHashMap<String, List<String>>(); + + public Collector(File file) throws IOException + { + String content = readTextFile(file); + collect(content, IMPORT_PATTERN, 1, imports); + collect(content, FIELD_PATTERN, 3, fields); + collect(content, METHOD_PATTERN, 4, methods); + } + + private static void collect(String content, Pattern pattern, int group, Map<String, List<String>> result) + { + Matcher matcher = pattern.matcher(content); + while (matcher.find()) + { + String text = matcher.group(0); + String name = matcher.group(group); + + if (pattern == METHOD_PATTERN) + { + String braceOrSemicolon = matcher.group(5); + if (braceOrSemicolon.equals("{")) + { + int start = matcher.end(); + int end = content.length(); + int nesting = 1; + + for (int i = start; i < end; i++) + { + char c = content.charAt(i); + if (c == '{') + { + ++nesting; + } + else if (c == '}') + { + if (--nesting == 0) + { + String body = content.substring(start, i + 1); + text += body; + break; + } + } + } + } + } + + List<String> texts = result.get(name); + if (texts == null) + { + texts = new ArrayList<String>(); + result.put(name, texts); + } + + texts.add(text); + } + } + } +} |