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.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 */
43public abstract class InterpreterProvider extends ContentProvider {
44
45  private static final int PROPERTIES = 1;
46  private static final int ENVIRONMENT_VARIABLES = 2;
47  private static final int ARGUMENTS = 3;
48
49  private UriMatcher mUriMatcher;
50  private SharedPreferences mPreferences;
51
52  private InterpreterDescriptor mDescriptor;
53  private Context mContext;
54
55  public static final String MIME = "vnd.android.cursor.item/vnd.googlecode.interpreter";
56
57  public InterpreterProvider() {
58    mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
59    String auth = this.getClass().getName().toLowerCase();
60    mUriMatcher.addURI(auth, InterpreterConstants.PROVIDER_PROPERTIES, PROPERTIES);
61    mUriMatcher.addURI(auth, InterpreterConstants.PROVIDER_ENVIRONMENT_VARIABLES,
62        ENVIRONMENT_VARIABLES);
63    mUriMatcher.addURI(auth, InterpreterConstants.PROVIDER_ARGUMENTS, ARGUMENTS);
64  }
65
66  /**
67   * Returns an instance of the class that implements the desired {@link InterpreterDescriptor}.
68   */
69  protected abstract InterpreterDescriptor getDescriptor();
70
71  @Override
72  public int delete(Uri uri, String selection, String[] selectionArgs) {
73    return 0;
74  }
75
76  @Override
77  public String getType(Uri uri) {
78    return MIME;
79  }
80
81  @Override
82  public Uri insert(Uri uri, ContentValues values) {
83    return null;
84  }
85
86  @Override
87  public boolean onCreate() {
88    mDescriptor = getDescriptor();
89    mContext = getContext();
90    mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
91    return false;
92  }
93
94  @Override
95  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
96      String sortOrder) {
97    if (!isInterpreterInstalled()) {
98      return null;
99    }
100    Map<String, String> map;
101    switch (mUriMatcher.match(uri)) {
102    case PROPERTIES:
103      map = getProperties();
104      break;
105    case ENVIRONMENT_VARIABLES:
106      map = getEnvironmentVariables();
107      break;
108    case ARGUMENTS:
109      map = getArguments();
110      break;
111    default:
112      map = null;
113    }
114    return buildCursorFromMap(map);
115  }
116
117  @Override
118  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
119    return 0;
120  }
121
122  private boolean isInterpreterInstalled() {
123    return mPreferences.getBoolean(InterpreterConstants.INSTALLED_PREFERENCE_KEY, false);
124  }
125
126  private Cursor buildCursorFromMap(Map<String, String> map) {
127    if (map == null) {
128      return null;
129    }
130    MatrixCursor cursor = new MatrixCursor(map.keySet().toArray(new String[map.size()]));
131    cursor.addRow(map.values());
132    return cursor;
133  }
134
135  private Map<String, String> getProperties() {
136    Map<String, String> values = new HashMap<String, String>();
137    values.put(InterpreterPropertyNames.NAME, mDescriptor.getName());
138    values.put(InterpreterPropertyNames.NICE_NAME, mDescriptor.getNiceName());
139    values.put(InterpreterPropertyNames.EXTENSION, mDescriptor.getExtension());
140    values.put(InterpreterPropertyNames.BINARY, mDescriptor.getBinary(mContext).getAbsolutePath());
141    values.put(InterpreterPropertyNames.INTERACTIVE_COMMAND, mDescriptor
142        .getInteractiveCommand(mContext));
143    values.put(InterpreterPropertyNames.SCRIPT_COMMAND, mDescriptor.getScriptCommand(mContext));
144    values.put(InterpreterPropertyNames.HAS_INTERACTIVE_MODE, Boolean.toString(mDescriptor
145        .hasInteractiveMode()));
146    return values;
147  }
148
149  private Map<String, String> getEnvironmentVariables() {
150    Map<String, String> values = new HashMap<String, String>();
151    values.putAll(mDescriptor.getEnvironmentVariables(mContext));
152    return values;
153  }
154
155  private Map<String, String> getArguments() {
156    Map<String, String> values = new LinkedHashMap<String, String>();
157    int column = 0;
158    for (String argument : mDescriptor.getArguments(mContext)) {
159      values.put(Integer.toString(column), argument);
160      column++;
161    }
162    return values;
163  }
164}
165