/* Copyright 2017 Google Inc. * * Licensed 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. * 2019.12.15-Changed constructor HuaweiApp * 2019.12.15-Changed method initializeApp * Huawei Technologies Co., Ltd. * */ package com.huawei.push.messaging; import com.google.common.collect.ImmutableList; import com.huawei.push.util.ValidatorUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.text.MessageFormat; import java.util.*; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** * The entry point of Huawei Java SDK. *
{@link HuaweiApp#initializeApp(HuaweiOption)} initializes the app instance.
*/
public class HuaweiApp {
private static final Logger logger = LoggerFactory.getLogger(HuaweiApp.class);
private String appId;
private HuaweiOption option;
/** Global lock */
private static final Object appsLock = new Object();
/** Store a map of A no-op if delete was called before.
*/
public void delete() {
synchronized (lock) {
boolean valueChanged = deleted.compareAndSet(false /* expected */, true);
if (!valueChanged) {
return;
}
try {
this.getOption().getHttpClient().close();
this.getOption().getCredential().getHttpClient().close();
} catch (IOException e) {
logger.debug("Fail to close httpClient");
}
for (HuaweiService service : services.values()) {
service.destroy();
}
services.clear();
tokenRefresher.stop();
threadManager.releaseHuaweiExecutors(this, executors);
if (scheduledExecutor != null) {
scheduledExecutor.shutdown();
scheduledExecutor = null;
}
}
synchronized (appsLock) {
instances.remove(this.getAppId());
}
}
/**
* Check the app is not deleted, whcic is the premisi of some methods
*/
private void checkNotDeleted() {
String errorMessage = MessageFormat.format("HuaweiApp with id {0} was deleted", getAppId());
ValidatorUtils.checkState(!deleted.get(), errorMessage);
}
/**
* Singleton mode, ensure the scheduleExecutor is singleton
*/
private ScheduledExecutorService singleScheduledExecutorService() {
if (scheduledExecutor == null) {
synchronized (lock) {
checkNotDeleted();
if (scheduledExecutor == null) {
scheduledExecutor = new HuaweiScheduledExecutor(getThreadFactory(), "huawei-scheduled-worker");
}
}
}
return scheduledExecutor;
}
public ThreadFactory getThreadFactory() {
return threadManager.getThreadFactory();
}
private ScheduledExecutorService getScheduledExecutorService() {
return singleScheduledExecutorService();
}
ScheduledFuture> schedule(Runnable runnable, long initialDelay, long period) {
return getScheduledExecutorService().scheduleWithFixedDelay(runnable, initialDelay, period, TimeUnit.MILLISECONDS);
}
/**
* Add service to the app, such as HuaweiMessaging, other services can be added if needed
*/
void addService(HuaweiService service) {
synchronized (lock) {
checkNotDeleted();
ValidatorUtils.checkArgument(!services.containsKey(service.getId()), "service already exists");
services.put(service.getId(), service);
}
}
HuaweiService getService(String id) {
synchronized (lock) {
return services.get(id);
}
}
/**
* Start the scheduled task for refreshing token automatically
*/
public void startTokenRefresher() {
synchronized (lock) {
checkNotDeleted();
tokenRefresher.start();
}
}
/** It is just for test */
public static void clearInstancesForTest() {
synchronized (appsLock) {
//copy before delete
for (HuaweiApp app : ImmutableList.copyOf(instances.values())) {
app.delete();
}
instances.clear();
}
}
}