简体   繁体   中英

Issue with Eclipse plugin (copying a file)

Ok, so I've written a plugin for Eclipse (ok, so it's mostly copied code from ADT). It is a new project wizard which does essentially the same thing as ADT's new Project wizard, only it copies over a library, adds it to the build path, and copies over some other files. This all works fine.

The library is called AltBridge, which was built from App Inventor's Java Bridge library. This library essentially changes how you write an activity a little bit, and I wanted to add a menu option to create a new Form (which is a modified Activity).

This is where Eclipse is being bothersome. I got it to work fine if I hit F11. It creates the new file no problem. However, when I export the plugin, and try it, it doesn't work.

Here's what I have so far:

public class NewFormMenuSelection extends AbstractHandler implements IHandler {

private static final String PARAM_PACKAGE = "PACKAGE";  
private static final String PARAM_ACTIVITY = "ACTIVITY_NAME"; 
private static final String PARAM_IMPORT_RESOURCE_CLASS = "IMPORT_RESOURCE_CLASS";
private Map<String, Object> java_activity_parameters = new HashMap<String, Object>();

public Object execute(ExecutionEvent event) throws ExecutionException {

    IStructuredSelection selection = (IStructuredSelection) HandlerUtil
            .getActiveMenuSelection(event);
    String directory = "";
    Object firstElement = selection.getFirstElement();
    if (firstElement instanceof IPackageFragment) {
        InputDialog dialog = new InputDialog(HandlerUtil.getActiveShell(event), "Name of the new Form to create?", "Please enter the name of the new form to create.", "NewForm", null);
        if ( dialog.open()==IStatus.OK ) {
            String activityName = dialog.getValue();


        String packageName = ((IPackageFragment) firstElement).getElementName();

        if (activityName != null) {

            String resourcePackageClass = null;

            // An activity name can be of the form ".package.Class", ".Class" or FQDN.
            // The initial dot is ignored, as it is always added later in the templates.
            int lastDotIndex = activityName.lastIndexOf('.');

            if (lastDotIndex != -1) {

                // Resource class
                if (lastDotIndex > 0) {
                    resourcePackageClass = packageName + "." + AdtConstants.FN_RESOURCE_BASE; //$NON-NLS-1$
                }

                // Package name
                if (activityName.startsWith(".")) {  //$NON-NLS-1$
                    packageName += activityName.substring(0, lastDotIndex);
                } else {
                    packageName = activityName.substring(0, lastDotIndex);
                }

                // Activity Class name
                activityName = activityName.substring(lastDotIndex + 1);
            }
        java_activity_parameters.put(PARAM_IMPORT_RESOURCE_CLASS, "");
        java_activity_parameters.put(PARAM_ACTIVITY, activityName);
        java_activity_parameters.put(PARAM_PACKAGE, packageName);
        if (resourcePackageClass != null) {
            String importResourceClass = "\nimport " + resourcePackageClass + ";";  //$NON-NLS-1$ // $NON-NLS-2$
            java_activity_parameters.put(PARAM_IMPORT_RESOURCE_CLASS, importResourceClass);
        }
        if (activityName != null) {
            // create the main activity Java file
            // get the path of the package
            IPath path = ((IPackageFragment) firstElement).getPath();                
            String pkgpath = path.toString();
            // Get the project name
            String activityJava = activityName + AdtConstants.DOT_JAVA;
            String projname = ((IPackageFragment) firstElement).getParent().getJavaProject().getElementName();

            // Get the project
            IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projname);
            IFolder pkgFolder = project.getFolder(pkgpath);

            IFile file = pkgFolder.getFile(activityJava);
            if (!file.exists()) {
                try {
                    copyFile("java_file.template", file, java_activity_parameters, false);
                } catch (CoreException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
    }
    }
    return null;
}


private void copyFile(String resourceFilename, IFile destFile,
        Map<String, Object> parameters, boolean reformat)
        throws CoreException, IOException {

    // Read existing file.
    String template = AltBridge.readEmbeddedTextFile(
            "templates/" + resourceFilename);

    // Replace all keyword parameters
    template = replaceParameters(template, parameters);

    if (reformat) {
        // Guess the formatting style based on the file location
        XmlFormatStyle style = XmlFormatStyle.getForFile(destFile.getProjectRelativePath());
        if (style != null) {
            template = reformat(style, template);
        }
    }

    // Save in the project as UTF-8
    InputStream stream = new ByteArrayInputStream(template.getBytes("UTF-8")); //$NON-NLS-1$
    destFile.create(stream, true /* force */, null);
}

private String replaceParameters(String str, Map<String, Object> parameters) {

    if (parameters == null) {
        AltBridge.log(IStatus.ERROR,
                "NPW replace parameters: null parameter map. String: '%s'", str);  //$NON-NLS-1$
        return str;
    } else if (str == null) {
        AltBridge.log(IStatus.ERROR,
                "NPW replace parameters: null template string");  //$NON-NLS-1$
        return str;
    }

    for (Entry<String, Object> entry : parameters.entrySet()) {
        if (entry != null && entry.getValue() instanceof String) {
            Object value = entry.getValue();
            if (value == null) {
                AltBridge.log(IStatus.ERROR,
                "NPW replace parameters: null value for key '%s' in template '%s'",  //$NON-NLS-1$
                entry.getKey(),
                str);
            } else {
                str = str.replaceAll(entry.getKey(), (String) value);
            }
        }
    }

    return str;
}

private String reformat(XmlFormatStyle style, String contents) {
    if (AdtPrefs.getPrefs().getUseCustomXmlFormatter()) {
        XmlFormatPreferences formatPrefs = XmlFormatPreferences.create();
        return XmlPrettyPrinter.prettyPrint(contents, formatPrefs, style,
                null /*lineSeparator*/);
    } else {
        return contents;
   }
}

The part I seem to be having the problem with is under where it says // create the main activity java file.

In order to get it to work when hitting F11, I had to drop the first two entries of the package (I know I could have probably done this a better way, but it works). Otherwise, for some reason, it added the project name to the path at the beginning (doubling it). If left this way, it won't work when exported and tried outside of the testing environment. It gives an error saying that the project name must be in the path. So, if I remove the section that drops that, it doesn't work when hitting F11, and outside the build environment, it doesn't work, and doesn't give any kind of error. Any clues on what I may be doing wrong?

Here's the copy file code (again, this is just copied from the ADT plugin) :

public static String readEmbeddedTextFile(String filepath) {
    try {
        InputStream is = readEmbeddedFileAsStream(filepath);
        if (is != null) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));

            String line;
            StringBuilder total = new StringBuilder(reader.readLine());
            while ((line = reader.readLine()) != null) {
                total.append('\n');
                total.append(line);
            }

            return total.toString();
        }
    } catch (IOException e) {
        // we'll just return null
        AltBridge.log(e, "Failed to read text file '%s'", filepath);  //$NON-NLS-1$
    }

    return null;
}

public static InputStream readEmbeddedFileAsStream(String filepath) {
    // attempt to read an embedded file
    try {
        URL url = getEmbeddedFileUrl(AdtConstants.WS_SEP + filepath);
        if (url != null) {
            return url.openStream();
        }
    } catch (MalformedURLException e) {
        // we'll just return null.
        AltBridge.log(e, "Failed to read stream '%s'", filepath);  //$NON-NLS-1$
    } catch (IOException e) {
        // we'll just return null;.
        AltBridge.log(e, "Failed to read stream '%s'", filepath);  //$NON-NLS-1$
    }

    return null;
}

public static URL getEmbeddedFileUrl(String filepath) {
    Bundle bundle = null;
    synchronized (AltBridge.class) {
        if (plugin != null) {
            bundle = plugin.getBundle();
        } else {
            AltBridge.log(IStatus.WARNING, "ADT Plugin is missing");    //$NON-NLS-1$
            return null;
        }
    }

    // attempt to get a file to one of the template.
    String path = filepath;
    if (!path.startsWith(AdtConstants.WS_SEP)) {
        path = AdtConstants.WS_SEP + path;
    }

    URL url = bundle.getEntry(path);

    if (url == null) {
        AltBridge.log(IStatus.INFO, "Bundle file URL not found at path '%s'", path); //$NON-NLS-1$
    }

    return url;
}

Ok, the issue seems to be with IProject, or IFolder. The path gets returned as "test/src/com/test" for example. Then, when I use pkgfolder.getFile, it adds another /test/ in front of the path (this is when testing by hitting F11 in eclipse).

Ok, I was making it more complicated than it needed to be of course. Here's the code I used that worked. (I still don't understand why Eclipse behaves so strangely...why would something work when testing by using F11, but not when the plugin is deployed?).

