PageRenderTime 23ms CodeModel.GetById 12ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/AccessCheck/src/com/android/accessibility/AccessibilityValidator.java

http://eyes-free.googlecode.com/
Java | 191 lines | 105 code | 17 blank | 69 comment | 14 complexity | 47cef111989a52b583da0180afb2b051 MD5 | raw file
  1/*
  2 * Copyright 2010 Google Inc.
  3 *
  4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5 * use this file except in compliance with the License. You may obtain a copy of
  6 * the License at
  7 *
  8 * http://www.apache.org/licenses/LICENSE-2.0
  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, WITHOUT
 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 13 * License for the specific language governing permissions and limitations under
 14 * the License.
 15 */
 16
 17package com.android.accessibility;
 18
 19import org.xml.sax.InputSource;
 20import org.xml.sax.SAXException;
 21import org.xml.sax.XMLReader;
 22import org.xml.sax.helpers.XMLReaderFactory;
 23
 24import java.io.*;
 25import java.util.ArrayList;
 26import java.util.List;
 27import java.util.logging.Logger;
 28
 29/**
 30 * An object that fetches all Android layout files and manages the testing of
 31 * the files with the use of the AccessibilityValidationContentHandler. This
 32 * object also reports on any errors encountered during the testing.
 33 *
 34 * @author dtseng@google.com (David Tseng)
 35 */
 36public class AccessibilityValidator {
 37    /** The root path to scan for Android layout files. */
 38    private final File mRootFilePath;
 39    /** Errors generated by thrown exceptions (and not by validation errors). */
 40    private final List<String> mGeneralErrors = new ArrayList<String>();
 41    /** A list of files we wish to have tested. */
 42    private List<InputSource> mLayoutFiles;
 43    /** The total number of validation test errors across all files. */
 44    private int mTotalValidationErrors = 0;
 45    /** The path to the Android sdk jar. */
 46    private final File mAndroidSdkPath;
 47
 48    /** The object that handles our logging. */
 49    private static final Logger sLogger = Logger.getLogger("android.accessibility");
 50
 51    /**
 52     * The entry point to this tool.
 53     * 
 54     * @param <args>
 55     *            path on which to search for layout xml files that need
 56     *            validation
 57     */
 58    public static void main(String[] args) {
 59        sLogger.info("AccessibilityValidator");
 60        if (args.length == 2) {
 61            sLogger.info("Validating classes using android jar for subclasses of ImageView");
 62            new AccessibilityValidator(args[0], args[1]).run();
 63        } else {
 64            sLogger.info("Usage: java AccessibilityValidator <path> <Android jar path>");
 65            return;
 66        }
 67    }
 68
 69    /**
 70     * Constructs an AccessibilityValidator object using the root path and the
 71     * android jar path.
 72     */
 73    public AccessibilityValidator(String rootPath, String androidSdkPath) {
 74        mRootFilePath = new File(rootPath);
 75        mAndroidSdkPath = new File(androidSdkPath);
 76
 77        if (!mRootFilePath.exists()) {
 78            throw new IllegalArgumentException("Invalid root path specified "
 79                    + rootPath);
 80        } else if (!mAndroidSdkPath.exists()) {
 81            throw new IllegalArgumentException(
 82                    "Invalid android sdk path specified " + androidSdkPath);
 83        }
 84    }
 85
 86    /**
 87     * Performs validation of Android layout files and logs errors that have
 88     * been encountered during the validation. Returns true if the validation
 89     * passes.
 90     */
 91    private boolean run() {
 92        sLogger.info("Validating files under " + mRootFilePath);
 93        mLayoutFiles = findLayoutFiles(mRootFilePath);
 94        validateFiles();
 95        for (String error : mGeneralErrors) {
 96            sLogger.info(error);
 97        }
 98        sLogger.info("done with validation");
 99        return mGeneralErrors.size() == 0;
100    }
101
102    /**
103     * Accumulates a list of files under the path that meet two constraints.
104     * Firstly, it has a containing (parent) directory of "layout". Secondly, it
105     * has an xml extension
106     */
107    private List<InputSource> findLayoutFiles(File directory) {
108        List<InputSource> layoutFiles = new ArrayList<InputSource>();
109
110        for (File file : directory.listFiles()) {
111            // The file is a directory; recurse on the file.
112            if (file.isDirectory()) {
113                List<InputSource> directoryFiles = findLayoutFiles(file);
114                layoutFiles.addAll(directoryFiles);
115                // Does the containing directory and filename meet our
116                // constraints?
117            } else if (directory.getName().toLowerCase().contains("layout")
118                    && file.getName().toLowerCase().endsWith(".xml")) {
119                InputSource addition;
120                try {
121                    addition = new InputSource(new FileReader(file));
122                    // Store this explicitly for logging.
123                    addition.setPublicId(file.toString());
124                    layoutFiles.add(addition);
125                } catch (FileNotFoundException fileNotFoundException) {
126                    mGeneralErrors.add("File not found "
127                            + fileNotFoundException);
128                }
129            }
130        }
131
132        return layoutFiles;
133    }
134
135    /*
136     * Processes a list of files via an AccessibilityValidationContentHandler.
137     * The caller will only be notified of errors via logging.
138     */
139    public void validateFiles() {
140        sLogger.info("Validating " + getLayoutFiles().size());
141        XMLReader reader;
142        try {
143            reader = XMLReaderFactory.createXMLReader();
144        } catch (SAXException saxExp) {
145            mGeneralErrors.add("Error " + saxExp);
146            return;
147        }
148        for (InputSource file : getLayoutFiles()) {
149            try {
150                AccessibilityValidationContentHandler contentHandler
151                = new AccessibilityValidationContentHandler(
152                        file.getPublicId(), mAndroidSdkPath);
153                reader.setContentHandler(contentHandler);
154                reader.parse(file);
155                mTotalValidationErrors += contentHandler.getValidationErrors();
156            } catch (IOException ioExp) {
157                mGeneralErrors.add("Error reading file " + ioExp);
158            } catch (SAXException saxExp) {
159                mGeneralErrors.add("Error " + saxExp);
160            }
161        }
162    }
163
164    /**
165     * Returns the number of general errors (considered caught exceptions).
166     */
167    public List<String> getGeneralErrors() {
168        return mGeneralErrors;
169    }
170
171    /**
172     * Sets the files to be tested.
173     */
174    public void setLayoutFiles(List<InputSource> layoutFiles) {
175        this.mLayoutFiles = layoutFiles;
176    }
177
178    /**
179     * Gets the files to be tested.
180     */
181    public List<InputSource> getLayoutFiles() {
182        return mLayoutFiles;
183    }
184
185    /**
186     * Gets the total number of test validation errors across all files.
187     */
188    public int getTotalValidationErrors() {
189        return mTotalValidationErrors;
190    }
191}