Added Run Tests Action in the popup menu for .php file
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / PHPSyntaxRdr.java
1 package net.sourceforge.phpeclipse.phpeditor;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.OutputStream;
9 import java.io.UnsupportedEncodingException;
10 import java.util.ArrayList;
11
12 import javax.xml.parsers.DocumentBuilder;
13 import javax.xml.parsers.DocumentBuilderFactory;
14 import javax.xml.parsers.ParserConfigurationException;
15 import javax.xml.transform.OutputKeys;
16 import javax.xml.transform.Transformer;
17 import javax.xml.transform.TransformerException;
18 import javax.xml.transform.TransformerFactory;
19 import javax.xml.transform.dom.DOMSource;
20 import javax.xml.transform.stream.StreamResult;
21
22 import net.sourceforge.phpeclipse.IPreferenceConstants;
23 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
24 import net.sourceforge.phpeclipse.phpeditor.php.PHPConstant;
25 import net.sourceforge.phpeclipse.phpeditor.php.PHPElement;
26 import net.sourceforge.phpeclipse.phpeditor.php.PHPFunction;
27 import net.sourceforge.phpeclipse.phpeditor.php.PHPKeyword;
28 import net.sourceforge.phpeclipse.phpeditor.php.PHPType;
29
30 import org.eclipse.core.runtime.CoreException;
31 import org.eclipse.core.runtime.IPath;
32 import org.eclipse.core.runtime.IStatus;
33 import org.eclipse.jface.preference.IPreferenceStore;
34 import org.w3c.dom.Attr;
35 import org.w3c.dom.Document;
36 import org.w3c.dom.NamedNodeMap;
37 import org.w3c.dom.Node;
38 import org.w3c.dom.NodeList;
39 import org.w3c.dom.Text;
40 import org.xml.sax.InputSource;
41 import org.xml.sax.SAXException;
42 import org.xml.sax.SAXParseException;
43
44 /**
45  * <code>PHPSyntaxRdr</code> reads PHP specifics from an XML file (eg. keywords) 
46  */
47
48 public class PHPSyntaxRdr {
49   private static final String PHPDEFAULT_FILE = "default-phpsyntax.xml"; //$NON-NLS-1$
50   private static final String PHPSYNTAX_FILE = "phpsyntax.xml"; //$NON-NLS-1$
51   private static final String USERSYNTAX_FILE = "usersyntax.xml"; //$NON-NLS-1$
52   private static final String USERDEFAULT_FILE = "default-usersyntax.xml"; //$NON-NLS-1$
53   private static final String PHPSYNTAX_TAG = "phpsyntax"; //$NON-NLS-1$
54   private static final String KEYWORD_ATTR = "keyword"; //$NON-NLS-1$
55   private static final String TYPE_ATTR = "type"; //$NON-NLS-1$
56   private static final String CONSTANT_ATTR = "constant"; //$NON-NLS-1$
57   private static final String FN_ATTR = "function"; //$NON-NLS-1$
58   private static final String USAGE_ATTR = "usage"; //$NON-NLS-1$
59   private static final String TOKENVAL_ATTR = "tokenval"; //$NON-NLS-1$
60   private static IPreferenceStore store;
61   private static boolean hasXMLFileBeenRead = true;
62
63   //The following variable is used to hold the syntax from
64   //the suers custom file - if that file should be changed,
65   //then all entries in this variable should be removed from
66   //the word list, reread from the file and then reinserted.
67   private static ArrayList userdefsyntaxdata;
68
69   private static ArrayList syntaxdata;
70
71   public PHPSyntaxRdr() {
72     // see getSyntaxData()
73     syntaxdata = null;
74     store = PHPeclipsePlugin.getDefault().getPreferenceStore();
75   }
76
77   public static void readInSyntax() {
78     try {
79       hasXMLFileBeenRead = true;
80       /*Attempt to read the syntax file from the metadata
81        * if this does not work, create metadata from default*/
82       File syntaxFile = getSyntaxFile();
83       if (syntaxFile.exists()) {
84         readFromFile(syntaxFile);
85       } else {
86         readFromStream(PHPSyntaxRdr.class.getResourceAsStream(PHPSYNTAX_FILE));
87         saveToFile(syntaxFile);
88       }
89       /*Read the user-defined syntax file if it exists*/
90       //String buffer = new String(store.getString(PHPeclipsePlugin.PHP_USERDEF_XMLFILE));
91       if (store == null)
92         store = PHPeclipsePlugin.getDefault().getPreferenceStore();
93       String buffer = new String(store.getString(IPreferenceConstants.PHP_USERDEF_XMLFILE));
94       if (!(buffer.equals("") || buffer == null)) {
95         readFromFile(buffer);
96       }
97     } catch (CoreException ce) {
98       ce.printStackTrace();
99     }
100   }
101
102   public static void readFromFile(String filename) {
103     try {
104       readFromFile(new File(filename));
105     } catch (CoreException e) {
106     }
107   }
108
109   public static void readFromFile(File file) throws CoreException {
110     InputStream stream = null;
111
112     if (file.exists()) {
113       try {
114         stream = new FileInputStream(file);
115         readFromStream(stream);
116       } catch (IOException e) {
117         throwReadException(e);
118       } finally {
119         try {
120           if (stream != null) {
121             stream.close();
122           }
123         } catch (IOException e) {
124         }
125       }
126     }
127   }
128   public static void readFromStream(InputStream stream) throws CoreException {
129     try {
130       DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
131       DocumentBuilder parser = factory.newDocumentBuilder();
132       org.apache.crimson.parser.Parser2 pp;
133       Document document = parser.parse(new InputSource(stream));
134       //                Read in the Standard PHPSyntax "stuff"
135       NodeList elements = document.getElementsByTagName(PHPSYNTAX_TAG);
136
137       int count = elements.getLength();
138       for (int i = 0; i != count; i++) {
139         Node node = elements.item(i);
140         NamedNodeMap attributes = node.getAttributes();
141
142         if (attributes == null)
143           continue;
144
145         String Keyword = getAttributeValue(attributes, KEYWORD_ATTR);
146         String Type = getAttributeValue(attributes, TYPE_ATTR);
147         String Function = getAttributeValue(attributes, FN_ATTR);
148         String Constant = getAttributeValue(attributes, CONSTANT_ATTR);
149         String usage = getAttributeValue(attributes, USAGE_ATTR);
150         String Tokenval = getAttributeValue(attributes, TOKENVAL_ATTR);
151       
152         StringBuffer buffer = new StringBuffer();
153         NodeList children = node.getChildNodes();
154         for (int j = 0; j != children.getLength(); j++) {
155           String value = children.item(j).getNodeValue();
156           if (value != null)
157             buffer.append(value);
158         }
159         String description = buffer.toString().trim();
160
161         if (Keyword == null && Type == null && Function == null && Constant == null) {
162           //ignore as it is not a valid phpsyntax tag
163         } else {
164           if (Keyword != null) {
165             syntaxdata.add(new PHPKeyword(Keyword, usage, Tokenval));
166           } else if (Type != null) {
167             syntaxdata.add(new PHPType(Type, usage));
168           } else if (Function != null) {
169             syntaxdata.add(new PHPFunction(Function, usage, description));
170           } else if (Constant != null) {
171             syntaxdata.add(new PHPConstant(Constant, null, description));
172           }
173         }
174       }
175     } catch (ParserConfigurationException e) {
176       throwReadException(e);
177     } catch (IOException e) {
178       throwReadException(e);
179     } catch (SAXParseException e) {
180       System.out.println("SAXParseException in line:"+e.getLineNumber()+" column:"+e.getColumnNumber());
181       throwReadException(e);
182     } catch (SAXException e) {
183       throwReadException(e);
184     }
185   }
186
187   public static ArrayList getSyntaxData() {
188     if (syntaxdata == null) {
189       syntaxdata = new ArrayList();
190       readInSyntax();
191     }
192     return syntaxdata;
193   }
194
195   public static void replaceUserDefFile() {
196     /*Replace the user-defined syntax file if it exists*/
197     String buffer = new String(store.getString(IPreferenceConstants.PHP_USERDEF_XMLFILE));
198     if (!buffer.equals("") || buffer == null) {
199       readFromFile(buffer);
200     }
201   }
202
203   public static ArrayList getUserSyntaxData() {
204     return userdefsyntaxdata;
205   }
206
207   private static File getSyntaxFile() {
208     IPath path = PHPeclipsePlugin.getDefault().getStateLocation();
209     path = path.append(PHPSYNTAX_FILE);
210     return path.toFile();
211   }
212
213   private static String getAttributeValue(NamedNodeMap attributes, String name) {
214     Node node = attributes.getNamedItem(name);
215     return node == null ? null : node.getNodeValue();
216   }
217
218   public static void saveToFile(File file) throws CoreException {
219     OutputStream stream = null;
220     try {
221       stream = new FileOutputStream(file);
222       saveToStream(stream);
223     } catch (IOException e) {
224       throwWriteException(e);
225     } finally {
226       try {
227         if (stream != null)
228           stream.close();
229       } catch (IOException e) {
230       }
231     }
232   }
233
234   public static void saveToStream(OutputStream stream) throws CoreException {
235     try {
236       DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
237       DocumentBuilder builder = factory.newDocumentBuilder();
238       Document document = builder.newDocument();
239       Node root = document.createElement("PHPStandardSyntax"); // $NON-NLS-1$ //$NON-NLS-1$
240       document.appendChild(root);
241       for (int i = 0; i != syntaxdata.size(); i++) {
242         Object bufferobj = (Object) syntaxdata.get(i);
243         Attr name = null;
244         Node node = document.createElement(PHPSYNTAX_TAG); // $NON-NLS-1$ //$NON-NLS-1$
245         root.appendChild(node);
246         NamedNodeMap attributes = node.getAttributes();
247         if (bufferobj instanceof PHPType)
248           name = document.createAttribute(TYPE_ATTR);
249         if (bufferobj instanceof PHPKeyword)
250           name = document.createAttribute(KEYWORD_ATTR);
251         if (bufferobj instanceof PHPFunction)
252           name = document.createAttribute(FN_ATTR);
253         if (bufferobj instanceof PHPConstant)
254           name = document.createAttribute(CONSTANT_ATTR);
255         name.setValue(((PHPElement) bufferobj).getName());
256         attributes.setNamedItem(name);
257         Attr description = document.createAttribute(USAGE_ATTR);
258         description.setValue(((PHPElement) bufferobj).getUsage());
259         attributes.setNamedItem(description);
260         if (bufferobj instanceof PHPKeyword) {
261           Attr tokenval = document.createAttribute(TOKENVAL_ATTR);
262           tokenval.setValue((new Integer(((PHPKeyword) bufferobj).gettokenval())).toString());
263           attributes.setNamedItem(tokenval);
264         }
265         if (bufferobj instanceof PHPFunction) {
266           //      Attr usage = document.createAttribute(USAGE_ATTR);
267           Text usage = document.createTextNode(((PHPFunction) bufferobj).getDescription());
268           node.appendChild(usage);
269         }
270         if (bufferobj instanceof PHPConstant) {
271             //      Attr usage = document.createAttribute(USAGE_ATTR);
272             Text usage = document.createTextNode(((PHPConstant) bufferobj).getDescription());
273             node.appendChild(usage);
274           }
275       }
276       Transformer transformer=TransformerFactory.newInstance().newTransformer();
277                 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
278                 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
279                 DOMSource source = new DOMSource(document);
280                 StreamResult result = new StreamResult(stream);
281
282                 transformer.transform(source, result);
283
284         } catch (ParserConfigurationException e) {
285                 throwWriteException(e);
286         } catch (TransformerException e) {
287                 throwWriteException(e);
288         }               
289 //      OutputFormat format = new OutputFormat();
290 //      format.setPreserveSpace(true);
291 //      try {
292 //        Serializer serializer = SerializerFactory.getSerializerFactory("xml").makeSerializer(stream, format);
293 //        serializer.asDOMSerializer().serialize(document);
294 //      } catch (UnsupportedEncodingException e) {
295 //      } catch (IOException e) {
296 //      } //$NON-NLS-1$
297 //      //                      Serializer serializer = SerializerFactory.getSerializer().makeSerializer(stream, format); //$NON-NLS-1$
298 //    } catch (ParserConfigurationException e) {
299 //      throwWriteException(e);
300 //    }
301   }
302
303   private static void throwReadException(Throwable t) throws CoreException {
304     PHPeclipsePlugin.log(t);
305   }
306
307   private static void throwWriteException(Throwable t) throws CoreException {
308     PHPeclipsePlugin.log(t);
309   }
310
311 }