This is also just the section // create the main activity Java file:

if (activityName != null) {
    // create the main activity Java file

    String activityJava = activityName + AdtConstants.DOT_JAVA;

    // Get the path of the package

    IPath path = ((IPackageFragment) firstElement).getPath();
    String pkgpath = path.toString();                               

    String projname = "";

    // Remove the project name from the beginning of the path
    String temp[] = pkgpath.split("/");
    pkgpath = "";
    for (int i = 1; i < temp.length; i++) {
        if (i==1) {
            pkgpath = "/";
            projname = temp[i];
        } else {
            pkgpath = pkgpath + "/" + temp[i];
        }
    }

    // Get the project                
    IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projname);  

    IFile file = project.getFile(pkgpath+"/"+activityJava);
    if (!file.exists()) {
        try {
            copyFile("java_file.template", file, java_activity_parameters);
        } catch (CoreException e) {
            AltBridge.log(e, "Couldn't copy the text file", pkgpath);
            e.printStackTrace();
        } catch (IOException e) {
            AltBridge.log(e, "Couldn't copy the text file", pkgpath);
            e.printStackTrace();
        }
    }
}

To manage files in packages, you need to use Eclipse's Bundle class . There's an example in my PhoneGap project creation wizard in the bundleCopy method here .

Ok, the issue seems to be with IProject, or IFolder. The path gets returned as "test/src/com/test" for example. Then, when I use pkgfolder.getFile, it adds another /test/ in front of the path (this is when testing by hitting F11 in eclipse).

So if the path is test/src/com/test, then test must be the project. Use IWorkspaceRoot.findMember(path). And put a "/" in front of the path. There is no need to do that other stuff of finding the project/folder, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM