diff --git a/cored/config/cored.properties b/cored/config/cored.properties index 7d6650a..cefbb13 100644 --- a/cored/config/cored.properties +++ b/cored/config/cored.properties @@ -1,15 +1,15 @@ # The directory to contain the projects created with Cored. -PROJECTS_ROOT_DIR = C:\\Users\\niemin75\\Desktop\\cored_projects +PROJECTS_ROOT_DIR = C:\\Users\\arcarons\\cored\\projects # The build template directory. # You can get the build template from http://www.cs.tut.fi/~niemin75/cored/BuildTemplate.zip -WAR_BUILD_TEMPLATE_DIR = C:\\Users\\niemin75\\Desktop\\BuildTemplate +WAR_BUILD_TEMPLATE_DIR = C:\\Users\\arcarons\\cored\\BuildTemplate # The directory where the apps created with Cored are put after a successful build. # For example the webapps directory of Tomcat. -WAR_DEPLOY_DIR = C:\\Users\\niemin75\\Desktop\\deploy +WAR_DEPLOY_DIR = C:\\Users\\arcarons\\cored\\deploy # The (Tomcat) server URL. # This is just for giving the user a link to the deployed applications. @@ -26,4 +26,4 @@ FACEBOOK_APP_ID = 191563344261896 # If LOG_DIR is set, a project log is written to that # dir into file named .log -LOG_DIR = C:\\Users\\Antti\\Desktop\\logs \ No newline at end of file +#LOG_DIR = C:\\Users\\Antti\\Desktop\\logs \ No newline at end of file diff --git a/cored/src/main/java/org/vaadin/cored/APIClient.java b/cored/src/main/java/org/vaadin/cored/APIClient.java new file mode 100644 index 0000000..4ce3b7f --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/APIClient.java @@ -0,0 +1,212 @@ +package org.vaadin.cored; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class APIClient { + + //return url to deployed app + public static String depployApp(String appName, String warName, + String warLocation,String date,String paasApiUrl) throws IOException { + String responseXML = ""; + //see: http://.../CF-api/rest/application.wadl + //almost working curl: curl -v -X POST -H 'Accept: application/xml' -H 'Content-Type: application/xml' -d message.xml http://jlautamaki.dy.fi:8080/CF-api/rest/environment + String envID = parseEnvID(makeRequest(paasApiUrl+"environment",getCreateEnvironmentString(appName,date))); + String appID = parseAppID(makeRequest(paasApiUrl+"app",getCreateApplicationString(appName,date))); + responseXML = makeRequest(paasApiUrl+"app/"+appID+"/version/create",getCreateAppVersionString(appName, warName,warLocation,date)); + responseXML = makeRequest(paasApiUrl+"app/"+appID+"/version/1/instance",getCreateApplicationVersionInstanceString(appName, date)); + responseXML = makeRequest(paasApiUrl+"environment/"+envID+"/action/deploy/app/"+appID+"/version/1/instance/1", ""); // deploys the application + String serviceurl = parseUrl(makeRequest(paasApiUrl+"app/"+appID+"/version/1/instance/1/action/start","")); //Starts the application + return serviceurl; + } + + private static String parseUrl(String response) { + String seekString = ""; + int startIndex = response.indexOf(seekString)+seekString.length(); + response = response.substring(startIndex); + seekString = ""; + int endIndex = response.indexOf(seekString); + String url = response.substring(0, endIndex); + return url; + } + + private static String getCreateApplicationVersionInstanceString(String appName, String date) { + String xml = ""+ + ""+ + ""+ + " "+ + " "+ + " "+ + " "+ + " "+ + ""; + return xml; + } + + + private static String getCreateAppVersionString(String appName, String warName, String warLocation, String date) { + String xml = "\n"+ + ""+ + "\n"+ + " \n"+ + " \n"+ + " \n"+ + " \n"+ + " \n"+ + " \n"+ + ""; + return xml; + } + + //should parse appID number from XML... could also be done with somekind of xmlparser :) + private static String parseAppID(String response) { + String seekString = "appId=\""; + int startIndex = response.indexOf(seekString)+seekString.length(); + response = response.substring(startIndex); + seekString = "\""; + int endIndex = response.indexOf(seekString)+seekString.length(); + String appId = response.substring(0, endIndex-1); + return appId; + } + + + private static String getCreateApplicationString(String appName, String date) { + String xml = ""+ + ""+ + " This manifest describes a simple display Servlet to deploy on CF."+ + " "+ + " "+ + "" ; + return xml; + } + + + //should parse envID number from XML... could also be done with somekind of xmlparser :) + private static String parseEnvID(String response) { + String seekString = "envId=\""; + int startIndex = response.indexOf(seekString)+seekString.length(); + response = response.substring(startIndex); + seekString = "\""; + int endIndex = response.indexOf(seekString)+seekString.length(); + String envId = response.substring(0, endIndex-1); + return envId; + } + + + private static String getCreateEnvironmentString(String appName, String date) { + String xml= ""+ + ""+ + ""+ + " "+ + " "+ + " "+ + " "+ + " "+ + " "+ + " "+ + " " + + ""; + return xml; + } + + private static String makeRequest(String urlString, String requestXML) throws IOException{ + + URL url = new URL(urlString); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.setInstanceFollowRedirects(false); + connection.setRequestMethod("POST"); + connection.setUseCaches (false); + + if (requestXML.length()>0){ + connection.setDoOutput(true); + connection.setRequestProperty("Content-Type", "application/xml"); + connection.setRequestProperty("charset", "utf-8"); + connection.setRequestProperty("Content-Length", "" + Integer.toString(requestXML.getBytes().length)); + DataOutputStream wr = new DataOutputStream(connection.getOutputStream ()); + wr.writeBytes(requestXML); + wr.flush(); + wr.close(); + } + + + //Get Response + InputStream is = connection.getInputStream(); + BufferedReader rd = new BufferedReader(new InputStreamReader(is)); + String line; + StringBuffer response = new StringBuffer(); + while((line = rd.readLine()) != null) { + response.append(line); + response.append("\r"); + } + rd.close(); + connection.disconnect(); + return response.toString(); + + + /* + // Get the method name + String method = request.getParameter("method"); + // Get the method path + String path = request.getParameter("path"); + // Get the request body + String body = request.getParameter("body"); + // Get the PaaS name (0 CloudFoundry, 1 Openshift, -1 not specfied) + paas = Integer.parseInt(request.getParameter("paas")); + + if (method == null || method.equals("") || path == null + || path.equals("")) { + request.setAttribute("status", 404); + request.setAttribute("output", + "Select an Action from the proposed list."); + request.getRequestDispatcher("/index.jsp").forward(request, + response); + } else if (paas==-1) { + request.setAttribute("status", 404); + request.setAttribute("output", + "Select a PaaS Solution from the proposed list."); + request.getRequestDispatcher("/index.jsp").forward(request, + response); + } + else { + + ClientConfig config = new DefaultClientConfig(); + Client client = Client.create(config); + client.setConnectTimeout(0); + WebResource service = client.resource(getBaseURI()); + + // Get the type of the methods (i.e. GET, POST,...) + String[] methodSplit = method.split("-"); + method = methodSplit[0]; + + ClientResponse cr = null; + String output = null; + if (method.equals("GET")) { + cr = service.path(path).type(MediaType.APPLICATION_XML) + .get(ClientResponse.class); + } else if (method.equals("POST")) { + cr = service.path(path).type(MediaType.APPLICATION_XML) + .entity(body).post(ClientResponse.class); + } else if (method.equals("DELETE")) { + cr = service.path(path).type(MediaType.APPLICATION_XML) + .delete(ClientResponse.class); + } + + request.setAttribute("status", cr.getStatus()); + if (cr.getStatus() == 200 || cr.getStatus() == 202)// if the + // response will be an xml descriptor, format it + request.setAttribute("output", + prettyFormat(cr.getEntity(String.class), 2)); + else + request.setAttribute("output", cr.getEntity(String.class)); + request.getRequestDispatcher("/index.jsp").forward(request, + response); + }*/ + + } +} diff --git a/cored/src/main/java/org/vaadin/cored/DjangoClearDatabase.java b/cored/src/main/java/org/vaadin/cored/DjangoClearDatabase.java new file mode 100644 index 0000000..133d92d --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/DjangoClearDatabase.java @@ -0,0 +1,73 @@ +package org.vaadin.cored; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.vaadin.cored.model.DjangoProject; + +import com.vaadin.terminal.UserError; +import com.vaadin.ui.Label; +import com.vaadin.ui.Window; + +@SuppressWarnings("serial") +public class DjangoClearDatabase extends Window { + + //TODO: delete this? + public class ReadStream implements Runnable { + String name; + InputStream is; + Thread thread; + public ReadStream(String name, InputStream is) { + this.name = name; + this.is = is; + } + public void start () { + thread = new Thread (this); + thread.start (); + } + public void run () { + try { + InputStreamReader isr = new InputStreamReader (is); + BufferedReader br = new BufferedReader (isr); + while (true) { + String s = br.readLine (); + if (s == null) break; + System.out.println ("[" + name + "] " + s); + Label l = new Label(s); + addComponent(l); + l.setComponentError(new UserError(s)); + } + + is.close (); + } catch (Exception ex) { + System.out.println ("Problem reading stream " + name + "... :" + ex); + ex.printStackTrace (); + } + } + } + + public DjangoClearDatabase(DjangoProject project) { + + try { + //project.writeToDisk(); + + String cmds = "cmd /c python manage.py cleanup"; + System.out.println("projectDir=="+project.getProjectDir()+"getName=="+project.getName()); + File djangoDir = new File(project.getProjectDir()+"\\"+project.getName()); + System.out.println("djangoDir=="+djangoDir); + Runtime rt = Runtime.getRuntime(); + Process proc = rt.exec(cmds,null,djangoDir); + ReadStream s1 = new ReadStream("stdin", proc.getInputStream ()); + ReadStream s2 = new ReadStream("stderr", proc.getErrorStream ()); + s1.start (); + s2.start (); + //proc.waitFor(); + } catch (Exception e) { + e.printStackTrace(); + } + this.close(); + //TODO: close the window? or change it so is not a window at all (button) + } +} diff --git a/cored/src/main/java/org/vaadin/cored/DjangoNewAppWindow.java b/cored/src/main/java/org/vaadin/cored/DjangoNewAppWindow.java new file mode 100644 index 0000000..38b9726 --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/DjangoNewAppWindow.java @@ -0,0 +1,116 @@ +package org.vaadin.cored; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.vaadin.cored.model.DjangoProject; + +import com.vaadin.data.Property; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; +import com.vaadin.ui.Button.ClickListener; + +@SuppressWarnings("serial") +public class DjangoNewAppWindow extends Window implements +ClickListener { + + private final DjangoProject project; + private TextField appName; + private File djangoDir; + private Process proc = null; + private Runtime rt; + private String value; + private Button startappButton; + + public DjangoNewAppWindow(DjangoProject project) { + super("Create new app"); + this.project = project; + getContent().setSizeFull(); + setWidth("300px"); + setHeight("200px"); + draw(); + } + + + private void draw() { + + getContent().removeAllComponents(); + VerticalLayout ve = new VerticalLayout(); + ve.setSizeFull(); + addComponent(ve); + + appName = new TextField("App name:"); + appName.setWidth("150"); + appName.focus(); + appName.addListener(new Property.ValueChangeListener() { + public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) { + value = (String) appName.getValue(); + } + + }); + //TODO: check the previous state in case the server is running and the window was closed + //portField.setEnabled(portField.isEnabled()); + addComponent(appName); + + startappButton = new Button ("Startapp"); + startappButton.addListener(this); + addComponent(startappButton); + + } + //TODO: delete this? + public class ReadStream implements Runnable { + String name; + InputStream is; + Thread thread; + public ReadStream(String name, InputStream is) { + this.name = name; + this.is = is; + } + public void start () { + thread = new Thread (this); + thread.start (); + } + public void run () { + try { + InputStreamReader isr = new InputStreamReader (is); + BufferedReader br = new BufferedReader (isr); + while (true) { + String s = br.readLine (); + if (s == null) break; + System.out.println ("[" + name + "] " + s); + } + is.close (); + } catch (Exception ex) { + System.out.println ("Problem reading stream " + name + "... :" + ex); + ex.printStackTrace (); + } + } + } + + public void buttonClick(ClickEvent event) { + try { + String cmds = "cmd /c python manage.py startapp "+appName.getValue(); + djangoDir = new File(project.getProjectDir()+"\\"+project.getName()); + rt = Runtime.getRuntime(); + proc = rt.exec(cmds,null,djangoDir); + ReadStream s1 = new ReadStream("stdin", proc.getInputStream ()); + ReadStream s2 = new ReadStream("stderr", proc.getErrorStream ()); + s1.start (); + s2.start (); + proc.waitFor(); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("obert proc="+proc); + appName.setEnabled(false); + this.close(); + project.readFromDisk(); + } + + +} diff --git a/cored/src/main/java/org/vaadin/cored/DjangoPortWindow.java b/cored/src/main/java/org/vaadin/cored/DjangoPortWindow.java new file mode 100644 index 0000000..5665a1e --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/DjangoPortWindow.java @@ -0,0 +1,161 @@ +package org.vaadin.cored; + + + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Field; + +import org.vaadin.cored.DjangoNewAppWindow.ReadStream; +import org.vaadin.cored.model.DjangoProject; + +import com.vaadin.data.Property; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; +import com.vaadin.ui.Button.ClickListener; + +@SuppressWarnings("serial") +public class DjangoPortWindow extends Window implements +ClickListener { + + /** + * + */ + + private final DjangoProject project; + private Button runButton; + private Button stopButton; + private TextField portField; + private String value; + private File djangoDir; + private Process proc = null; + private Process procc = null; + private Runtime rt,rtt; + + public DjangoPortWindow(DjangoProject project) { + super("Port to run " + project.getName()); + this.project = project; + getContent().setSizeFull(); + setWidth("300px"); + setHeight("200px"); + draw(); + } + + private void draw() { + + getContent().removeAllComponents(); + VerticalLayout ve = new VerticalLayout(); + ve.setSizeFull(); + addComponent(ve); + + portField = new TextField("Port number:"); + portField.setWidth("50"); + portField.focus(); + portField.addListener(new Property.ValueChangeListener() { + public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) { + value = (String) portField.getValue(); + portField.setValue(value); + } + }); + //portField.setEnabled(portField.isEnabled()); + addComponent(portField); + + runButton = new Button ("Runserver"); + runButton.addListener(this); + addComponent(runButton); + stopButton = new Button ("Stop"); + stopButton.addListener(this); + + } + + //TODO: delete this? + public class ReadStream implements Runnable { + String name; + InputStream is; + Thread thread; + public ReadStream(String name, InputStream is) { + this.name = name; + this.is = is; + } + public void start () { + thread = new Thread (this); + thread.start (); + } + public void run () { + try { + InputStreamReader isr = new InputStreamReader (is); + BufferedReader br = new BufferedReader (isr); + while (true) { + String s = br.readLine (); + if (s == null) break; + System.out.println ("[" + name + "] " + s); + } + is.close (); + } catch (Exception ex) { + System.out.println ("Problem reading stream " + name + "... :" + ex); + ex.printStackTrace (); + } + } + } + + public void buttonClick(ClickEvent event) { + if (event.getButton() == runButton) + { + try { + String cmds = "cmd /c python manage.py runserver 0.0.0.0:"+portField.getValue(); + djangoDir = new File(project.getProjectDir()+"\\"+project.getName()); + rt = Runtime.getRuntime(); + proc = rt.exec(cmds,null,djangoDir); + //proc.waitFor(); + + portField.setEnabled(false); + removeComponent(runButton); + addComponent(stopButton); + //test to get process PID + String cmdPid = "cmd /c wmic process get commandline,processid | find \"manage.py runserver 0.0.0.0:"+portField.getValue()+"\""; + rtt = Runtime.getRuntime(); + procc = rtt.exec(cmdPid,null,djangoDir); + System.out.println("-------->"); + ReadStream s1 = new ReadStream("stdin", procc.getInputStream ()); + ReadStream s2 = new ReadStream("stderr", procc.getErrorStream ()); + s1.start (); + s2.start (); + //proc.waitFor(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + if (event.getButton() == stopButton) + { + if(rt != null) + { + try { + //wmic Path win32_process Where "CommandLine Like '%-jar selenium-server.jar%'" Call Terminate + //TODO: try not to kill all of them + String cmds = "cmd /c taskkill /im python.exe /f"; + //rt = Runtime.getRuntime(); + rt.exec(cmds,null,djangoDir); + proc.waitFor(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + proc.destroy(); + portField.setEnabled(true); + removeComponent(stopButton); + addComponent(runButton); + } + } + } + +} diff --git a/cored/src/main/java/org/vaadin/cored/DjangoSQLapp.java b/cored/src/main/java/org/vaadin/cored/DjangoSQLapp.java new file mode 100644 index 0000000..0caf5c8 --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/DjangoSQLapp.java @@ -0,0 +1,113 @@ +package org.vaadin.cored; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.vaadin.cored.DjangoNewAppWindow.ReadStream; +import org.vaadin.cored.model.DjangoProject; + +import com.vaadin.data.Property; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +public class DjangoSQLapp extends Window implements ClickListener { + + + + private final DjangoProject project; + private TextField appName; + private File djangoDir; + private Process proc = null; + private Runtime rt; + private String value; + private Button sqlAppButton; + + public DjangoSQLapp(DjangoProject project) { + super("Name of the app"); + this.project = project; + getContent().setSizeFull(); + setWidth("300px"); + setHeight("200px"); + draw(); + } + + private void draw() { + + getContent().removeAllComponents(); + VerticalLayout ve = new VerticalLayout(); + ve.setSizeFull(); + addComponent(ve); + + appName = new TextField("App name:"); + appName.setWidth("50"); + appName.focus(); + appName.addListener(new Property.ValueChangeListener() { + public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) { + value = (String) appName.getValue(); + appName.setValue(value); + } + }); + //portField.setEnabled(portField.isEnabled()); + addComponent(appName); + + sqlAppButton = new Button ("Run sql"); + sqlAppButton.addListener(this); + addComponent(sqlAppButton); + } + + //TODO: delete this? + public class ReadStream implements Runnable { + String name; + InputStream is; + Thread thread; + public ReadStream(String name, InputStream is) { + this.name = name; + this.is = is; + } + public void start () { + thread = new Thread (this); + thread.start (); + } + public void run () { + try { + InputStreamReader isr = new InputStreamReader (is); + BufferedReader br = new BufferedReader (isr); + while (true) { + String s = br.readLine (); + if (s == null) break; + System.out.println ("[" + name + "] " + s); + } + is.close (); + } catch (Exception ex) { + System.out.println ("Problem reading stream " + name + "... :" + ex); + ex.printStackTrace (); + } + } + } + + public void buttonClick(ClickEvent event) { + try { + project.writeToDisk(); + + String cmds = "cmd /c python manage.py sql "+appName.getValue(); + djangoDir = new File(project.getProjectDir()+"\\"+project.getName()); + rt = Runtime.getRuntime(); + proc = rt.exec(cmds,null,djangoDir); + ReadStream s1 = new ReadStream("stdin", proc.getInputStream ()); + ReadStream s2 = new ReadStream("stderr", proc.getErrorStream ()); + s1.start (); + s2.start (); + proc.waitFor(); + } catch (Exception e) { + e.printStackTrace(); + } + this.close(); + } + +} diff --git a/cored/src/main/java/org/vaadin/cored/DjangoSyncDB.java b/cored/src/main/java/org/vaadin/cored/DjangoSyncDB.java new file mode 100644 index 0000000..9276734 --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/DjangoSyncDB.java @@ -0,0 +1,76 @@ +package org.vaadin.cored; + +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import org.vaadin.cored.model.DjangoProject; + +import com.vaadin.terminal.UserError; +import com.vaadin.ui.Label; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.TextField; +import com.vaadin.ui.Window; + +@SuppressWarnings("serial") +public class DjangoSyncDB extends Window { + + //TODO: delete this? + public class ReadStream implements Runnable { + String name; + InputStream is; + Thread thread; + public ReadStream(String name, InputStream is) { + this.name = name; + this.is = is; + } + public void start () { + thread = new Thread (this); + thread.start (); + } + public void run () { + try { + InputStreamReader isr = new InputStreamReader (is); + BufferedReader br = new BufferedReader (isr); + while (true) { + String s = br.readLine (); + if (s == null) break; + System.out.println ("[" + name + "] " + s); + Label l = new Label(s); + addComponent(l); + l.setComponentError(new UserError(s)); + + } + is.close (); + } catch (Exception ex) { + System.out.println ("Problem reading stream " + name + "... :" + ex); + ex.printStackTrace (); + } + } + } + + public DjangoSyncDB(DjangoProject project) { + + try { + project.writeToDisk(); + + String cmds = "cmd /c python manage.py syncdb"; + System.out.println("projectDir=="+project.getProjectDir()+"getName=="+project.getName()); + File djangoDir = new File(project.getProjectDir()+"\\"+project.getName()); + System.out.println("djangoDir=="+djangoDir); + Runtime rt = Runtime.getRuntime(); + Process proc = rt.exec(cmds,null,djangoDir); + ReadStream s1 = new ReadStream("stdin", proc.getInputStream ()); + ReadStream s2 = new ReadStream("stderr", proc.getErrorStream ()); + s1.start (); + s2.start (); + + //proc.waitFor(); + } catch (Exception e) { + e.printStackTrace(); + } + this.close(); + //TODO: close the window? or change it so is not a window at all (button) + } + +} diff --git a/cored/src/main/java/org/vaadin/cored/EditorView.java b/cored/src/main/java/org/vaadin/cored/EditorView.java index d0b0d58..f6bbb4f 100644 --- a/cored/src/main/java/org/vaadin/cored/EditorView.java +++ b/cored/src/main/java/org/vaadin/cored/EditorView.java @@ -20,6 +20,7 @@ import org.vaadin.chatbox.SharedChat; import org.vaadin.chatbox.gwt.shared.ChatLine; import org.vaadin.cored.MarkerComponent.MarkerComponentListener; +import org.vaadin.cored.model.CoredDoc; import org.vaadin.cored.model.Project; import org.vaadin.cored.model.ProjectFile; import org.vaadin.cored.model.Team; @@ -44,7 +45,7 @@ public class EditorView extends CustomComponent implements SelectionChangeListen private final VerticalLayout layout = new VerticalLayout(); private final SuggestibleCollabAceEditor editor; - private final Shared doc; + private final CoredDoc cdoc; private final ProjectFile file; private final User user; private final Project project; @@ -85,7 +86,7 @@ public EditorView(ProjectFile file, Project project, User user, boolean inIde, i layout.setExpandRatio(ho, 1); ho.setSizeFull(); - doc = project.getDoc(file); + cdoc = project.getDoc(file); @@ -94,7 +95,8 @@ public EditorView(ProjectFile file, Project project, User user, boolean inIde, i editor.setEnabled(user != null); editor.setUser(user.getUserId(), user.getStyle()); - final int pos = org.vaadin.aceeditor.gwt.shared.Util.cursorPosFromLineCol(doc.getValue().getText(), line, 0, 1); + final int pos = org.vaadin.aceeditor.gwt.shared.Util.cursorPosFromLineCol( + cdoc.getShared().getValue().getText(), line, 0, 1); editor.scrollToPosition(pos); ho.addComponent(editor); ho.setExpandRatio(editor, 1); @@ -149,7 +151,7 @@ public SuggestibleCollabAceEditor getEditor() { } private SuggestibleCollabAceEditor createEditor(ProjectFile file, Project project) { - SuggestibleCollabAceEditor ed = EditorUtil.createEditorFor(doc, file); + SuggestibleCollabAceEditor ed = EditorUtil.createEditorFor(cdoc.getShared(), file); if (file.getName().endsWith(".java") && project instanceof VaadinProject) { InMemoryCompiler compiler = ((VaadinProject)project).getCompiler(); String className = ((VaadinProject)project).getPackageName()+"."+file.getName().substring(0, file.getName().length()-5); @@ -162,7 +164,7 @@ public void selectionChanged(int start, int end) { selMin = Math.min(start, end); selMax = Math.max(start, end); DocDiff diff = user.cursorDiff(selMin, selMax, editor.getShadow().getText()); - doc.applyDiff(diff, editor.getCollaboratorId()); + cdoc.getShared().applyDiff(diff, editor.getCollaboratorId()); checkMarkers(); } @@ -303,9 +305,9 @@ private void showMarkerPopup() { private void showMarkerPopup(int yCoord) { final String markerId = activeMarker; - String firstLine = project.getMarkerChat(file, markerId).getValue().getFrozenLines().get(0).getText(); + SharedChat chat = project.getDoc(file).getMarkerChat(markerId); + String firstLine = chat.getValue().getFrozenLines().get(0).getText(); Marker m = latestMarkers.get(markerId); - SharedChat chat = project.getMarkerChat(file, markerId); MarkerComponent mc = new MarkerComponent(m, user, chat); mc.addListener(new MarkerComponentListener() { public void removeMarker() { @@ -322,7 +324,7 @@ public void removeMarker() { } private void removeMarkerById(String markerId) { - doc.applyDiff(DocDiff.removeMarker(markerId), editor.getCollaboratorId()); + cdoc.getShared().applyDiff(DocDiff.removeMarker(markerId), editor.getCollaboratorId()); } private void showAddMarkerPopup(boolean notingEnabled, boolean lockingEnabled) { @@ -377,7 +379,7 @@ public void addNote(String note) { private void addMarker(Marker m, ChatLine chatLine) { String markerId = editor.newItemId(); - Doc v = doc.getValue(); + Doc v = cdoc.getShared().getValue(); // Adding the marker to the selection marker position, a bit of a hack. Marker sema = v.getMarkers().get(user.getSelectionMarkerId()); if (sema==null) { @@ -390,11 +392,11 @@ private void addMarker(Marker m, ChatLine chatLine) { m = m.withNewPos(start, end); DocDiff d = DocDiff.addMarker(markerId, m, text); - doc.applyDiff(d, editor.getCollaboratorId()); + cdoc.getShared().applyDiff(d, editor.getCollaboratorId()); if (chatLine!=null) { List lines = Collections.singletonList(chatLine); - project.getMarkerChatCreateIfNotExist(file, markerId, lines); + project.getDoc(file).getMarkerChatCreateIfNotExist(markerId, lines); } latestMarkers.put(markerId, m); diff --git a/cored/src/main/java/org/vaadin/cored/IDE.java b/cored/src/main/java/org/vaadin/cored/IDE.java index f2d4981..b48e9e7 100644 --- a/cored/src/main/java/org/vaadin/cored/IDE.java +++ b/cored/src/main/java/org/vaadin/cored/IDE.java @@ -5,6 +5,7 @@ import org.vaadin.chatbox.ChatBox; import org.vaadin.chatbox.SharedChat; import org.vaadin.cored.ProjectPanel.FileSelectListener; +import org.vaadin.cored.model.CoredDoc; import org.vaadin.cored.model.Project; import org.vaadin.cored.model.ProjectFile; import org.vaadin.cored.model.Team.TeamListener; @@ -100,7 +101,7 @@ private void editFile(ProjectFile file) { if (file == null) { editorLayout.removeAllComponents(); } else if (EditorUtil.isEditableWithEditor(file)) { - Shared doc = project.getDoc(file); + CoredDoc doc = project.getDoc(file); if (doc != null) { editDoc(doc, file); } else { @@ -113,7 +114,7 @@ private void editFile(ProjectFile file) { } } - private void editDoc(Shared doc, ProjectFile file) { + private void editDoc(CoredDoc cd, ProjectFile file) { editorView = new EditorView(file, project, user, true, 0); editorView.setSizeFull(); diff --git a/cored/src/main/java/org/vaadin/cored/MarkerComponent.java b/cored/src/main/java/org/vaadin/cored/MarkerComponent.java index ce81f62..0da1fd5 100644 --- a/cored/src/main/java/org/vaadin/cored/MarkerComponent.java +++ b/cored/src/main/java/org/vaadin/cored/MarkerComponent.java @@ -36,7 +36,6 @@ public MarkerComponent(Marker marker, User user, SharedChat chat) { this.marker = marker; this.user = user; this.chat = chat; - System.out.println("Marker component for " + marker); initThis(); setSizeFull(); } diff --git a/cored/src/main/java/org/vaadin/cored/ProjectPanel.java b/cored/src/main/java/org/vaadin/cored/ProjectPanel.java index 3e0b049..77c9929 100644 --- a/cored/src/main/java/org/vaadin/cored/ProjectPanel.java +++ b/cored/src/main/java/org/vaadin/cored/ProjectPanel.java @@ -1,7 +1,5 @@ package org.vaadin.cored; -import java.util.Collection; -import java.util.HashMap; import java.util.LinkedList; import java.util.Set; @@ -42,8 +40,8 @@ public class ProjectPanel extends Panel implements DocListener, private Object selectedItemId; - private HashMap errors = new HashMap(); - private HashMap> fileUsers = new HashMap>(); +// private HashMap errors = new HashMap(); +// private HashMap> fileUsers = new HashMap>(); public ProjectPanel(final Project project) { super("Files"); @@ -222,53 +220,57 @@ public void valueChange(ValueChangeEvent event) { } public void docValueChanged(ProjectFile pf, Doc newValue) { - Boolean prev; - boolean hasErrors = newValue.hasErrors(); - synchronized (errors) { - prev = errors.put(pf, hasErrors); - } - if (prev == null || prev != hasErrors) { -// synchronized (getApplication()) { - setIconOf(pf, hasErrors); -// } - } + refresh(); +// Boolean prev; +// boolean hasErrors = newValue.hasErrors(); +// synchronized (errors) { +// prev = errors.put(pf, hasErrors); +// } +// if (prev == null || prev != hasErrors) { +//// synchronized (getApplication()) { +// setIconOf(pf, hasErrors); +//// } +// } +// +// project.fillTree(tree) } - private void setIconOf(ProjectFile pf, Boolean hasErrors) { - if (hasErrors) { - tree.setItemIcon(pf, Icons.CROSS_CIRCLE); - } - else { - tree.setItemIcon(pf, Icons.TICK_SMALL); - } - } +// private void setIconOf(ProjectFile pf, Boolean hasErrors) { +// if (hasErrors) { +// tree.setItemIcon(pf, Icons.CROSS_CIRCLE); +// } +// else { +// tree.setItemIcon(pf, Icons.TICK_SMALL); +// } +// } public void userFilesChanged(Set users, Set files) { - for (ProjectFile f : files) { - userFileChanged(f); - } + refresh(); +// for (ProjectFile f : files) { +// userFileChanged(f); +// } } - private void userFileChanged(ProjectFile f) { - Collection uf = project.getTeam().getUsersByFile(f); - synchronized (fileUsers) { - fileUsers.put(f, uf); - } - - int n = uf.size(); - if (n==0) { -// synchronized (getApplication()) { - tree.setItemCaption(f, f.getName()); -// } - } - else { -// synchronized (getApplication()) { - tree.setItemCaption(f, f.getName()+" ("+n+")"); -// } - } - - - } +// private void userFileChanged(ProjectFile f) { +// Collection uf = project.getTeam().getUsersByFile(f); +// synchronized (fileUsers) { +// fileUsers.put(f, uf); +// } +// +// int n = uf.size(); +// if (n==0) { +//// synchronized (getApplication()) { +// tree.setItemCaption(f, f.getName()); +//// } +// } +// else { +//// synchronized (getApplication()) { +// tree.setItemCaption(f, f.getName()+" ("+n+")"); +//// } +// } +// +// +// } } diff --git a/cored/src/main/java/org/vaadin/cored/VaadinBuildComponent.java b/cored/src/main/java/org/vaadin/cored/VaadinBuildComponent.java index 1c75ca7..530c2f0 100644 --- a/cored/src/main/java/org/vaadin/cored/VaadinBuildComponent.java +++ b/cored/src/main/java/org/vaadin/cored/VaadinBuildComponent.java @@ -114,10 +114,29 @@ private void doTheBuild() throws IOException { if (this.deployType.equals(DeployType.war)){ warDeployName = null; - warDeployName = antBuildWar(); + warDeployName = antBuildWar(); }else if (this.deployType.equals(DeployType.osgi)){ + //does not work yet :( antBuildOsgi(); } + + //Experimental implementation for using the *-PaaS API implemented by + //Mohamed Sellami, Telecom SudParis. + //Sami Yangui, Telecom SudParis. + //Mohamed Mohamed, Telecom SudParis. + //Samir Tata, Telecom SudParis. + //for deploying the applications + boolean deployToCloudFoundry = false; + if (deployToCloudFoundry){ + //deployDir = polku warriin + //warDeployName + ".war" = warrin nimi + String appName ="JanneTestaaApplication"; + String warName ="jannetestaa2.war"; + String warLocation="/home/jlautamaki/git"; + String paasApiUrl = "http://jlautamaki.dy.fi:8080/CF-api/rest/"; + String date="2012-10-10"; + APIClient.depployApp(appName, warName, warLocation,date,paasApiUrl); + } } } diff --git a/cored/src/main/java/org/vaadin/cored/VaadinNewFileWindow.java b/cored/src/main/java/org/vaadin/cored/VaadinNewFileWindow.java index 2beb84a..a7e0e7c 100644 --- a/cored/src/main/java/org/vaadin/cored/VaadinNewFileWindow.java +++ b/cored/src/main/java/org/vaadin/cored/VaadinNewFileWindow.java @@ -1,5 +1,6 @@ package org.vaadin.cored; +import org.vaadin.aceeditor.collab.gwt.shared.Doc; import org.vaadin.cored.model.VaadinProject; import org.vaadin.cored.model.VaadinProject.JavaUtils; @@ -61,7 +62,7 @@ public void buttonClick(ClickEvent event) { } String content = VaadinProject.generateContent(project.getPackageName(), name, base); - project.createDoc(project.getFileOfClass(name), content); + project.addDoc(project.getFileOfClass(name), new Doc(content)); VaadinNewFileWindow.this.close(); } diff --git a/cored/src/main/java/org/vaadin/cored/lobby/CreateProjectPanel.java b/cored/src/main/java/org/vaadin/cored/lobby/CreateProjectPanel.java index 6df6852..403cd8b 100644 --- a/cored/src/main/java/org/vaadin/cored/lobby/CreateProjectPanel.java +++ b/cored/src/main/java/org/vaadin/cored/lobby/CreateProjectPanel.java @@ -22,7 +22,7 @@ public class CreateProjectPanel extends Panel { private OptionGroup projectTypeGroup = new OptionGroup("Project type:", - Arrays.asList(new String[] {"Vaadin", "Python", "Generic"})); + Arrays.asList(new String[] {"Vaadin", "Python", "Generic", "Django"})); private static final ThemeResource ICON = new ThemeResource("icons/box--plus.png"); @@ -82,6 +82,9 @@ public void buttonClick(ClickEvent event) { else if ("Python".equals(typeStr)) { type = ProjectType.python; } + else if ("Django".equals(typeStr)) { + type = ProjectType.django; + } else { type = ProjectType.generic; } diff --git a/cored/src/main/java/org/vaadin/cored/model/CoredDoc.java b/cored/src/main/java/org/vaadin/cored/model/CoredDoc.java new file mode 100644 index 0000000..c5ff9ab --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/model/CoredDoc.java @@ -0,0 +1,135 @@ +package org.vaadin.cored.model; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; + +import org.apache.commons.io.FileUtils; +import org.vaadin.aceeditor.collab.DocDiff; +import org.vaadin.aceeditor.collab.gwt.shared.Doc; +import org.vaadin.aceeditor.gwt.shared.LockMarkerData; +import org.vaadin.aceeditor.gwt.shared.Marker; +import org.vaadin.chatbox.SharedChat; +import org.vaadin.chatbox.gwt.shared.Chat; +import org.vaadin.chatbox.gwt.shared.ChatDiff; +import org.vaadin.chatbox.gwt.shared.ChatLine; +import org.vaadin.cored.ProjectLog; +import org.vaadin.diffsync.Shared; + + +/** + * A document containing the Shared Doc as well as some related things such as marker chats. + * + * Can be subclassed to create for example VaadinCoredDoc. + * + * + */ +public class CoredDoc { + + private final File projectRoot; + private final ProjectFile file; + private final File location; + private final SharedDoc shared; + + private final ProjectLog log; + + private HashMap markerChats = + new HashMap(); + + public static Doc fromDisk(File projectDir, ProjectFile file) throws IOException { + File loc = new File(projectDir, file.getPath()); + return new Doc(FileUtils.readFileToString(loc)); + } + + public CoredDoc(File root, ProjectFile file, SharedDoc shared, ProjectLog log) { + this.projectRoot = root; + this.file = file; + this.location = new File(projectRoot, file.getPath()); + this.shared = shared; + this.log = log; + } + + public CoredDoc(File root, ProjectFile file, Doc doc, ProjectLog log) { + this(root, file, new SharedDoc(doc), log); + } + + public ProjectFile getProjectFile() { + return file; + } + + public SharedDoc getShared() { + return shared; + } + + public void setValue(Doc doc) { + getShared().setValue(doc, Shared.NO_COLLABORATOR_ID); + } + + public void writeToDisk() throws IOException { + FileUtils.write(location, shared.getValue().getText()); + } + + public boolean writoDiskIfErrorFree() throws IOException { + Doc doc = getShared().getValue(); + if (doc.hasErrors()) { + return false; + } + writeToDisk(); + return true; + } + + public SharedChat getMarkerChat(String markerId) { + return markerChats.get(markerId); + } + + public SharedChat getMarkerChatCreateIfNotExist(String markerId, List initial) { + SharedChat chat = markerChats.get(markerId); + if (chat == null) { + chat = new SharedChat(new Chat(initial)); + if (log!=null) { + for (ChatLine li : initial) { + log.logMarkerChat(markerId, li.getUserId(), li.getText()); + } + chat.addTask(new ChatLogTask(log, markerId)); + } + markerChats.put(markerId, chat); + } + return chat; + } + + synchronized public Shared removeMarkerChat(String markerId) { + return markerChats.remove(markerId); + } + + + + public void readFromDisk() throws IOException { + + String content = FileUtils.readFileToString(location); + getShared().setValue(new Doc(content), Shared.NO_COLLABORATOR_ID); + + } + + public void deleteFromDisk() { + location.delete(); + } + + public void removeLocksOf(User user) { + Doc doc = getShared().getValue(); + LinkedList locksOf = new LinkedList(); + for (Entry e : doc.getMarkers().entrySet()) { + Marker m = e.getValue(); + if (m.getType()==Marker.Type.LOCK && + user.getUserId().equals(((LockMarkerData)m.getData()).getLockerId())) { + locksOf.add(e.getKey()); + } + } + if (!locksOf.isEmpty()) { + getShared().applyDiff(DocDiff.removeMarkers(locksOf)); + } + } + +} diff --git a/cored/src/main/java/org/vaadin/cored/model/DjangoProject.java b/cored/src/main/java/org/vaadin/cored/model/DjangoProject.java new file mode 100644 index 0000000..c5c5da8 --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/model/DjangoProject.java @@ -0,0 +1,224 @@ +package org.vaadin.cored.model; + +import java.util.regex.Pattern; + +import java.io.*; + +import org.vaadin.aceeditor.collab.gwt.shared.Doc; +import org.vaadin.cored.DjangoClearDatabase; +import org.vaadin.cored.DjangoNewAppWindow; +import org.vaadin.cored.DjangoPortWindow; +import org.vaadin.cored.DjangoSQLapp; +import org.vaadin.cored.DjangoSyncDB; + + +import com.vaadin.data.validator.AbstractValidator; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.MenuBar.Command; +import com.vaadin.ui.MenuBar.MenuItem; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.MenuBar; +import com.vaadin.ui.TextField; +import com.vaadin.ui.Tree; +import com.vaadin.ui.Window; + +public class DjangoProject extends Project { + + + public static class DjangoUtils { + + private static final Pattern validClass = Pattern.compile("^[A-Za-z1-9_]+$"); + + public static boolean isValidDjangoClass(String s) { + return validClass.matcher(s).matches(); + } + + @SuppressWarnings("serial") + public static class DjangoClassNameValidator extends AbstractValidator { + + public DjangoClassNameValidator() { + super("Class names should contain letters, numbers, _"); + } + + public boolean isValid(Object value) { + return value instanceof String && isValidDjangoClass((String) value); + } + } + } + + protected DjangoProject(String name) { + super(name,ProjectType.django); + } + //TODO: delete this? + public class ReadStream implements Runnable { + String name; + InputStream is; + Thread thread; + public ReadStream(String name, InputStream is) { + this.name = name; + this.is = is; + } + public void start () { + thread = new Thread (this); + thread.start (); + } + public void run () { + try { + InputStreamReader isr = new InputStreamReader (is); + BufferedReader br = new BufferedReader (isr); + while (true) { + String s = br.readLine (); + if (s == null) break; + + System.out.println ("[" + name + "] " + s); + } + is.close (); + } catch (Exception ex) { + System.out.println ("Problem reading stream " + name + "... :" + ex); + ex.printStackTrace (); + } + } + } + + @Override + protected void projectInitialized(boolean createSkeleton) { + if (createSkeleton) { + try { + String cmds = "cmd /c django-admin.py startproject "+this.getName(); + Runtime rt = Runtime.getRuntime(); + Process proc = rt.exec(cmds,null,this.getProjectDir()); + ReadStream s1 = new ReadStream("stdin", proc.getInputStream ()); + ReadStream s2 = new ReadStream("stderr", proc.getErrorStream ()); + s1.start (); + s2.start (); + proc.waitFor(); + readFromDisk(); + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("project "+ this.getName() +" created"); + } + } + + + @Override + public void fillTree(Tree tree) { + String folderParentName; + for (ProjectFile pf : super.getProjectFiles()) { + if(pf.getParent().indexOf("\\")>0) //it's a sub folder + { + tree.addItem(pf.getParent()); + folderParentName = pf.getParent().substring(0, pf.getParent().indexOf("\\")); + tree.setParent(pf.getParent(),folderParentName); + tree.setItemCaption(pf.getParent(),pf.getParent().substring((pf.getParent().indexOf("\\")+1),pf.getParent().length())); + } + else if(pf.getParent().indexOf(".")<0) //it's a root folder + { + tree.addItem(pf.getParent()); + tree.setItemCaption(pf.getParent(), pf.getParent()); + tree.expandItem(pf.getParent()); //expand the root folder + } + } + for (ProjectFile pf : super.getProjectFiles()) { + if( pf.getName().endsWith(".py")) //filter file type + { + tree.addItem(pf); + tree.setParent(pf,pf.getParent()); + tree.setItemCaption(pf, pf.getName()); + tree.setChildrenAllowed(pf, false); + } + } + } + + + @SuppressWarnings("serial") + private class NewPyFileWindow extends Window { + TextField nameField = new TextField(); + private NewPyFileWindow(final DjangoProject p) { + super("New Django File"); + HorizontalLayout h = new HorizontalLayout(); + h.addComponent(new Label("Django file: ")); + h.addComponent(nameField); + h.addComponent(new Label(".py")); + Button b = new Button("Add"); + addComponent(h); + addComponent(b); + b.addListener(new ClickListener() { + public void buttonClick(ClickEvent event) { + String n = (String)nameField.getValue(); + if (!DjangoUtils.isValidDjangoClass(n)) { + return; + } + p.addDoc(new ProjectFile(n+".py"), new Doc("# "+n+".py\n")); + NewPyFileWindow.this.close(); + } + }); + } + } + + @SuppressWarnings("serial") + @Override + public void addMenuItem(final MenuBar menuBar) { + MenuItem mi = menuBar.addItem("Django", null, null); + final DjangoPortWindow runserverWindow = new DjangoPortWindow(DjangoProject.this); + + mi.addItem("Runserver", new Command() { + public void menuSelected(MenuItem selectedItem) { + //menuBar.getWindow().addWindow(new DjangoPortWindow(DjangoProject.this)); + menuBar.getWindow().addWindow(runserverWindow); + } + }); + mi.addItem("New app", new Command() { + public void menuSelected(MenuItem selectedItem) { + menuBar.getWindow().addWindow(new DjangoNewAppWindow(DjangoProject.this)); + } + }); + mi.addItem("syncdb", new Command() { + //this is the only one that saves the project changes + //TODO: save button? + public void menuSelected(MenuItem selectedItem) { + menuBar.getWindow().addWindow(new DjangoSyncDB(DjangoProject.this)); + + /*try { + //project.writeToDisk(); + + String cmds = "cmd /c python manage.py cleanup"; + System.out.println("projectDir=="+getProjectDir()+"getName=="+getName()); + File djangoDir = new File(getProjectDir()+"\\"+getName()); + System.out.println("djangoDir=="+djangoDir); + Runtime rt = Runtime.getRuntime(); + Process proc = rt.exec(cmds,null,djangoDir); + ReadStream s1 = new ReadStream("stdin", proc.getInputStream ()); + ReadStream s2 = new ReadStream("stderr", proc.getErrorStream ()); + s1.start (); + s2.start (); + //proc.waitFor(); + } catch (Exception e) { + e.printStackTrace(); + }*/ + + } + }); + mi.addItem("Run sql app", new Command() { + public void menuSelected(MenuItem selectedItem) { + menuBar.getWindow().addWindow(new DjangoSQLapp(DjangoProject.this)); + } + }); + mi.addItem("Clear Database", new Command() { + public void menuSelected(MenuItem selectedItem) { + menuBar.getWindow().addWindow(new DjangoClearDatabase(DjangoProject.this)); + } + }); + } + + + @Override + public Window createNewFileWindow() { + return new NewPyFileWindow(this); + } + + +} diff --git a/cored/src/main/java/org/vaadin/cored/model/GenericProject.java b/cored/src/main/java/org/vaadin/cored/model/GenericProject.java index 6f95503..710379f 100644 --- a/cored/src/main/java/org/vaadin/cored/model/GenericProject.java +++ b/cored/src/main/java/org/vaadin/cored/model/GenericProject.java @@ -1,6 +1,14 @@ package org.vaadin.cored.model; +import org.vaadin.aceeditor.collab.gwt.shared.Doc; + +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.TextField; import com.vaadin.ui.Tree; import com.vaadin.ui.Window; @@ -21,7 +29,37 @@ public void fillTree(Tree tree) { @Override public Window createNewFileWindow() { - return new Window(); + return new NewFileWindow(this); + } + + private static final String[] ILLEGAL_CHARACTERS = { "/", "\n", "\r", "\t", "\0", "\f", "`", "?", "*", "\\", "<", ">", "|", "\"", ":" }; + + @SuppressWarnings("serial") + private class NewFileWindow extends Window { + TextField nameField = new TextField(); + private NewFileWindow(final GenericProject p) { + super("New File"); + HorizontalLayout h = new HorizontalLayout(); + h.addComponent(new Label("Filename: ")); + h.addComponent(nameField); + Button b = new Button("Add"); + addComponent(h); + addComponent(b); + b.addListener(new ClickListener() { + public void buttonClick(ClickEvent event) { + String n = (String)nameField.getValue(); + if (n.isEmpty()) { + return; + } + for (String c : ILLEGAL_CHARACTERS) { + if (n.contains(c)) { + return; + } + } + p.addDoc(new ProjectFile(n), new Doc("")); + NewFileWindow.this.close(); + } + }); + } } - } diff --git a/cored/src/main/java/org/vaadin/cored/model/Project.java b/cored/src/main/java/org/vaadin/cored/model/Project.java index c54d002..db1e638 100644 --- a/cored/src/main/java/org/vaadin/cored/model/Project.java +++ b/cored/src/main/java/org/vaadin/cored/model/Project.java @@ -20,19 +20,14 @@ import org.apache.commons.io.FileUtils; import org.vaadin.aceeditor.collab.DocDiff; import org.vaadin.aceeditor.collab.gwt.shared.Doc; -import org.vaadin.aceeditor.gwt.shared.LockMarkerData; -import org.vaadin.aceeditor.gwt.shared.Marker; import org.vaadin.chatbox.SharedChat; -import org.vaadin.chatbox.gwt.shared.Chat; import org.vaadin.chatbox.gwt.shared.ChatDiff; import org.vaadin.chatbox.gwt.shared.ChatLine; import org.vaadin.cored.BuildComponent; -import org.vaadin.cored.EditorUtil; import org.vaadin.cored.LoggerTask; import org.vaadin.cored.MyFileUtils; import org.vaadin.cored.ProjectLog; import org.vaadin.cored.PropertiesUtil; -import org.vaadin.diffsync.DiffTask; import org.vaadin.diffsync.Shared; import org.vaadin.diffsync.Shared.Listener; @@ -42,9 +37,12 @@ //TODO: check synchronization -// TODO: refactor: create a CoredDocument class (containing Doc -// and stuff such as marker chats, file writing, etc.) - +/** + * An abstract cored project containing the project files (CoredDoc's) as well as other related things. + * + * Must subclassed to create projects of various types, eg. Vaadin, Python, ... + * + */ public abstract class Project { private static final Pattern VALID_PROJECT_NAME = Pattern.compile("[a-z][a-z0-9]*"); @@ -55,7 +53,7 @@ public abstract class Project { private final ProjectLog log; public enum ProjectType { - vaadin, python, generic; + vaadin, python, generic, django; } public interface DocListener { @@ -67,41 +65,51 @@ public interface DocValueChangeListener { public void docValueChanged(ProjectFile pf, Doc newValue); } - abstract public void fillTree(Tree tree); - abstract public Window createNewFileWindow(); - /** - * Adds things like error checkers and other things specific to project type to the doc. + * Must fill the tree (com.vaadin.ui.Tree) with the files of this project. + * + * It's a tree so the files can be put to a hierarchy by type or something like that. + * */ - protected void decorateDoc(ProjectFile file, Shared sharedDoc) { - // Default implementation does nothing. - } + abstract public void fillTree(Tree tree); /** - * Override in subclass if needed + * Returns a Window (com.vaadin.ui.Window) for creating a new File. + * + * The window must have the needed functionality to actually create the file. + * What kind of files to create depends on the project. + * */ - protected void projectInitialized(boolean createSkeleton) { } + abstract public Window createNewFileWindow(); /** + * Called when the project has been initialized. * - * @return file is editable with editor + * Override in subclass if needed. To for example create some default files in the project + * at the beginning or something. */ - protected boolean isEditableFile(File f) { - return true; // default implementation - } + protected void projectInitialized(boolean createSkeleton) { } + /** - * Override in subclass if needed + * Called when the project directory has been created on the disk. + * + * Can be overridden in subclass if it needs to for example read some of the contents of + * files to memory. */ + // TODO: is this really needed? protected void projectDirCreated() { } /** - * Override in subclass if needed + * If the project has something it needs to add to the IDE menu, + * it can override this method and add item(s) to the menubar. */ public void addMenuItem(MenuBar menuBar) { } /** - * Override in subclass if needed + * Returns a build component for the project. + * + * Implement in subclass if the project needs to be built. */ public BuildComponent createBuildComponent() { return null; @@ -115,7 +123,7 @@ public BuildComponent createBuildComponent() { private final String projName; - protected Map> files = new HashMap>(); + protected Map files = new HashMap(); private SharedChat projectChat; private Team team; @@ -124,8 +132,7 @@ public BuildComponent createBuildComponent() { private static volatile File projectsRootDir; - private HashMap> fileMarkerChats = - new HashMap>(); + private ProjectType projectType; @@ -265,6 +272,9 @@ else if (ProjectType.vaadin.equals(type)){ else if (ProjectType.generic.equals(type)){ p = new GenericProject(name); } + else if (ProjectType.django.equals(type)){ + p = new DjangoProject(name); + } else { throw new IllegalStateException("???"); } @@ -371,7 +381,7 @@ public String getName() { return projName; } - synchronized public Shared getDoc(ProjectFile file) { + synchronized public CoredDoc getDoc(ProjectFile file) { return files.get(file); } @@ -387,41 +397,47 @@ synchronized public ProjectFile getProjectFile(String filename) { } return null; } - - public Shared createDoc(ProjectFile file, Doc doc, - long collaboratorId) { - Shared sharedDoc; - synchronized (this) { - if (files.containsKey(file)) { - sharedDoc = files.get(file); - sharedDoc.setValue(doc, collaboratorId); - return sharedDoc; - } - - sharedDoc = addNewSharedDoc(file, doc); - - try { - writeFileToDisk(file, doc); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + + public CoredDoc addDoc(ProjectFile file, Doc doc) { + CoredDoc cd; + if (files.containsKey(file)) { + cd = files.get(file); + cd.setValue(doc); + return cd; } - fireDocCreated(file); - - return sharedDoc; + else { + cd = addNewCoredDoc(file, doc); + } + return cd; } - private Shared addNewSharedDoc(ProjectFile file, Doc doc) { - Shared sharedDoc = new Shared(doc); - decorateDoc(file, sharedDoc); + final protected CoredDoc addNewCoredDoc(CoredDoc cd) { + ProjectFile file = cd.getProjectFile(); + try { + cd.writeToDisk(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } if (logging) { log.logNewFile(file); - sharedDoc.addTask(new LoggerTask(this,file)); + cd.getShared().addTask(new LoggerTask(this,file)); } - files.put(file, sharedDoc); - listenTo(file, sharedDoc); - return sharedDoc; + files.put(file, cd); + listenTo(file, cd.getShared()); + fireDocCreated(file); + return cd; + } + + /** + * + * @param file + * @param doc + * @return + */ + protected CoredDoc addNewCoredDoc(ProjectFile file, Doc doc) { + return addNewCoredDoc(new CoredDoc(getProjectDir(), file, doc, log)); + } private void listenTo(final ProjectFile file, Shared sharedDoc) { @@ -435,22 +451,13 @@ public void changed(Doc newValue, DocDiff diff, long collaboratorId) { } - - public Shared createDoc(ProjectFile file, String content) { - return createDoc(file, new Doc(content), Shared.NO_COLLABORATOR_ID); - } - - public Shared createDoc(ProjectFile file) { - return createDoc(file, new Doc(), Shared.NO_COLLABORATOR_ID); - } - public void removeDoc(ProjectFile file) { boolean removed = false; synchronized (this) { - if (files.containsKey(file)) { - getLocationOfFile(file).delete(); + CoredDoc cd = files.get(file); + if (cd!=null) { + cd.deleteFromDisk(); files.remove(file); - removeMarkerChatsOf(file); removed = true; } } @@ -466,83 +473,43 @@ synchronized public SharedChat getProjectChat() { return projectChat; } - synchronized public SharedChat getMarkerChat(ProjectFile file, String markerId) { - if (fileMarkerChats.containsKey(file)) { - return fileMarkerChats.get(file).get(markerId); - } - return null; - } - - synchronized public SharedChat getMarkerChatCreateIfNotExist( - ProjectFile file, String markerId, List initial) { - HashMap markerChats = fileMarkerChats.get(file); - if (markerChats == null) { - markerChats = new HashMap(); - fileMarkerChats.put(file, markerChats); - } - SharedChat chat = markerChats.get(markerId); - if (chat == null) { - chat = new SharedChat(new Chat(initial)); - if (logging) { - for (ChatLine li : initial) { - log.logMarkerChat(markerId, li.getUserId(), li.getText()); - } - chat.addTask(new ChatLogTask(log, markerId)); - } - fileMarkerChats.get(file).put(markerId, chat); - } - return chat; - - } - - synchronized public Shared removeMarkerChat( - ProjectFile file, String markerId) { - if (fileMarkerChats.containsKey(file)) { - return fileMarkerChats.get(file).remove(markerId); - } - return null; - } - - private HashMap removeMarkerChatsOf(ProjectFile file) { - return fileMarkerChats.remove(file); - } - synchronized public Team getTeam() { return team; } synchronized public void writeToDisk() throws IOException { - for (Entry> e : files.entrySet()) { + for (Entry e : files.entrySet()) { if (e.getValue() != null) { - writeFileToDisk(e.getKey(), e.getValue().getValue()); + e.getValue().writeToDisk(); } } } - - private void writeFileToDisk(ProjectFile file, Doc doc) throws IOException { - writeFileToDisk(file, doc, getLocationOfFile(file)); - } - private void writeFileToDisk(ProjectFile file, Doc doc, File dest) throws IOException { - if (doc == null) { - return; - } - FileUtils.write(dest, doc.getText()); - } - + public void log(String text) { getProjectChat().applyDiff(ChatDiff.newLiveLine(new ChatLine(text))); } - private boolean readFromDisk() { + public boolean readFromDisk() { TreeSet files = getFilesIn(getProjectDir()); boolean isProjectDir = false; for (File f : files) { if (f.getName().equals(PROPERTY_FILE_NAME)) { isProjectDir = true; } - else if (isEditableFile(f)) { - readFileFromDisk(f); + else { + String rel = MyFileUtils.relativizePath(getProjectDir(), f); + ProjectFile pf = new ProjectFile(rel); + if (pf.isEditable()) { + try { + Doc doc = CoredDoc.fromDisk(getProjectDir(), pf); + addNewCoredDoc(pf, doc); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } } return isProjectDir; @@ -636,31 +603,6 @@ final protected File getLocationOfFile(ProjectFile file) { return new File(getProjectDir(), file.getPath()); } - private boolean readFileFromDisk(File fileFullPath) { - String rel = MyFileUtils.relativizePath(getProjectDir(), fileFullPath); - return readFileFromDisk(new ProjectFile(rel)); - } - - private boolean readFileFromDisk(ProjectFile file) { - String content; - try { - content = FileUtils.readFileToString(getLocationOfFile(file)); - } catch (IOException e) { - return false; - } - - if (files.containsKey(file)) { - Shared shared = files.get(file); - shared.setValue(new Doc(content), Shared.NO_COLLABORATOR_ID); - } - else { - if (EditorUtil.isEditableWithEditor(file)) { - addNewSharedDoc(file, new Doc(content)); - } - } - - return true; - } synchronized public File getProjectDir() { if (projectsRootDir == null) { @@ -719,31 +661,16 @@ public static void kickFromAllProjects(User user) { } } - synchronized public void removeCursorMarkersOf(User user, ProjectFile file) { - Shared doc; - synchronized (files) { - doc = files.get(file); - } - doc.applyDiff(user.getRemoveMarkersDiff()); - } - synchronized public void removeCursorMarkersOf(User user) { DocDiff diff = user.getRemoveMarkersDiff(); - for (Shared doc : files.values()) { - doc.applyDiff(diff); + for (CoredDoc cd : files.values()) { + cd.getShared().applyDiff(diff); } } synchronized public void removeLocksOf(User user) { - for (Shared doc : files.values()) { - for (Entry e : doc.getValue().getMarkers().entrySet()) { - Marker m = e.getValue(); - if (m.getType()==Marker.Type.LOCK && - user.getUserId().equals(((LockMarkerData)m.getData()).getLockerId())) { - doc.applyDiff(DocDiff.removeMarker(e.getKey())); - } - - } + for (CoredDoc cd : files.values()) { + cd.removeLocksOf(user); } } diff --git a/cored/src/main/java/org/vaadin/cored/model/ProjectFile.java b/cored/src/main/java/org/vaadin/cored/model/ProjectFile.java index bf412ef..78a2bf5 100644 --- a/cored/src/main/java/org/vaadin/cored/model/ProjectFile.java +++ b/cored/src/main/java/org/vaadin/cored/model/ProjectFile.java @@ -22,5 +22,12 @@ public ProjectFile(String f) { public ProjectFile(String parent, String child) { super(parent, child); } + + /** + * Can be overridden in subclass if needed. + */ + public boolean isEditable() { + return true; + } } diff --git a/cored/src/main/java/org/vaadin/cored/model/PythonProject.java b/cored/src/main/java/org/vaadin/cored/model/PythonProject.java index 7561f9c..81bcedf 100644 --- a/cored/src/main/java/org/vaadin/cored/model/PythonProject.java +++ b/cored/src/main/java/org/vaadin/cored/model/PythonProject.java @@ -2,6 +2,8 @@ import java.util.regex.Pattern; +import org.vaadin.aceeditor.collab.gwt.shared.Doc; + import com.vaadin.data.validator.AbstractValidator; import com.vaadin.ui.Button; @@ -45,19 +47,18 @@ protected PythonProject(String name) { protected void projectInitialized(boolean createSkeleton) { if (createSkeleton) { String ske = createSkeletonCode(); - createDoc(new ProjectFile("main.py"), ske); + addDoc(new ProjectFile("main.py"), new Doc(ske)); } } - - + private static String createSkeletonCode() { return "print \"Hello, World!\" \n"; - } @Override public void fillTree(Tree tree) { for (ProjectFile pf : super.getProjectFiles()) { + System.out.println("Python " + pf.getName()); tree.addItem(pf); tree.setItemCaption(pf, pf.getName()); tree.setChildrenAllowed(pf, false); @@ -82,7 +83,7 @@ public void buttonClick(ClickEvent event) { if (!PythonUtils.isValidPythonClass(n)) { return; } - p.createDoc(new ProjectFile(n+".py"), "# "+n+".py\n"); + p.addDoc(new ProjectFile(n+".py"), new Doc("# "+n+".py\n")); NewPyFileWindow.this.close(); } }); diff --git a/cored/src/main/java/org/vaadin/cored/model/SharedDoc.java b/cored/src/main/java/org/vaadin/cored/model/SharedDoc.java new file mode 100644 index 0000000..1786e7e --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/model/SharedDoc.java @@ -0,0 +1,13 @@ +package org.vaadin.cored.model; + +import org.vaadin.aceeditor.collab.DocDiff; +import org.vaadin.aceeditor.collab.gwt.shared.Doc; +import org.vaadin.diffsync.Shared; + +public class SharedDoc extends Shared { + + public SharedDoc(Doc value) { + super(value); + } + +} diff --git a/cored/src/main/java/org/vaadin/cored/model/VaadinCoredDoc.java b/cored/src/main/java/org/vaadin/cored/model/VaadinCoredDoc.java new file mode 100644 index 0000000..b020dc7 --- /dev/null +++ b/cored/src/main/java/org/vaadin/cored/model/VaadinCoredDoc.java @@ -0,0 +1,44 @@ +package org.vaadin.cored.model; + +import org.vaadin.aceeditor.ErrorChecker; +import org.vaadin.aceeditor.collab.DocDiff; +import org.vaadin.aceeditor.collab.ErrorCheckTask; +import org.vaadin.aceeditor.collab.gwt.shared.Doc; +import org.vaadin.aceeditor.java.CompilerErrorChecker; +import org.vaadin.diffsync.DiffTaskExecPolicy; +import org.vaadin.diffsync.Shared; + +public class VaadinCoredDoc extends CoredDoc { + + private final VaadinProject project; + + public VaadinCoredDoc(VaadinProject project, ProjectFile file, SharedDoc shared) { + super(project.getProjectDir(), file, shared, project.getLog()); + this.project = project; + + if (file.getName().endsWith(".java")) { + + ErrorCheckTask task = createErrorCheckTaskFor(file, getShared()); + +// DocDiff d = task.exec(sharedDoc.getValue(), null, Shared.NO_COLLABORATOR_ID); +// if (d!=null) { +// sharedDoc.applyDiff(d); +// } + + getShared().addAsyncTask(task, DiffTaskExecPolicy.LATEST_CANCEL_RUNNING); + } + } + + public VaadinCoredDoc(VaadinProject project, ProjectFile file, Doc doc) { + this(project, file, new SharedDoc(doc)); + + } + + private ErrorCheckTask createErrorCheckTaskFor(ProjectFile file, Shared doc) { + String className = project.fullJavaNameOf(file.getName()); + ErrorChecker checker = new CompilerErrorChecker(project.getCompiler(), className); + ErrorCheckTask task = new ErrorCheckTask(doc.newCollaboratorId(), checker); + return task; + } + +} diff --git a/cored/src/main/java/org/vaadin/cored/model/VaadinProject.java b/cored/src/main/java/org/vaadin/cored/model/VaadinProject.java index ac873f7..3958b66 100644 --- a/cored/src/main/java/org/vaadin/cored/model/VaadinProject.java +++ b/cored/src/main/java/org/vaadin/cored/model/VaadinProject.java @@ -160,7 +160,7 @@ synchronized public TreeSet getSourceFiles() { protected void projectInitialized(boolean createSkeleton) { if (createSkeleton) { String ske = createSkeletonCode(getPackageName(), getApplicationClassName()); - createDoc(getApplicationFile(), ske); + addDoc(getApplicationFile(), new Doc(ske)); } updateJarsFromDisk(); } @@ -209,18 +209,20 @@ synchronized public void checkErrors(ProjectFile file) { if (!file.getName().endsWith(".java")) { return; } - Shared doc = getDoc(file); + CoredDoc doc = getDoc(file); if (doc == null) { return; } - DocDiff d = createErrorCheckTaskFor(file, doc).exec(doc.getValue(), null, 0); + SharedDoc shared = doc.getShared(); + DocDiff d = createErrorCheckTaskFor(file, shared) + .exec(shared.getValue(), null, 0); if (d!=null) { - doc.applyDiff(d); + shared.applyDiff(d); } } - private String fullJavaNameOf(String name) { + String fullJavaNameOf(String name) { if (!name.endsWith(".java")) { return null; } @@ -272,13 +274,6 @@ private static String generateClass(String name, String base) { + " \n}\n"; } } - - @Override - public Shared createDoc(ProjectFile file, Doc doc, - long collaboratorId) { - Shared shared = super.createDoc(file, doc, collaboratorId); - return shared; - } @Override public void removeDoc(ProjectFile file) { @@ -309,9 +304,9 @@ public void fillTree(Tree tree) { for (ProjectFile pf : getSourceFiles()) { tree.addItem(pf); - Shared doc = getDoc(pf); + CoredDoc doc = getDoc(pf); if (doc != null) { - if (doc.getValue().hasErrors()) { + if (doc.getShared().getValue().hasErrors()) { tree.setItemIcon(pf, Icons.CROSS_CIRCLE); } else { tree.setItemIcon(pf, Icons.TICK_SMALL); @@ -337,8 +332,8 @@ public Window createNewFileWindow() { } @Override - protected boolean isEditableFile(File f) { - return f.getName().endsWith(".java"); + protected CoredDoc addNewCoredDoc(ProjectFile file, Doc doc) { + return addNewCoredDoc(new VaadinCoredDoc(this, file, doc)); } @SuppressWarnings("serial") @@ -360,29 +355,30 @@ public void menuSelected(MenuItem selectedItem) { // XXX: this compilation is a bit of a mess... protected final void compileAll() { - Map> m; + Map m; synchronized (this) { - m = new HashMap>(files); + m = new HashMap(files); } HashMap ss = new HashMap(); - for (Entry> e : m.entrySet()) { - ss.put(fullClassNameOf(e.getKey()), e.getValue().getValue().getText()); + for (Entry e : m.entrySet()) { + ss.put(fullClassNameOf(e.getKey()), e.getValue().getShared().getValue().getText()); } Map>> xx = getCompiler().compileAll(ss); for (Entry>> e : xx.entrySet()) { - Shared doc = getDoc(fromFullClassName(e.getKey())); + CoredDoc doc = getDoc(fromFullClassName(e.getKey())); if (doc==null) { continue; } + SharedDoc shared = doc.getShared(); final List> errors = e.getValue(); - DocDiff d = new ErrorCheckTask(doc.newCollaboratorId(), new ErrorChecker() { + DocDiff d = new ErrorCheckTask(shared.newCollaboratorId(), new ErrorChecker() { public Collection getErrors(String source) { return CompilerErrorChecker.errorsFromDiagnostics(errors); } - }).exec(doc.getValue(), null, Shared.NO_COLLABORATOR_ID); - doc.applyDiff(d); + }).exec(shared.getValue(), null, Shared.NO_COLLABORATOR_ID); + shared.applyDiff(d); } @@ -419,6 +415,7 @@ synchronized public boolean removeJar(String filename) { return false; } + @Override public BuildComponent createBuildComponent() { return new VaadinBuildComponent(this, DeployType.war);