package saros.stf.server.rmi.superbot.internal.impl; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.rmi.RemoteException; import java.util.Arrays; import java.util.HashSet; import java.util.Random; import java.util.Set; import org.apache.log4j.Logger; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jdt.launching.LibraryLocation; import saros.stf.server.StfRemoteObject; import saros.stf.server.rmi.superbot.internal.IInternal; import saros.versioning.Version; import saros.versioning.VersionManager; public final class InternalImpl extends StfRemoteObject implements IInternal { private static final Logger log = Logger.getLogger(InternalImpl.class); private static final InternalImpl INSTANCE = new InternalImpl(); private Field localVersionField; private Version originalVersion; private static class GeneratingInputStream extends InputStream { private Random random = null; private int size; public GeneratingInputStream(int size, boolean compressAble) { this.size = size; if (!compressAble) this.random = new Random(); } @Override public int read() throws IOException { if (size == 0) return -1; size--; if (random != null) return random.nextInt() & 0xFF; return 'A'; } } public static IInternal getInstance() { return INSTANCE; } private InternalImpl() { try { localVersionField = VersionManager.class.getDeclaredField("localVersion"); localVersionField.setAccessible(true); } catch (SecurityException e) { log.error("reflection failed", e); localVersionField = null; } catch (NoSuchFieldException e) { log.error("reflection failed", e); localVersionField = null; } } @Override public void changeSarosVersion(String version) throws RemoteException { Version newVersion; log.trace("attempting to change saros version to: " + version); if (localVersionField == null) { log.error("unable to change version, reflection failed during initialization"); throw new IllegalStateException( "unable to change version, reflection failed during initialization"); } try { newVersion = Version.parseVersion(version); } catch (IllegalArgumentException e) { log.error(e.getMessage(), e); throw e; } try { if (originalVersion == null) originalVersion = (Version) localVersionField.get(getVersionManager()); localVersionField.set(getVersionManager(), newVersion); getInfoManager().setLocalInfo(VersionManager.VERSION_KEY, newVersion.toString()); } catch (IllegalArgumentException e) { log.error("unable to change saros version, reflection failed", e); throw new RemoteException("unable to change saros version, reflection failed", e); } catch (IllegalAccessException e) { log.error("unable to change saros version, reflection failed", e); throw new RemoteException("unable to change saros version, reflection failed", e); } } @Override public void resetSarosVersion() throws RemoteException { log.trace("attempting to reset saros version"); if (originalVersion == null) { log.trace("saros version was not changed"); return; } try { localVersionField.set(getVersionManager(), originalVersion); getInfoManager().setLocalInfo(VersionManager.VERSION_KEY, originalVersion.toString()); } catch (IllegalArgumentException e) { log.error("unable to reset saros version, reflection failed", e); throw new RemoteException("unable to reset saros version, reflection failed", e); } catch (IllegalAccessException e) { log.error("unable to reset saros version, reflection failed", e); throw new RemoteException("unable to reset saros version, reflection failed", e); } log.trace("changed saros version to its default state"); originalVersion = null; } @Override public void createFile(String projectName, String path, String content) throws RemoteException { log.trace( "creating file in project '" + projectName + "', path '" + path + "' content: " + content); path = path.replace('\\', '/'); int idx = path.lastIndexOf('/'); if (idx != -1) createFolder(projectName, path.substring(0, idx)); IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); IFile file = project.getFile(path); try { file.create( new ByteArrayInputStream(content.getBytes(project.getDefaultCharset())), true, null); } catch (CoreException e) { log.error(e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } catch (UnsupportedEncodingException e) { log.error(e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } } @Override public void append(String projectName, String path, String content) throws RemoteException { log.trace( "appending content '" + content + "' to file '" + path + "' in project '" + projectName + "'"); path = path.replace('\\', '/'); IFile file = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getFile(path); try { file.appendContents(new ByteArrayInputStream(content.getBytes()), true, false, null); } catch (CoreException e) { log.error(e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } } @Override public void createFile(String projectName, String path, int size, boolean compressAble) throws RemoteException { log.trace( "creating file in project '" + projectName + "', path '" + path + "' size: " + size + ", compressAble=" + compressAble); path = path.replace('\\', '/'); int idx = path.lastIndexOf('/'); if (idx != -1) createFolder(projectName, path.substring(0, idx)); IFile file = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getFile(path); try { file.create(new GeneratingInputStream(size, compressAble), true, null); } catch (CoreException e) { log.error(e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } } @Override public boolean clearWorkspace() throws RemoteException { boolean error = false; for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) { try { log.trace("deleting project: " + project.getName()); project.delete(true, true, null); } catch (CoreException e) { error = true; log.error("unable to delete project '" + project.getName() + "' :" + e.getMessage(), e); } } return !error; } @Override public long getFileSize(String projectName, String path) throws RemoteException { return new File( ResourcesPlugin.getWorkspace() .getRoot() .getProject(projectName) .getFile(path) .getLocationURI()) .length(); } @Override public void createProject(String projectName) throws RemoteException { log.trace("creating project: " + projectName); IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); try { project.create(null); project.open(null); } catch (CoreException e) { log.error("unable to create project '" + projectName + "' : " + e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } } @Override public void createJavaProject(String projectName) throws RemoteException { log.trace("creating java project: " + projectName); IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); try { project.create(null); project.open(null); IProjectDescription description = project.getDescription(); description.setNatureIds(new String[] {JavaCore.NATURE_ID}); project.setDescription(description, null); IJavaProject javaProject = JavaCore.create(project); Set<IClasspathEntry> entries = new HashSet<IClasspathEntry>(); entries.add(JavaCore.newSourceEntry(javaProject.getPath().append("src"), new IPath[0])); IVMInstall vmInstall = JavaRuntime.getDefaultVMInstall(); LibraryLocation[] locations = JavaRuntime.getLibraryLocations(vmInstall); for (LibraryLocation element : locations) { entries.add(JavaCore.newLibraryEntry(element.getSystemLibraryPath(), null, null)); } javaProject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null); } catch (CoreException e) { log.error("unable to create java project '" + projectName + "' :" + e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } } @Override public void createFolder(String projectName, String path) throws RemoteException { path = path.replace('\\', '/'); IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); try { String segments[] = path.split("/"); IFolder folder = project.getFolder(segments[0]); log.trace(Arrays.asList(segments)); if (!folder.exists()) folder.create(true, true, null); if (segments.length <= 1) return; for (int i = 1; i < segments.length; i++) { folder = folder.getFolder(segments[i]); if (!folder.exists()) folder.create(true, true, null); } } catch (CoreException e) { log.error(e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } } @Override public void createJavaClass(String projectName, String packageName, String className) throws RemoteException { String path = "src/" + packageName.replace(".", "/") + "/" + className + ".java"; StringBuilder content = new StringBuilder(); if (packageName.trim().length() > 0) content.append("package ").append(packageName).append(';').append('\n').append('\n'); content.append("public class ").append(className).append(" {\n\n}"); createFile(projectName, path, content.toString()); } @Override public boolean existsResource(String path) throws RemoteException { return ResourcesPlugin.getWorkspace().getRoot().exists(new Path(path)); } @Override public byte[] getFileContent(String projectName, String path) throws RemoteException { int size = (int) getFileSize(projectName, path); IFile file = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName).getFile(path); byte[] content = new byte[size]; DataInputStream in; try { in = new DataInputStream(file.getContents()); } catch (CoreException e) { log.error(e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } try { in.readFully(content); in.close(); } catch (IOException e) { throw new RemoteException("error while reading file:" + file, e); } return content; } @Override public void changeProjectEncoding(String projectName, String charset) throws RemoteException { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); try { project.setDefaultCharset(charset, null); } catch (CoreException e) { log.error(e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } } @Override public void changeFileEncoding(String projectName, String path, String charset) throws RemoteException { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); IFile file = project.getFile(path); try { file.setCharset(charset, null); } catch (CoreException e) { log.error(e.getMessage(), e); throw new RemoteException(e.getMessage(), e.getCause()); } } }