1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.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.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,
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
17package com.googlecode.android_scripting;
18
19import com.googlecode.android_scripting.interpreter.Interpreter;
20import com.googlecode.android_scripting.interpreter.InterpreterConfiguration;
21import com.googlecode.android_scripting.interpreter.InterpreterConstants;
22
23import java.io.BufferedWriter;
24import java.io.File;
25import java.io.FileWriter;
26import java.io.IOException;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.Collections;
30import java.util.Comparator;
31import java.util.Iterator;
32import java.util.LinkedList;
33import java.util.List;
34
35/**
36 * Manages storage and retrieval of scripts on the file system.
37 *
38 */
39public class ScriptStorageAdapter {
40
41  private ScriptStorageAdapter() {
42    // Utility class.
43  }
44
45  /**
46   * Writes data to the script by name and overwrites any existing data.
47   */
48  public static void writeScript(File script, String data) {
49    if (script.getParent() == null) {
50      script = new File(InterpreterConstants.SCRIPTS_ROOT, script.getPath());
51    }
52    try {
53      FileWriter stream = new FileWriter(script, false /* overwrite */);
54      BufferedWriter out = new BufferedWriter(stream);
55      out.write(data);
56      out.close();
57    } catch (IOException e) {
58      Log.e("Failed to write script.", e);
59    }
60  }
61
62  /**
63   * Returns a list of all available script {@link File}s.
64   */
65  public static List<File> listAllScripts(File dir) {
66    if (dir == null) {
67      dir = new File(InterpreterConstants.SCRIPTS_ROOT);
68    }
69    if (dir.exists()) {
70      List<File> scripts = Arrays.asList(dir.listFiles());
71      Collections.sort(scripts, new Comparator<File>() {
72        @Override
73        public int compare(File file1, File file2) {
74          if (file1.isDirectory() && !file2.isDirectory()) {
75            return -1;
76          } else if (!file1.isDirectory() && file2.isDirectory()) {
77            return 1;
78          }
79          return file1.compareTo(file2);
80        }
81      });
82      return scripts;
83    }
84    return new ArrayList<File>();
85  }
86
87  /**
88   * Returns a list of script {@link File}s from the given folder for which there is an interpreter
89   * installed.
90   */
91  public static List<File> listExecutableScripts(File directory, InterpreterConfiguration config) {
92    // NOTE(damonkohler): Creating a LinkedList here is necessary in order to be able to filter it
93    // later.
94    List<File> scripts = new LinkedList<File>(listAllScripts(directory));
95    // Filter out any files that don't have interpreters installed.
96    for (Iterator<File> it = scripts.iterator(); it.hasNext();) {
97      File script = it.next();
98      if (script.isDirectory()) {
99        continue;
100      }
101      Interpreter interpreter = config.getInterpreterForScript(script.getName());
102      if (interpreter == null || !interpreter.isInstalled()) {
103        it.remove();
104      }
105    }
106    return scripts;
107  }
108
109  /**
110   * Returns a list of all (including subfolders) script {@link File}s for which there is an
111   * interpreter installed.
112   */
113  public static List<File> listExecutableScriptsRecursively(File directory,
114      InterpreterConfiguration config) {
115    // NOTE(damonkohler): Creating a LinkedList here is necessary in order to be able to filter it
116    // later.
117    List<File> scripts = new LinkedList<File>();
118    List<File> files = listAllScripts(directory);
119
120    // Filter out any files that don't have interpreters installed.
121    for (Iterator<File> it = files.iterator(); it.hasNext();) {
122      File file = it.next();
123      if (file.isDirectory()) {
124        scripts.addAll(listExecutableScriptsRecursively(file, config));
125      }
126      Interpreter interpreter = config.getInterpreterForScript(file.getName());
127      if (interpreter != null && interpreter.isInstalled()) {
128        scripts.add(file);
129      }
130    }
131    Collections.sort(scripts);
132    return scripts;
133  }
134}