Java tutorial
/* This file was modified from or inspired by Apache Cordova. Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.polyvi.xface.extension; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.json.JSONArray; import org.json.JSONException; import com.polyvi.xface.core.XConfiguration; import com.polyvi.xface.core.XRuntime; import com.polyvi.xface.extension.XExtensionResult.Status; import com.polyvi.xface.plugin.api.XIWebContext; import com.polyvi.xface.util.XLog; import com.umeng.analytics.MobclickAgent; /** * ? ?js??? * */ public class XExtensionManager { private static final String CLASS_NAME = XExtensionManager.class.getSimpleName(); private static final String EMPTY_STRING = ""; private static final int THREAD_POOL_TERMINATION_TIMEOUT = 500; private final ExecutorService mExecThreadPool = Executors.newCachedThreadPool(); /** * */ private HashMap<String, XExtension> mExtensionMap; private XExtensionContext mExtensionContext; private XIWebContext mWebContext; public XExtensionManager(XIWebContext webContext, XExtensionContext extensionContext) { mExtensionMap = new HashMap<String, XExtension>(); mExtensionContext = extensionContext; mWebContext = webContext; } /** * ? * @param service ??? * @param action * @param callbackId id js? * @param arguments ? * @return ?? */ public boolean exec(String service, final String action, String callbackId, String arguments) { final XExtension extension = mExtensionMap.get(service); if (null == extension) { XLog.e(CLASS_NAME, "%s not registered!", service); XExtensionResult er = new XExtensionResult(XExtensionResult.Status.CLASS_NOT_FOUND_EXCEPTION); mWebContext.sendExtensionResult(er, callbackId); return true; } try { JSONArray args = new JSONArray(arguments); final XCallbackContext callbackCtx = new XCallbackContext(mWebContext, callbackId); exec(extension, action, args, callbackCtx); return callbackCtx.isFinished(); } catch (JSONException e) { XExtensionResult er = new XExtensionResult(XExtensionResult.Status.JSON_EXCEPTION); mWebContext.sendExtensionResult(er, callbackId); return true; } } private String exec(final XExtension extension, final String action, final JSONArray args, final XCallbackContext ctx) { XExtensionResult result = null; try { boolean runAync = extension.isAsync(action); if (runAync) { mExecThreadPool.execute(new Runnable() { public void run() { XExtensionResult result; try { result = extension.exec(action, args, ctx); } catch (JSONException e) { result = new XExtensionResult(XExtensionResult.Status.ERROR, e.getMessage()); XLog.d(CLASS_NAME, e.getMessage()); } catch (Exception e) { result = new XExtensionResult(XExtensionResult.Status.ERROR, e.getMessage()); XLog.d(CLASS_NAME, e.getMessage()); e.printStackTrace(); // ???? reportError(e); } if (Status.NO_RESULT.ordinal() != result.getStatus()) { ctx.sendExtensionResult(result); } } }); return EMPTY_STRING; } else { // ?? result = extension.exec(action, args, ctx); if (Status.NO_RESULT.ordinal() == result.getStatus()) { return EMPTY_STRING; } } } catch (JSONException e) { result = new XExtensionResult(XExtensionResult.Status.ERROR, e.getMessage()); XLog.d(CLASS_NAME, e.getMessage()); } catch (Exception e) { XLog.d(CLASS_NAME, e.getMessage()); e.printStackTrace(); // ???? reportError(e); } if (null != result) { ctx.sendExtensionResult(result); } return EMPTY_STRING; } /** * amsams{@link XRuntime}?XExtensionManager * * @param ams * ams */ public void registerExtension(String extName, XExtension extension) { mExtensionMap.put(extName, extension); } private XExtension createExtension(String className) { try { Class<?> cls = Class.forName(className); Object obj = cls.newInstance(); if (!(obj instanceof XExtension)) { XLog.e(CLASS_NAME, "Class (" + className + ") not a sub class of XExtension!"); return null; } XExtension extension = (XExtension) obj; extension.init(mExtensionContext, mWebContext); return extension; } catch (ClassNotFoundException e) { XLog.e(CLASS_NAME, "Class:" + className + " not found!"); } catch (InstantiationException e) { XLog.e(CLASS_NAME, "Can't create object of class " + className); } catch (IllegalAccessException e) { XLog.e(CLASS_NAME, "Can't create object of class " + className); } return null; } /** * */ public void loadExtensions() { HashMap<String, XExtensionEntry> loadingExtensions = XConfiguration.getInstance() .readLoadingExtensions(mExtensionContext); Iterator<Entry<String, XExtensionEntry>> iter = loadingExtensions.entrySet().iterator(); while (iter.hasNext()) { Entry<String, XExtensionEntry> entry = iter.next(); String extName = entry.getKey(); String className = entry.getValue().getExtClassName(); XExtension ext = createExtension(className); if (null == ext) { continue; } registerExtension(extName, ext); } } public void destroy() { Iterator<Entry<String, XExtension>> extensionIterator = mExtensionMap.entrySet().iterator(); while (extensionIterator.hasNext()) { HashMap.Entry<String, XExtension> entry = (HashMap.Entry<String, XExtension>) extensionIterator.next(); XExtension extension = (XExtension) entry.getValue(); extension.destroy(); } shutdownAndAwaitTermination(mExecThreadPool); } /** * */ private void shutdownAndAwaitTermination(ExecutorService pool) { pool.shutdown(); // Disable new tasks from being submitted try { // Wait a while for existing tasks to terminate if (!pool.awaitTermination(THREAD_POOL_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) { pool.shutdownNow(); // Cancel currently executing tasks // Wait a while for tasks to respond to being cancelled if (!pool.awaitTermination(THREAD_POOL_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) { XLog.d(CLASS_NAME, "Thread Pool did not terminate"); } } } catch (InterruptedException ie) { // (Re-)Cancel if current thread also interrupted pool.shutdownNow(); // Preserve interrupt status Thread.currentThread().interrupt(); } } /** * ??? ext */ public void onPageStarted() { Iterator<XExtension> extensionIterator = mExtensionMap.values().iterator(); while (extensionIterator.hasNext()) { extensionIterator.next().onPageStarted(); } } /** * app? ext */ public void onAppClosed() { Iterator<XExtension> extensionIterator = mExtensionMap.values().iterator(); while (extensionIterator.hasNext()) { extensionIterator.next().onAppClosed(); } } /** * ?app? ext */ public void onAppUninstalled() { Iterator<XExtension> extensionIterator = mExtensionMap.values().iterator(); while (extensionIterator.hasNext()) { extensionIterator.next().onAppUninstalled(); } } /** * app???ext * * @param appId */ public void onPause() { Iterator<XExtension> extensionIterator = mExtensionMap.values().iterator(); while (extensionIterator.hasNext()) { extensionIterator.next().onPause(); } } /** * app????ext * * @param appId */ public void onResume() { Iterator<XExtension> extensionIterator = mExtensionMap.values().iterator(); while (extensionIterator.hasNext()) { extensionIterator.next().onResume(); } } public XExtensionContext getExtensionContext() { return mExtensionContext; } /** * ???umeng? * * @param e */ public void reportError(Exception e) { try { // ?Writer Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); e.printStackTrace(printWriter); printWriter.flush(); writer.flush(); String stackTrackInfo = writer.toString(); printWriter.close(); writer.close(); MobclickAgent.reportError(mExtensionContext.getSystemContext().getContext(), stackTrackInfo); } catch (IOException ioE) { XLog.e(CLASS_NAME, ioE.getMessage()); } catch (Exception genericE) { XLog.e(CLASS_NAME, genericE.getMessage()); } } }