commit
5c6770bf5b
@ -0,0 +1,104 @@ |
|||||||
|
/* |
||||||
|
* 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.arialyy.aria.core.common; |
||||||
|
|
||||||
|
/** |
||||||
|
* 速度限制 |
||||||
|
*/ |
||||||
|
public class BandwidthLimiter { |
||||||
|
public static int maxBandWith = 2 * 1024; //KB
|
||||||
|
|
||||||
|
/* KB */ |
||||||
|
private static Long KB = 1024L; |
||||||
|
/* The smallest count chunk length in bytes */ |
||||||
|
private static Long CHUNK_LENGTH = 1024L; |
||||||
|
/* How many bytes will be sent or receive */ |
||||||
|
private int bytesWillBeSentOrReceive = 0; |
||||||
|
/* When the last piece was sent or receive */ |
||||||
|
private long lastPieceSentOrReceiveTick = System.nanoTime(); |
||||||
|
/* Default rate is 1024KB/s */ |
||||||
|
private int maxRate = 1024; |
||||||
|
/* Time cost for sending CHUNK_LENGTH bytes in nanoseconds */ |
||||||
|
private long timeCostPerChunk = (1000000000L * CHUNK_LENGTH) |
||||||
|
/ (this.maxRate * KB); |
||||||
|
|
||||||
|
/** |
||||||
|
* Initialize a BandwidthLimiter object with a certain rate. |
||||||
|
* |
||||||
|
* @param maxRate the download or upload speed in KBytes |
||||||
|
*/ |
||||||
|
public BandwidthLimiter(int maxRate, int threadNum) { |
||||||
|
if (threadNum > 1) { |
||||||
|
maxRate = maxRate / threadNum; |
||||||
|
} |
||||||
|
this.setMaxRate(maxRate); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the max upload or download rate in KB/s. maxRate must be grater than |
||||||
|
* 0. If maxRate is zero, it means there is no bandwidth limit. |
||||||
|
* |
||||||
|
* @param maxRate If maxRate is zero, it means there is no bandwidth limit. |
||||||
|
* @throws IllegalArgumentException |
||||||
|
*/ |
||||||
|
public synchronized void setMaxRate(int maxRate) |
||||||
|
throws IllegalArgumentException { |
||||||
|
if (maxRate < 0) { |
||||||
|
throw new IllegalArgumentException("maxRate can not less than 0"); |
||||||
|
} |
||||||
|
this.maxRate = maxRate; |
||||||
|
if (maxRate == 0) { |
||||||
|
this.timeCostPerChunk = 0; |
||||||
|
} else { |
||||||
|
this.timeCostPerChunk = (1000000000L * CHUNK_LENGTH) |
||||||
|
/ (this.maxRate * KB); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Next 1 byte should do bandwidth limit. |
||||||
|
*/ |
||||||
|
public synchronized void limitNextBytes() { |
||||||
|
this.limitNextBytes(1); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Next len bytes should do bandwidth limit |
||||||
|
*/ |
||||||
|
public synchronized void limitNextBytes(int len) { |
||||||
|
this.bytesWillBeSentOrReceive += len; |
||||||
|
|
||||||
|
/* We have sent CHUNK_LENGTH bytes */ |
||||||
|
while (!Thread.currentThread().isInterrupted() && this.bytesWillBeSentOrReceive > CHUNK_LENGTH) { |
||||||
|
long nowTick = System.nanoTime(); |
||||||
|
long missedTime = this.timeCostPerChunk |
||||||
|
- (nowTick - this.lastPieceSentOrReceiveTick); |
||||||
|
if (missedTime > 0) { |
||||||
|
try { |
||||||
|
Thread.currentThread().sleep(missedTime / 1000000, |
||||||
|
(int) (missedTime % 1000000)); |
||||||
|
} catch (InterruptedException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
this.bytesWillBeSentOrReceive -= CHUNK_LENGTH; |
||||||
|
this.lastPieceSentOrReceiveTick = nowTick |
||||||
|
+ (missedTime > 0 ? missedTime : 0); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,145 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.core.common; |
||||||
|
|
||||||
|
import android.os.Handler; |
||||||
|
import com.arialyy.aria.core.AriaManager; |
||||||
|
import com.arialyy.aria.core.inf.AbsEntity; |
||||||
|
import com.arialyy.aria.core.inf.AbsTask; |
||||||
|
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||||
|
import com.arialyy.aria.core.inf.IEntity; |
||||||
|
import com.arialyy.aria.core.inf.IEventListener; |
||||||
|
import com.arialyy.aria.core.inf.TaskSchedulerType; |
||||||
|
import com.arialyy.aria.core.scheduler.ISchedulers; |
||||||
|
import com.arialyy.aria.exception.BaseException; |
||||||
|
import com.arialyy.aria.util.ALog; |
||||||
|
import com.arialyy.aria.util.CommonUtil; |
||||||
|
import com.arialyy.aria.util.ErrorHelp; |
||||||
|
import java.lang.ref.WeakReference; |
||||||
|
|
||||||
|
public abstract class BaseListener<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>, TASK extends AbsTask<ENTITY, TASK_ENTITY>> |
||||||
|
implements IEventListener { |
||||||
|
private static final String TAG = "BaseListener"; |
||||||
|
protected WeakReference<Handler> outHandler; |
||||||
|
private int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度
|
||||||
|
private long mLastLen; //上一次发送长度
|
||||||
|
private boolean isFirst = true; |
||||||
|
private TASK mTask; |
||||||
|
private long mLastSaveTime; |
||||||
|
protected ENTITY mEntity; |
||||||
|
protected TASK_ENTITY mTaskEntity; |
||||||
|
protected boolean isConvertSpeed; |
||||||
|
protected long mUpdateInterval; |
||||||
|
protected AriaManager manager; |
||||||
|
|
||||||
|
protected BaseListener(TASK task, Handler outHandler) { |
||||||
|
this.outHandler = new WeakReference<>(outHandler); |
||||||
|
this.mTask = new WeakReference<>(task).get(); |
||||||
|
this.mEntity = mTask.getTaskEntity().getEntity(); |
||||||
|
this.mTaskEntity = mTask.getTaskEntity(); |
||||||
|
manager = AriaManager.getInstance(AriaManager.APP); |
||||||
|
mLastLen = mEntity.getCurrentProgress(); |
||||||
|
mLastSaveTime = System.currentTimeMillis(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onPre() { |
||||||
|
saveData(IEntity.STATE_PRE, -1); |
||||||
|
sendInState2Target(ISchedulers.PRE); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onStart(long startLocation) { |
||||||
|
saveData(IEntity.STATE_RUNNING, startLocation); |
||||||
|
sendInState2Target(ISchedulers.START); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onResume(long resumeLocation) { |
||||||
|
saveData(IEntity.STATE_RUNNING, resumeLocation); |
||||||
|
sendInState2Target(ISchedulers.RESUME); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onProgress(long currentLocation) { |
||||||
|
mEntity.setCurrentProgress(currentLocation); |
||||||
|
long speed = currentLocation - mLastLen; |
||||||
|
if (isFirst) { |
||||||
|
speed = 0; |
||||||
|
isFirst = false; |
||||||
|
} |
||||||
|
handleSpeed(speed); |
||||||
|
sendInState2Target(ISchedulers.RUNNING); |
||||||
|
if (System.currentTimeMillis() - mLastSaveTime >= RUN_SAVE_INTERVAL) { |
||||||
|
saveData(IEntity.STATE_RUNNING, currentLocation); |
||||||
|
mLastSaveTime = System.currentTimeMillis(); |
||||||
|
} |
||||||
|
|
||||||
|
mLastLen = currentLocation; |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onStop(long stopLocation) { |
||||||
|
saveData(mTask.getSchedulerType() == TaskSchedulerType.TYPE_STOP_AND_WAIT ? IEntity.STATE_WAIT |
||||||
|
: IEntity.STATE_STOP, stopLocation); |
||||||
|
handleSpeed(0); |
||||||
|
sendInState2Target(ISchedulers.STOP); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onComplete() { |
||||||
|
saveData(IEntity.STATE_COMPLETE, mEntity.getFileSize()); |
||||||
|
handleSpeed(0); |
||||||
|
sendInState2Target(ISchedulers.COMPLETE); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onCancel() { |
||||||
|
saveData(IEntity.STATE_CANCEL, -1); |
||||||
|
handleSpeed(0); |
||||||
|
sendInState2Target(ISchedulers.CANCEL); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onFail(boolean needRetry, BaseException e) { |
||||||
|
mEntity.setFailNum(mEntity.getFailNum() + 1); |
||||||
|
saveData(IEntity.STATE_FAIL, mEntity.getCurrentProgress()); |
||||||
|
handleSpeed(0); |
||||||
|
mTask.needRetry = needRetry; |
||||||
|
mTask.putExpand(AbsTask.ERROR_INFO_KEY, e); |
||||||
|
sendInState2Target(ISchedulers.FAIL); |
||||||
|
e.printStackTrace(); |
||||||
|
ErrorHelp.saveError(e.getTag(), "", ALog.getExceptionString(e)); |
||||||
|
} |
||||||
|
|
||||||
|
private void handleSpeed(long speed) { |
||||||
|
if (mUpdateInterval != 1000) { |
||||||
|
speed = speed * 1000 / mUpdateInterval; |
||||||
|
} |
||||||
|
if (isConvertSpeed) { |
||||||
|
mEntity.setConvertSpeed(CommonUtil.formatFileSize(speed < 0 ? 0 : speed) + "/s"); |
||||||
|
} |
||||||
|
mEntity.setSpeed(speed < 0 ? 0 : speed); |
||||||
|
|
||||||
|
mEntity.setPercent((int) (mEntity.getFileSize() <= 0 ? 0 |
||||||
|
: mEntity.getCurrentProgress() * 100 / mEntity.getFileSize())); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 将任务状态发送给下载器 |
||||||
|
* |
||||||
|
* @param state {@link ISchedulers#START} |
||||||
|
*/ |
||||||
|
protected void sendInState2Target(int state) { |
||||||
|
if (outHandler.get() != null) { |
||||||
|
outHandler.get().obtainMessage(state, mTask).sendToTarget(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract void saveData(int state, long location); |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.core.common; |
||||||
|
|
||||||
|
import android.support.annotation.StringDef; |
||||||
|
import java.lang.annotation.Retention; |
||||||
|
import java.lang.annotation.RetentionPolicy; |
||||||
|
|
||||||
|
@StringDef({ |
||||||
|
ProtocolType.Default, |
||||||
|
ProtocolType.SSL, |
||||||
|
ProtocolType.SSLv3, |
||||||
|
ProtocolType.TLS, |
||||||
|
ProtocolType.TLSv1, |
||||||
|
ProtocolType.TLSv1_1, |
||||||
|
ProtocolType.TLSv1_2 |
||||||
|
}) |
||||||
|
@Retention(RetentionPolicy.SOURCE) public @interface ProtocolType { |
||||||
|
String Default = "TLS"; |
||||||
|
String SSL = "SSL"; |
||||||
|
String SSLv3 = "SSLv3"; |
||||||
|
String TLS = "TLS"; |
||||||
|
String TLSv1 = "TLSv1"; |
||||||
|
String TLSv1_1 = "TLSv1.1"; |
||||||
|
String TLSv1_2 = "TLSv1.2"; |
||||||
|
} |
@ -1,78 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* 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. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.core.common; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Iterator; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.concurrent.ConcurrentHashMap; |
|
||||||
|
|
||||||
/** |
|
||||||
* 线程任务管理器 |
|
||||||
*/ |
|
||||||
class ThreadTaskManager { |
|
||||||
private static volatile ThreadTaskManager INSTANCE = null; |
|
||||||
private Map<String, List<AbsThreadTask>> mThreadTasks = new ConcurrentHashMap<>(); |
|
||||||
|
|
||||||
private ThreadTaskManager() { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public static ThreadTaskManager getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (ThreadTaskManager.class) { |
|
||||||
INSTANCE = new ThreadTaskManager(); |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 添加单条线程记录 |
|
||||||
* |
|
||||||
* @param key 任务对应的key |
|
||||||
* @param threadTask 线程任务 |
|
||||||
*/ |
|
||||||
public void addTask(String key, AbsThreadTask threadTask) { |
|
||||||
if (mThreadTasks.get(key) == null) { |
|
||||||
mThreadTasks.put(key, new ArrayList<AbsThreadTask>()); |
|
||||||
} |
|
||||||
mThreadTasks.get(key).add(threadTask); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除对应的任务的线程记录 |
|
||||||
* |
|
||||||
* @param key 任务对应的key |
|
||||||
*/ |
|
||||||
public void removeTask(String key) { |
|
||||||
for (Iterator<Map.Entry<String, List<AbsThreadTask>>> iter = mThreadTasks.entrySet().iterator(); |
|
||||||
iter.hasNext(); ) { |
|
||||||
Map.Entry<String, List<AbsThreadTask>> entry = iter.next(); |
|
||||||
if (key.equals(entry.getKey())) { |
|
||||||
List<AbsThreadTask> list = mThreadTasks.get(key); |
|
||||||
if (list != null && !list.isEmpty()) { |
|
||||||
list.clear(); |
|
||||||
} |
|
||||||
iter.remove(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,104 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.core.common.ftp; |
||||||
|
|
||||||
|
import android.text.TextUtils; |
||||||
|
import com.arialyy.aria.core.FtpUrlEntity; |
||||||
|
import com.arialyy.aria.core.common.ProtocolType; |
||||||
|
import com.arialyy.aria.core.inf.AbsTarget; |
||||||
|
import com.arialyy.aria.core.inf.ITarget; |
||||||
|
|
||||||
|
/** |
||||||
|
* FTP SSL/TSL配置 |
||||||
|
*/ |
||||||
|
public class FTPSConfig<TARGET extends AbsTarget> implements ITarget { |
||||||
|
private final String TAG = "FTPSConfig"; |
||||||
|
private TARGET mTarget; |
||||||
|
private FtpUrlEntity mUrlEntity; |
||||||
|
|
||||||
|
public FTPSConfig(TARGET target) { |
||||||
|
mTarget = target; |
||||||
|
mUrlEntity = mTarget.getTaskEntity().getUrlEntity(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置协议类型 |
||||||
|
* |
||||||
|
* @param protocol {@link ProtocolType} |
||||||
|
*/ |
||||||
|
public FTPSConfig setProtocol(@ProtocolType String protocol) { |
||||||
|
if (TextUtils.isEmpty(protocol)) { |
||||||
|
throw new NullPointerException("协议为空"); |
||||||
|
} |
||||||
|
mUrlEntity.protocol = protocol; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置证书别名 |
||||||
|
* |
||||||
|
* @param keyAlias 别名 |
||||||
|
*/ |
||||||
|
public FTPSConfig setAlias(String keyAlias) { |
||||||
|
if (TextUtils.isEmpty(keyAlias)) { |
||||||
|
throw new NullPointerException("别名为空"); |
||||||
|
} |
||||||
|
mUrlEntity.keyAlias = keyAlias; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置证书密码 |
||||||
|
* |
||||||
|
* @param storePass 私钥密码 |
||||||
|
*/ |
||||||
|
public FTPSConfig setStorePass(String storePass) { |
||||||
|
if (TextUtils.isEmpty(storePass)) { |
||||||
|
throw new NullPointerException("证书密码为空"); |
||||||
|
} |
||||||
|
mUrlEntity.storePass = storePass; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置证书路径 |
||||||
|
* |
||||||
|
* @param storePath 证书路径 |
||||||
|
*/ |
||||||
|
public FTPSConfig setStorePath(String storePath) { |
||||||
|
if (TextUtils.isEmpty(storePath)) { |
||||||
|
throw new NullPointerException("证书路径为空"); |
||||||
|
} |
||||||
|
mUrlEntity.storePath = storePath; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void start() { |
||||||
|
mTarget.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void stop() { |
||||||
|
mTarget.stop(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void resume() { |
||||||
|
mTarget.resume(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void cancel() { |
||||||
|
mTarget.cancel(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package com.arialyy.aria.core.common.ftp; |
||||||
|
|
||||||
|
import aria.apache.commons.net.ftp.FTPSClient; |
||||||
|
import java.io.IOException; |
||||||
|
import java.lang.reflect.Field; |
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.net.Socket; |
||||||
|
import java.util.Locale; |
||||||
|
import javax.net.ssl.SSLContext; |
||||||
|
import javax.net.ssl.SSLSession; |
||||||
|
import javax.net.ssl.SSLSessionContext; |
||||||
|
import javax.net.ssl.SSLSocket; |
||||||
|
|
||||||
|
public class SSLSessionReuseFTPSClient extends FTPSClient { |
||||||
|
|
||||||
|
SSLSessionReuseFTPSClient(boolean b, SSLContext context) { |
||||||
|
super(b, context); |
||||||
|
} |
||||||
|
|
||||||
|
// adapted from:
|
||||||
|
// https://trac.cyberduck.io/browser/trunk/ftp/src/main/java/ch/cyberduck/core/ftp/FTPClient.java
|
||||||
|
@Override |
||||||
|
protected void _prepareDataSocket_(final Socket socket) throws IOException { |
||||||
|
if (socket instanceof SSLSocket) { |
||||||
|
// Control socket is SSL
|
||||||
|
final SSLSession session = ((SSLSocket) _socket_).getSession(); |
||||||
|
if (session.isValid()) { |
||||||
|
final SSLSessionContext context = session.getSessionContext(); |
||||||
|
try { |
||||||
|
//final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
|
||||||
|
final Field sessionHostPortCache = |
||||||
|
context.getClass().getDeclaredField("sessionsByHostAndPort"); |
||||||
|
sessionHostPortCache.setAccessible(true); |
||||||
|
final Object cache = sessionHostPortCache.get(context); |
||||||
|
final Method method = |
||||||
|
cache.getClass().getDeclaredMethod("put", Object.class, Object.class); |
||||||
|
method.setAccessible(true); |
||||||
|
method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostName(), |
||||||
|
String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session); |
||||||
|
method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostAddress(), |
||||||
|
String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session); |
||||||
|
} catch (NoSuchFieldException e) { |
||||||
|
throw new IOException(e); |
||||||
|
} catch (Exception e) { |
||||||
|
throw new IOException(e); |
||||||
|
} |
||||||
|
} else { |
||||||
|
throw new IOException("Invalid SSL Session"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,86 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.core.common.http; |
||||||
|
|
||||||
|
import android.text.TextUtils; |
||||||
|
import com.arialyy.aria.core.common.RequestEnum; |
||||||
|
import com.arialyy.aria.core.download.DownloadGroupTarget; |
||||||
|
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; |
||||||
|
import com.arialyy.aria.core.download.DownloadTaskEntity; |
||||||
|
import com.arialyy.aria.core.inf.AbsTarget; |
||||||
|
import com.arialyy.aria.core.inf.IPostDelegate; |
||||||
|
import com.arialyy.aria.core.inf.ITarget; |
||||||
|
import com.arialyy.aria.util.ALog; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* post处理委托类 |
||||||
|
*/ |
||||||
|
public class PostDelegate<TARGET extends AbsTarget> implements IPostDelegate<TARGET>, ITarget { |
||||||
|
private static final String TAG = "PostDelegate"; |
||||||
|
private TARGET mTarget; |
||||||
|
|
||||||
|
public PostDelegate(TARGET target) { |
||||||
|
mTarget = target; |
||||||
|
mTarget.getTaskEntity().setRequestEnum(RequestEnum.POST); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public TARGET setParams(Map<String, String> params) { |
||||||
|
mTarget.getTaskEntity().setParams(params); |
||||||
|
if (mTarget instanceof DownloadGroupTarget) { |
||||||
|
for (DownloadTaskEntity subTask : ((DownloadGroupTaskEntity) mTarget.getTaskEntity()).getSubTaskEntities()) { |
||||||
|
subTask.setParams(params); |
||||||
|
} |
||||||
|
} |
||||||
|
return mTarget; |
||||||
|
} |
||||||
|
|
||||||
|
@Override public TARGET setParam(String key, String value) { |
||||||
|
if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) { |
||||||
|
ALog.d(TAG, "key 或value 为空"); |
||||||
|
return mTarget; |
||||||
|
} |
||||||
|
Map<String, String> params = mTarget.getTaskEntity().getParams(); |
||||||
|
if (params == null) { |
||||||
|
params = new HashMap<>(); |
||||||
|
mTarget.getTaskEntity().setParams(params); |
||||||
|
} |
||||||
|
params.put(key, value); |
||||||
|
if (mTarget instanceof DownloadGroupTarget) { |
||||||
|
for (DownloadTaskEntity subTask : ((DownloadGroupTaskEntity) mTarget.getTaskEntity()).getSubTaskEntities()) { |
||||||
|
subTask.setParams(params); |
||||||
|
} |
||||||
|
} |
||||||
|
return mTarget; |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void start() { |
||||||
|
mTarget.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void stop() { |
||||||
|
mTarget.stop(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void resume() { |
||||||
|
mTarget.resume(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void cancel() { |
||||||
|
mTarget.cancel(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.core.inf; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* post 通用处理接口 |
||||||
|
*/ |
||||||
|
public interface IPostDelegate<TARGET extends ITarget> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 设置Post请求参数 |
||||||
|
*/ |
||||||
|
TARGET setParams(Map<String, String> params); |
||||||
|
|
||||||
|
TARGET setParam(String key, String value); |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.arialyy.aria.core.inf; |
||||||
|
|
||||||
|
import android.support.annotation.IntDef; |
||||||
|
import java.lang.annotation.Retention; |
||||||
|
import java.lang.annotation.RetentionPolicy; |
||||||
|
|
||||||
|
@IntDef({ |
||||||
|
TaskSchedulerType.TYPE_DEFAULT, |
||||||
|
TaskSchedulerType.TYPE_STOP_NOT_NEXT, |
||||||
|
TaskSchedulerType.TYPE_STOP_AND_WAIT |
||||||
|
}) |
||||||
|
@Retention(RetentionPolicy.SOURCE) public @interface TaskSchedulerType { |
||||||
|
int TYPE_DEFAULT = 1; |
||||||
|
/** |
||||||
|
* 停止当前任务并且不自动启动下一任务 |
||||||
|
*/ |
||||||
|
int TYPE_STOP_NOT_NEXT = 2; |
||||||
|
/** |
||||||
|
* 停止任务并让当前任务处于等待状态 |
||||||
|
*/ |
||||||
|
int TYPE_STOP_AND_WAIT = 3; |
||||||
|
} |
@ -0,0 +1,135 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||||
|
* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.arialyy.aria.core.manager; |
||||||
|
|
||||||
|
import com.arialyy.aria.core.common.AbsThreadTask; |
||||||
|
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||||
|
import com.arialyy.aria.util.ALog; |
||||||
|
import com.arialyy.aria.util.CommonUtil; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
import java.util.concurrent.ExecutorService; |
||||||
|
import java.util.concurrent.Executors; |
||||||
|
import java.util.concurrent.Future; |
||||||
|
|
||||||
|
/** |
||||||
|
* 线程管理器 |
||||||
|
*/ |
||||||
|
public class ThreadTaskManager { |
||||||
|
private static volatile ThreadTaskManager INSTANCE = null; |
||||||
|
private static final Object LOCK = new Object(); |
||||||
|
private final String TAG = "ThreadTaskManager"; |
||||||
|
private ExecutorService mExePool; |
||||||
|
private Map<String, Set<Future>> mThreadTasks = new HashMap<>(); |
||||||
|
|
||||||
|
public static ThreadTaskManager getInstance() { |
||||||
|
if (INSTANCE == null) { |
||||||
|
synchronized (LOCK) { |
||||||
|
INSTANCE = new ThreadTaskManager(); |
||||||
|
} |
||||||
|
} |
||||||
|
return INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
private ThreadTaskManager() { |
||||||
|
mExePool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 启动线程任务 |
||||||
|
* |
||||||
|
* @param key 任务对应的key{@link AbsTaskEntity#getKey()} |
||||||
|
* @param threadTask 线程任务{@link AbsThreadTask} |
||||||
|
*/ |
||||||
|
public synchronized void startThread(String key, AbsThreadTask threadTask) { |
||||||
|
if (mExePool.isShutdown()) { |
||||||
|
ALog.e(TAG, "线程池已经关闭"); |
||||||
|
return; |
||||||
|
} |
||||||
|
key = getKey(key); |
||||||
|
Set<Future> temp = mThreadTasks.get(key); |
||||||
|
if (temp == null) { |
||||||
|
temp = new HashSet<>(); |
||||||
|
mThreadTasks.put(key, temp); |
||||||
|
} |
||||||
|
temp.add(mExePool.submit(threadTask)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 停止任务的所有线程 |
||||||
|
* |
||||||
|
* @param key 任务对应的key{@link AbsTaskEntity#getKey()} |
||||||
|
*/ |
||||||
|
public synchronized void stopTaskThread(String key) { |
||||||
|
if (mExePool.isShutdown()) { |
||||||
|
ALog.e(TAG, "线程池已经关闭"); |
||||||
|
return; |
||||||
|
} |
||||||
|
key = getKey(key); |
||||||
|
Set<Future> temp = mThreadTasks.get(key); |
||||||
|
if (temp != null && temp.size() > 0) { |
||||||
|
try { |
||||||
|
for (Future future : temp) { |
||||||
|
if (future.isDone() || future.isCancelled()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
AbsThreadTask task = (AbsThreadTask) future.get(); |
||||||
|
task.setInterrupted(true); |
||||||
|
future.cancel(true); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
ALog.e(TAG, e); |
||||||
|
} |
||||||
|
temp.clear(); |
||||||
|
} |
||||||
|
mThreadTasks.remove(key); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 重试线程任务 |
||||||
|
* |
||||||
|
* @param task 线程任务 |
||||||
|
*/ |
||||||
|
public synchronized void retryThread(AbsThreadTask task) { |
||||||
|
if (mExePool.isShutdown()) { |
||||||
|
ALog.e(TAG, "线程池已经关闭"); |
||||||
|
return; |
||||||
|
} |
||||||
|
try { |
||||||
|
if (task == null || task.isInterrupted()) { |
||||||
|
ALog.e(TAG, "线程为空或线程已经中断"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
ALog.e(TAG, e); |
||||||
|
return; |
||||||
|
} |
||||||
|
mExePool.submit(task); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* map中的key |
||||||
|
* |
||||||
|
* @param key 任务的key{@link AbsTaskEntity#getKey()} |
||||||
|
* @return 转换后的map中的key |
||||||
|
*/ |
||||||
|
private String getKey(String key) { |
||||||
|
return CommonUtil.getStrMd5(key); |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue