/*
* ====================================================================
*
* The ObjectStyle Group Software License, Version 1.0
*
* Copyright (c) 2005 The ObjectStyle Group and individual authors of the
* software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: 1.
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. The end-user documentation
* included with the redistribution, if any, must include the following
* acknowlegement: "This product includes software developed by the ObjectStyle
* Group (http://objectstyle.org/)." Alternately, this acknowlegement may
* appear in the software itself, if and wherever such third-party
* acknowlegements normally appear. 4. The names "ObjectStyle Group" and
* "Cayenne" must not be used to endorse or promote products derived from this
* software without prior written permission. For written permission, please
* contact andrus@objectstyle.org. 5. Products derived from this software may
* not be called "ObjectStyle" nor may "ObjectStyle" appear in their names
* without prior written permission of the ObjectStyle Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* OBJECTSTYLE GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the ObjectStyle Group. For more information on the ObjectStyle
* Group, please see <http://objectstyle.org/> .
*
*/
package org.objectstyle.wolips.pbserver;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.StringReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.IDocument;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
/**
* @author mike
*/
public class PBServer {
public static final int DEFAULT_PB_PORT = 8547;
ServerSocket myServerSocket;
private Thread myServerThread;
boolean myRunning;
public PBServer() {
super();
}
public synchronized void start(int _port) throws IOException {
myServerSocket = new ServerSocket(_port);
myRunning = true;
myServerThread = new Thread(new ServerSocketAcceptor());
myServerThread.start();
}
public synchronized void stop() throws IOException {
myRunning = false;
myServerSocket.close();
}
private Element appendArray(Document _document) {
Element arrayElement = _document.createElement("array");
_document.appendChild(arrayElement);
return arrayElement;
}
private Element appendString(Element _element, String _string) {
Element stringElement = _element.getOwnerDocument().createElement("string");
_element.appendChild(stringElement);
Text stringText = _element.getOwnerDocument().createTextNode(_string);
stringElement.appendChild(stringText);
return stringElement;
}
private String text(Element _element, String _tagName) {
NodeList elementsList = _element.getElementsByTagName(_tagName);
String text;
if (elementsList.getLength() > 0) {
Element textElementContainer = (Element) elementsList.item(0);
Text textNode = (Text) textElementContainer.getChildNodes().item(0);
text = textNode.getNodeValue();
} else {
text = null;
}
return text;
}
public String[] strings(Element _parentElement, String _arrayName) {
Element arrayParentElement = (Element) _parentElement.getElementsByTagName(_arrayName).item(0);
Element arrayElement = (Element) arrayParentElement.getElementsByTagName("array").item(0);
NodeList stringsList = arrayElement.getChildNodes();
String[] strings = new String[stringsList.getLength()];
for (int i = 0; i < strings.length; i++) {
Element textElementContainer = (Element) stringsList.item(0);
Text textNode = (Text) textElementContainer.getChildNodes().item(0);
strings[i] = textNode.getNodeValue();
}
return strings;
}
private IProject project(Document _requestDocument, String _cookieName) {
String cookie = text(_requestDocument.getDocumentElement(), _cookieName);
IContainer container = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(new Path(cookie));
IProject project = container.getProject();
return project;
}
private String path(Document _requestDocument) {
String path = text(_requestDocument.getDocumentElement(), "path");
return path;
}
public Document openProjectsAppropriateForFile(Document _requestDocument) throws ParserConfigurationException, TransformerFactoryConfigurationError, TransformerException {
String path = path(_requestDocument);
Document responseDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
IContainer[] containers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocation(new Path(path));
Element arrayElement = appendArray(responseDocument);
for (int i = 0; i < containers.length; i++) {
IProject project = containers[i].getProject();
IFile xcodeFile = project.getFile(project.getName() + ".xcode");
if (!xcodeFile.exists()) {
xcodeFile = project.getFile(project.getName() + ".xcodeproj");
}
String xcodeFilePath = xcodeFile.getLocation().toOSString();
if (containers[i].getName().endsWith(".woa")) {
// <?xml version="1.0" encoding="UTF-8"?>
// <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
// "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
// <plist version="1.0">
// <dict>
// <key>PBXProjectSourcePath</key>
// <string>/Users/mschrag/TestApp/TestApp.xcodeproj</string>
// </dict>
// </plist>
IFile pbDevelopmentResourceFile = containers[i].getFile(new Path("Contents").append("pbdevelopment.plist"));
Document pbDevelopmentDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element plistElement = pbDevelopmentDocument.createElement("plist");
plistElement.setAttribute("version", "1.0");
pbDevelopmentDocument.appendChild(plistElement);
Element dictElement = pbDevelopmentDocument.createElement("dict");
plistElement.appendChild(dictElement);
Element keyElement = pbDevelopmentDocument.createElement("key");
dictElement.appendChild(keyElement);
keyElement.appendChild(pbDevelopmentDocument.createTextNode("PBXProjectSourcePath"));
Element stringElement = pbDevelopmentDocument.createElement("string");
dictElement.appendChild(stringElement);
stringElement.appendChild(pbDevelopmentDocument.createTextNode(xcodeFilePath));
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(pbDevelopmentDocument);
File pbDevelopmentFile = pbDevelopmentResourceFile.getLocation().toFile();
StreamResult result = new StreamResult(pbDevelopmentFile);
transformer.transform(source, result);
}
appendString(arrayElement, xcodeFilePath);
}
return responseDocument;
}
public Document targetsInProjectContainingFile(Document _requestDocument) throws ParserConfigurationException {
IProject project = project(_requestDocument, "cookie");
// String path = path(_requestDocument);
// IContainer[] containers =
// ResourcesPlugin.getWorkspace().getRoot().findContainersForLocation(new
// Path(path));
Document responseDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
appendString(appendArray(responseDocument), project.getName());
appendString(appendArray(responseDocument), "Application Server");
appendString(appendArray(responseDocument), "Web Server");
return responseDocument;
}
public Document targetsInProject(/* Document _requestDocument */) throws ParserConfigurationException {
// IProject project = project(_requestDocument, "cookie");
Document responseDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
appendString(appendArray(responseDocument), "mockTarget");
return responseDocument;
}
public void nameOfProject(Document _requestDocument, OutputStream _os) {
IProject project = project(_requestDocument, "projectCookie");
new PrintStream(_os, true).print(project.getName());
}
public void addFilesToProject(Document _requestDocument, OutputStream _os) {
Element documentElement = _requestDocument.getDocumentElement();
String[] addFiles = strings(documentElement, "addFiles");
for (int i = 0; i < addFiles.length; i++) {
System.out.println("PBServer.addFilesToProject: add files " + addFiles[i]);
}
// IProject project = project(_requestDocument, "toProject");
// String nearFile = text(documentElement, "nearFile");
// String preferredInsertionGroupName = text(documentElement,
// "preferredInsertionGroupName");
// String[] addToTargets = strings(documentElement, "addToTargets");
// boolean copyIntoGroupFolder = booleanValue(documentElement,
// "copyIntoGroupFolder");
// boolean createGroupsRecursively = booleanValue(documentElement,
// "createGroupsRecursively");
new PrintStream(_os, true).print("YES");
}
public Document filesOfTypesInTargetOfProject(Document _requestDocument) throws ParserConfigurationException, CoreException {
// stringbuffer.append("<filesOfTypesInTargetOfProject>");
// stringbuffer.append("<cookie>" + s1 + "</cookie>");
// stringbuffer.append("<target>" + s + "</target>");
// stringbuffer.append("<typesArray>" + _xmlStringArray(nsarray) +
// "</typesArray>");
// stringbuffer.append("</filesOfTypesInTargetOfProject>");
IProject project = project(_requestDocument, "cookie");
Element documentElement = _requestDocument.getDocumentElement();
// String targetName = text(documentElement, "target");
String[] typesArray = strings(documentElement, "typesArray");
FileTypeResourceVisitor visitor = new FileTypeResourceVisitor(typesArray);
project.accept(visitor, IResource.DEPTH_INFINITE, IContainer.EXCLUDE_DERIVED);
Document responseDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element arrayElement = appendArray(responseDocument);
Iterator matchingResourcesIter = visitor.getMatchingFiles().iterator();
while (matchingResourcesIter.hasNext()) {
IResource resource = (IResource) matchingResourcesIter.next();
appendString(arrayElement, resource.getLocation().toOSString());
}
return responseDocument;
}
public void nameOfTargetInProject(Document _requestDocument, OutputStream _os) {
// stringbuffer.append("<nameOfTarget>");
// stringbuffer.append("<targetCookie>" + s + "</targetCookie >");
// stringbuffer.append("<projectCookie>" + s1 + "</projectCookie >");
// stringbuffer.append("</nameOfTarget>");
// IProject project = project(_requestDocument, "projectCookie");
Element documentElement = _requestDocument.getDocumentElement();
String targetCookie = text(documentElement, "targetCookie");
new PrintStream(_os, true).print(targetCookie);
}
public void openFile(Document _requestDocument, OutputStream _os) {
// stringbuffer.append("<OpenFile><filename>");
// stringbuffer.append(s);
// stringbuffer.append("</filename><linenumber>");
// stringbuffer.append(i);
// stringbuffer.append("</linenumber><message>");
// stringbuffer.append(s1);
// stringbuffer.append("</message></OpenFile>");
String filename = text(_requestDocument.getDocumentElement(), "filename");
String lineNumberStr = text(_requestDocument.getDocumentElement(), "linenumber");
// String message = text(_requestDocument.getDocumentElement(),
// "message");
final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(filename));
final int lineNumber = Integer.parseInt(lineNumberStr);
if (file != null) {
IWorkbenchWindow[] workbenchWindows = PlatformUI.getWorkbench().getWorkbenchWindows();
for (int i = 0; i < workbenchWindows.length; i++) {
final IWorkbenchPage workbenchPage = workbenchWindows[i].getActivePage();
if (workbenchPage != null) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
try {
IEditorPart editorPart = IDE.openEditor(workbenchPage, file, true);
if (editorPart != null && editorPart instanceof ITextEditor) {
ITextEditor textEditor = (ITextEditor) editorPart;
IDocumentProvider documentProvider = textEditor.getDocumentProvider();
IDocument document = documentProvider.getDocument(textEditor.getEditorInput());
int lineOffset = document.getLineOffset(lineNumber - 1);
textEditor.selectAndReveal(lineOffset, 0);
}
} catch (Throwable t) {
t.printStackTrace(System.out);
}
}
});
}
}
}
new PrintStream(_os, true).print("YES");
}
public void addGroup(Document _requestDocument, OutputStream _os) {
// stringbuffer.append("<addGroup>");
// stringbuffer.append("<name>" + s + "</name >");
// if(s1 != null)
// stringbuffer.append("<path>" + s1 + "</path >");
// stringbuffer.append("<projectCookie>" + s2 + "</projectCookie >");
// if(s3 != null)
// stringbuffer.append("<nearFile>" + s3 + "</nearFile >");
// stringbuffer.append("</addGroup>");
String name = text(_requestDocument.getDocumentElement(), "name");
// String path = text(_requestDocument.getDocumentElement(), "path");
System.out.println("PBServer.addGroup: name = " + name);
// IProject project = project(_requestDocument, "projectCookie");
// String nearFile = text(_requestDocument.getDocumentElement(),
// "nearFile");
new PrintStream(_os, true).print("YES");
}
public void addGroupToPreferredInsertionGroup(Document _requestDocument, OutputStream _os) {
// stringbuffer.append("<addGroupToPreferredInsertionGroup>");
// stringbuffer.append("<name>" + s + "</name >");
// if(s1 != null)
// stringbuffer.append("<path>" + s1 + "</path >");
// stringbuffer.append("<projectCookie>" + s2 + "</projectCookie >");
// if(s3 != null)
// stringbuffer.append("<nearFile>" + s3 + "</nearFile >");
// if(s4 != null)
// stringbuffer.append("<preferredInsertionGroup>" + s4 +
// "</preferredInsertionGroup >");
// stringbuffer.append("</addGroupToPreferredInsertionGroup>");
String name = text(_requestDocument.getDocumentElement(), "name");
System.out.println("PBServer.addGroupToPreferredInsertionGroup: name = " + name);
// String path = text(_requestDocument.getDocumentElement(), "path");
// IProject project = project(_requestDocument, "projectCookie");
// String nearFile = text(_requestDocument.getDocumentElement(),
// "nearFile");
// String preferredInsertionGroup =
// text(_requestDocument.getDocumentElement(),
// "preferredInsertionGroup");
new PrintStream(_os, true).print("YES");
}
public void handleRequestDocument(Document _requestDocument, OutputStream _os) throws Throwable {
Document responseDocument = null;
String nodeName = _requestDocument.getDocumentElement().getNodeName();
if ("openProjectsAppropriateForFile".equals(nodeName)) {
responseDocument = openProjectsAppropriateForFile(_requestDocument);
} else if ("targetsInProjectContainingFile".equals(nodeName)) {
responseDocument = targetsInProjectContainingFile(_requestDocument);
} else if ("targetsInProject".equals(nodeName)) {
responseDocument = targetsInProject(/* _requestDocument */);
} else if ("nameOfProject".equals(nodeName)) {
nameOfProject(_requestDocument, _os);
} else if ("addFilesToProject".equals(nodeName)) {
addFilesToProject(_requestDocument, _os);
} else if ("filesOfTypesInTargetOfProject".equals(nodeName)) {
responseDocument = filesOfTypesInTargetOfProject(_requestDocument);
} else if ("nameOfTarget".equals(nodeName)) {
nameOfTargetInProject(_requestDocument, _os);
} else if ("OpenFile".equals(nodeName)) {
openFile(_requestDocument, _os);
} else if ("addGroup".equals(nodeName)) {
addGroup(_requestDocument, _os);
} else if ("addGroupToPreferredInsertionGroup".equals(nodeName)) {
addGroupToPreferredInsertionGroup(_requestDocument, _os);
} else {
System.out.println("PBServer.run: Unknown request: " + nodeName);
// responseDocument = null;
}
if (responseDocument != null) {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(responseDocument);
StreamResult result = new StreamResult(_os);
transformer.transform(source, result);
}
}
public class FileTypeResourceVisitor implements IResourceVisitor {
private String[] myFileTypes;
private List myMatchingFiles;
public FileTypeResourceVisitor(String[] _fileTypes) {
myFileTypes = _fileTypes;
myMatchingFiles = new LinkedList();
}
public List getMatchingFiles() {
return myMatchingFiles;
}
public boolean visit(IResource _resource) throws CoreException {
boolean matched = false;
for (int i = 0; !matched && i < myFileTypes.length; i++) {
if (myFileTypes[i].equalsIgnoreCase(_resource.getFileExtension())) {
myMatchingFiles.add(_resource);
matched = true;
}
}
return true;
}
}
public class ServerSocketAcceptor implements Runnable {
public void run() {
while (myRunning) {
try {
Socket socket = myServerSocket.accept();
OutputStream os = socket.getOutputStream();
try {
InputStream is = socket.getInputStream();
StringBuffer sb = new StringBuffer();
sb.append((char) is.read());
while (is.available() > 0) {
int ch = is.read();
sb.append((char) ch);
}
Document requestDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(sb.toString())));
handleRequestDocument(requestDocument, os);
} finally {
os.flush();
os.close();
}
} catch (Throwable t) {
t.printStackTrace(System.out);
}
}
}
}
}