
atom.content.pm.DefaultPackageManager Maven / Gradle / Ivy
/*
* Copyright © 2015 Geeoz, and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Research Projects is dual-licensed under the GNU General Public
* License, version 2.0 (GPLv2) and the Geeoz Commercial License.
*
* Solely for non-commercial purposes. A purpose is non-commercial only if
* it is in no manner primarily intended for or directed toward commercial
* advantage or private monetary compensation.
*
* This Geeoz Software is supplied to you by Geeoz in consideration of your
* agreement to the following terms, and your use, installation, modification
* or redistribution of this Geeoz Software constitutes acceptance of these
* terms. If you do not agree with these terms, please do not use, install,
* modify or redistribute this Geeoz Software.
*
* Neither the name, trademarks, service marks or logos of Geeoz may be used
* to endorse or promote products derived from the Geeoz Software without
* specific prior written permission from Geeoz.
*
* The Geeoz Software is provided by Geeoz on an "AS IS" basis. GEEOZ MAKES NO
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, REGARDING THE GEEOZ SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
* COMBINATION WITH YOUR PRODUCTS.
*
* IN NO EVENT SHALL GEEOZ BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
* AND/OR DISTRIBUTION OF THE GEEOZ SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
* THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
* OTHERWISE, EVEN IF GEEOZ HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* A copy of the GNU General Public License is included in the distribution in
* the file LICENSE and at
*
* http://www.gnu.org/licenses/gpl-2.0.html
*
* If you are using the Research Projects for commercial purposes, we
* encourage you to visit
*
* http://products.geeoz.com/license
*
* for more details.
*
* This software or hardware and documentation may provide access to
* or information on content, products, and services from third parties.
* Geeoz and its affiliates are not responsible for and expressly disclaim
* all warranties of any kind with respect to third-party content, products,
* and services. Geeoz and its affiliates will not be responsible for any loss,
* costs, or damages incurred due to your access to or use of third-party
* content, products, or services. If a third-party content exists, the
* additional copyright notices and license terms applicable to portions of the
* software are set forth in the THIRD_PARTY_LICENSE_README file.
*
* Please contact Geeoz or visit www.geeoz.com if you need additional
* information or have any questions.
*/
package atom.content.pm;
import atom.app.AuditEvent;
import atom.app.AuditManager;
import atom.content.ComponentId;
import atom.content.Context;
import atom.content.Intent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Class for retrieving various kinds of information related to the application
* packages that are currently installed inside the system.
*
* @author Alex Voloshyn
* @author Serge Voloshyn
* @version 1.15 1/27/15
*/
public final class DefaultPackageManager implements PackageManager {
/**
* Application packages registry with package name key and package info
* value.
*/
private static final Map REGISTRY = new HashMap<>();
/**
* Audit manager service.
*/
private static final AuditManager AUDIT =
Context.getSystemService(AuditManager.class);
@Override
public PackageInfo find(final String packageName) {
final PackageIndex index = REGISTRY.get(packageName);
if (index == null) {
return null;
} else {
return index.packageInfo;
}
}
@Override
public void register(final PackageInfo packageInfo) {
initialPackageVerification(packageInfo);
final PackageIndex index = new PackageIndex(packageInfo);
AUDIT.log(AuditEvent.create(this, AuditEvent.SYSTEM, AuditEvent.CONFIG,
"Register package: {0}", packageInfo.getName()));
packageInfo.getActivities().forEach(index::addActivity);
REGISTRY.put(packageInfo.getName(), index);
}
@Override
public void unregister(final PackageInfo packageInfo) {
initialPackageVerification(packageInfo);
AUDIT.log(AuditEvent.create(this, AuditEvent.SYSTEM, AuditEvent.CONFIG,
"Un-register package: {0}", packageInfo.getName()));
REGISTRY.remove(packageInfo.getName());
}
@Override
public List resolveActivity(final Intent intent) {
checkIntent(intent);
final List infos;
if (intent.getComponentId() == null) {
infos = new ArrayList<>();
final boolean[] check
= new boolean[Intent.LAYER_MAX_COUNT];
REGISTRY.values()
.forEach(index -> index.activities.keySet()
.stream()
.filter(filter -> filter.match(intent))
.forEach(filter -> merge(
check,
infos,
index.activities.get(filter))));
} else {
infos = new ArrayList<>(1);
final ComponentId componentId = intent.getComponentId();
final PackageIndex index =
REGISTRY.get(componentId.getPackageName());
if (ComponentId.EMPTY_LAYER == componentId.getLayer()) {
infos.add(index.classNames.get(componentId.getClassName()));
} else {
final ActivityInfo origin =
index.classNames.get(componentId.getClassName());
final ActivityInfo copy = new ActivityInfo();
copy.setPackageInfo(origin.getPackageInfo());
copy.setClassName(origin.getClassName());
copy.setLayer(componentId.getLayer());
infos.add(copy);
}
}
if (AUDIT.isLoggable(AuditEvent.FINE)) {
AUDIT.log(AuditEvent.create(
this, AuditEvent.SYSTEM, AuditEvent.FINE,
"Resolve activity for - action: {0}, categories: {1}",
intent.getAction(), intent.getCategories()));
}
return infos;
}
/**
* Check an intent for existing.
*
* @param intent an intent containing all of the desired specification
* (action, data, type, category, and/or component)
*/
private void checkIntent(final Intent intent) {
if (intent == null) {
throw new IllegalArgumentException(
String.format(MSG_TMPL_EMPTY, "Input intent"));
}
}
/**
* Add all elements of the second activity infos to the first one.
*
* @param check an array with filling list
* @param infos array that should be updated
* @param collection collection containing elements to be added to this list
*/
private void merge(final boolean[] check,
final List infos,
final List collection) {
if (infos == null || collection == null) {
return;
}
for (ActivityInfo info : collection) {
if (check[info.getLayer()]) {
throw new IllegalStateException(MSG_LAYER_CONCURRENCY);
}
infos.add(info);
check[info.getLayer()] = true;
}
}
/**
* Provide initial package integrity verification.
*
* @param packageInfo package for verification
*/
private void initialPackageVerification(final PackageInfo packageInfo) {
if (packageInfo == null) {
throw new IllegalArgumentException(
String.format(MSG_TMPL_EMPTY, "Application package"));
} else if (packageInfo.getName() == null
|| packageInfo.getName().trim().isEmpty()) {
throw new IllegalArgumentException(
String.format(MSG_TMPL_EMPTY, "Application package name"));
}
}
/**
* Class that provide fast access to package content.
*/
private static final class PackageIndex {
/**
* Source package for the index.
*/
private final transient PackageInfo packageInfo;
/**
* Activity index for the class name key.
*/
private final transient Map classNames =
new HashMap<>();
/**
* Activity index for the PackageIndex.
*/
private final transient Map>
activities = new HashMap<>();
/**
* Base constructor.
*
* @param aPackageInfo a package for index
*/
public PackageIndex(final PackageInfo aPackageInfo) {
packageInfo = aPackageInfo;
}
/**
* Add activity info for indexing.
*
* @param info activity info entity
*/
public void addActivity(final ActivityInfo info) {
classNames.put(info.getClassName().getName(), info);
for (IntentFilter filter : info.getIntentFilters()) {
List list = activities.get(filter);
if (list == null) {
list = new ArrayList<>();
activities.put(filter, list);
}
list.add(info);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy