1/*
2 * Copyright (C) 2016 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.googlecode.android_scripting.interpreter;
18
19import android.content.ContentProvider;
20import android.content.ContentValues;
21import android.content.Context;
22import android.content.SharedPreferences;
23import android.content.UriMatcher;
24import android.database.Cursor;
25import android.database.MatrixCursor;
26import android.net.Uri;
27import android.preference.PreferenceManager;
28
29import java.util.HashMap;
30import java.util.LinkedHashMap;
31import java.util.Map;
32
33/**
34 * A provider that can be queried to obtain execution-related interpreter info.
35 *
36 * <p>
37 * To create an interpreter APK, please extend this content provider and implement getDescriptor()
38 * and getEnvironmentSettings().<br>
39 * Please declare the provider in the android manifest xml (the authority values has to be set to
40 * your_package_name.provider_name).
41 *
42 * @author Alexey Reznichenko (alexey.reznichenko@gmail.com)
43 */
44public abstract class InterpreterProvider extends ContentProvider {
45
46  private static final int PROPERTIES = 1;
47  private static final int ENVIRONMENT_VARIABLES = 2;
48  private static final int ARGUMENTS = 3;
49
50  private UriMatcher mUriMatcher;
51  private SharedPreferences mPreferences;
52
53  private InterpreterDescriptor mDescriptor;
54  private Context mContext;
55
56  public static final String MIME = "vnd.android.cursor.item/vnd.googlecode.interpreter";
57
58  public InterpreterProvider() {
59    mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
60    String auth = this.getClass().getName().toLowerCase();
61    mUriMatcher.addURI(auth, InterpreterConstants.PROVIDER_PROPERTIES, PROPERTIES);
62    mUriMatcher.addURI(auth, InterpreterConstants.PROVIDER_ENVIRONMENT_VARIABLES,
63        ENVIRONMENT_VARIABLES);
64    mUriMatcher.addURI(auth, InterpreterConstants.PROVIDER_ARGUMENTS, ARGUMENTS);
65  }
66
67  /**
68   * Returns an instance of the class that implements the desired {@link InterpreterDescriptor}.
69   */
70  protected abstract InterpreterDescriptor getDescriptor();
71
72  @Override
73  public int delete(Uri uri, String selection, String[] selectionArgs) {
74    return 0;
75  }
76
77  @Override
78  public String getType(Uri uri) {
79    return MIME;
80  }
81
82  @Override
83  public Uri insert(Uri uri, ContentValues values) {
84    return null;
85  }
86
87  @Override
88  public boolean onCreate() {
89    mDescriptor = getDescriptor();
90    mContext = getContext();
91    mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
92    return false;
93  }
94
95  @Override
96  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
97      String sortOrder) {
98    if (!isInterpreterInstalled()) {
99      return null;
100    }
101    Map<String, String> map;
102    switch (mUriMatcher.match(uri)) {
103    case PROPERTIES:
104      map = getProperties();
105      break;
106    case ENVIRONMENT_VARIABLES:
107      map = getEnvironmentVariables();
108      break;
109    case ARGUMENTS:
110      map = getArguments();
111      break;
112    default:
113      map = null;
114    }
115    return buildCursorFromMap(map);
116  }
117
118  @Override
119  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
120    return 0;
121  }
122
123  private boolean isInterpreterInstalled() {
124    return mPreferences.getBoolean(InterpreterConstants.INSTALLED_PREFERENCE_KEY, false);
125  }
126
127  private Cursor buildCursorFromMap(Map<String, String> map) {
128    if (map == null) {
129      return null;
130    }
131    MatrixCursor cursor = new MatrixCursor(map.keySet().toArray(new String[map.size()]));
132    cursor.addRow(map.values());
133    return cursor;
134  }
135
136  private Map<String, String> getProperties() {
137    Map<String, String> values = new HashMap<String, String>();
138    values.put(InterpreterPropertyNames.NAME, mDescriptor.getName());
139    values.put(InterpreterPropertyNames.NICE_NAME, mDescriptor.getNiceName());
140    values.put(InterpreterPropertyNames.EXTENSION, mDescriptor.getExtension());
141    values.put(InterpreterPropertyNames.BINARY, mDescriptor.getBinary(mContext).getAbsolutePath());
142    values.put(InterpreterPropertyNames.INTERACTIVE_COMMAND, mDescriptor
143        .getInteractiveCommand(mContext));
144    values.put(InterpreterPropertyNames.SCRIPT_COMMAND, mDescriptor.getScriptCommand(mContext));
145    values.put(InterpreterPropertyNames.HAS_INTERACTIVE_MODE, Boolean.toString(mDescriptor
146        .hasInteractiveMode()));
147    return values;
148  }
149
150  private Map<String, String> getEnvironmentVariables() {
151    Map<String, String> values = new HashMap<String, String>();
152    values.putAll(mDescriptor.getEnvironmentVariables(mContext));
153    return values;
154  }
155
156  private Map<String, String> getArguments() {
157    Map<String, String> values = new LinkedHashMap<String, String>();
158    int column = 0;
159    for (String argument : mDescriptor.getArguments(mContext)) {
160      values.put(Integer.toString(column), argument);
161      column++;
162    }
163    return values;
164  }
165}
166