1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/org/documents/epl-v10.php
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ide.eclipse.adt.internal.project;
18 
19 import com.android.ide.common.xml.AndroidManifestParser.ManifestErrorHandler;
20 import com.android.ide.eclipse.adt.AdtConstants;
21 
22 import org.eclipse.core.resources.IFile;
23 import org.eclipse.core.resources.IMarker;
24 import org.eclipse.core.runtime.CoreException;
25 import org.eclipse.jdt.core.IJavaProject;
26 import org.xml.sax.Locator;
27 import org.xml.sax.SAXException;
28 import org.xml.sax.SAXParseException;
29 import org.xml.sax.helpers.DefaultHandler;
30 
31 /**
32  * XML error handler used by the parser to report errors/warnings.
33  */
34 public class XmlErrorHandler extends DefaultHandler implements ManifestErrorHandler {
35 
36     private final IJavaProject mJavaProject;
37     /** file being parsed */
38     private final IFile mFile;
39     /** link to the delta visitor, to set the xml error flag */
40     private final XmlErrorListener mErrorListener;
41 
42     /**
43      * Classes which implement this interface provide a method that deals
44      * with XML errors.
45      */
46     public interface XmlErrorListener {
47         /**
48          * Sent when an XML error is detected.
49          */
errorFound()50         public void errorFound();
51     }
52 
53     public static class BasicXmlErrorListener implements XmlErrorListener {
54         public boolean mHasXmlError = false;
55 
56         @Override
errorFound()57         public void errorFound() {
58             mHasXmlError = true;
59         }
60     }
61 
XmlErrorHandler(IJavaProject javaProject, IFile file, XmlErrorListener errorListener)62     public XmlErrorHandler(IJavaProject javaProject, IFile file, XmlErrorListener errorListener) {
63         mJavaProject = javaProject;
64         mFile = file;
65         mErrorListener = errorListener;
66     }
67 
XmlErrorHandler(IFile file, XmlErrorListener errorListener)68     public XmlErrorHandler(IFile file, XmlErrorListener errorListener) {
69         this(null, file, errorListener);
70     }
71 
72     /**
73      * Xml Error call back
74      * @param exception the parsing exception
75      * @throws SAXException
76      */
77     @Override
error(SAXParseException exception)78     public void error(SAXParseException exception) throws SAXException {
79         handleError(exception, exception.getLineNumber());
80     }
81 
82     /**
83      * Xml Fatal Error call back
84      * @param exception the parsing exception
85      * @throws SAXException
86      */
87     @Override
fatalError(SAXParseException exception)88     public void fatalError(SAXParseException exception) throws SAXException {
89         handleError(exception, exception.getLineNumber());
90     }
91 
92     /**
93      * Xml Warning call back
94      * @param exception the parsing exception
95      * @throws SAXException
96      */
97     @Override
warning(SAXParseException exception)98     public void warning(SAXParseException exception) throws SAXException {
99         if (mFile != null) {
100             BaseProjectHelper.markResource(mFile,
101                     AdtConstants.MARKER_XML,
102                     exception.getMessage(),
103                     exception.getLineNumber(),
104                     IMarker.SEVERITY_WARNING);
105         }
106     }
107 
getFile()108     protected final IFile getFile() {
109         return mFile;
110     }
111 
112     /**
113      * Handles a parsing error and an optional line number.
114      * @param exception
115      * @param lineNumber
116      */
117     @Override
handleError(Exception exception, int lineNumber)118     public void handleError(Exception exception, int lineNumber) {
119         if (mErrorListener != null) {
120             mErrorListener.errorFound();
121         }
122 
123         String message = exception.getMessage();
124         if (message == null) {
125             message = "Unknown error " + exception.getClass().getCanonicalName();
126         }
127 
128         if (mFile != null) {
129             BaseProjectHelper.markResource(mFile,
130                     AdtConstants.MARKER_XML,
131                     message,
132                     lineNumber,
133                     IMarker.SEVERITY_ERROR);
134         }
135     }
136 
137     /**
138      * Checks that a class is valid and can be used in the Android Manifest.
139      * <p/>
140      * Errors are put as {@link IMarker} on the manifest file.
141      * @param locator
142      * @param className the fully qualified name of the class to test.
143      * @param superClassName the fully qualified name of the class it is supposed to extend.
144      * @param testVisibility if <code>true</code>, the method will check the visibility of
145      * the class or of its constructors.
146      */
147     @Override
checkClass(Locator locator, String className, String superClassName, boolean testVisibility)148     public void checkClass(Locator locator, String className, String superClassName,
149             boolean testVisibility) {
150         if (mJavaProject == null) {
151             return;
152         }
153         // we need to check the validity of the activity.
154         String result = BaseProjectHelper.testClassForManifest(mJavaProject,
155                 className, superClassName, testVisibility);
156         if (result != BaseProjectHelper.TEST_CLASS_OK) {
157             // get the line number
158             int line = locator.getLineNumber();
159 
160             // mark the file
161             IMarker marker = BaseProjectHelper.markResource(getFile(),
162                     AdtConstants.MARKER_ANDROID, result, line, IMarker.SEVERITY_ERROR);
163 
164             // add custom attributes to be used by the manifest editor.
165             if (marker != null) {
166                 try {
167                     marker.setAttribute(AdtConstants.MARKER_ATTR_TYPE,
168                             AdtConstants.MARKER_ATTR_TYPE_ACTIVITY);
169                     marker.setAttribute(AdtConstants.MARKER_ATTR_CLASS, className);
170                 } catch (CoreException e) {
171                 }
172             }
173         }
174     }
175 }
176