/**
* Copyright (C) 2007 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 63.529,40 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package com.aelitis.azureus.util;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.global.GlobalManagerAdapter;
import org.gudy.azureus2.core3.torrent.TOTorrent;
import org.gudy.azureus2.core3.torrent.TOTorrentException;
import org.gudy.azureus2.core3.util.*;
import com.aelitis.azureus.core.AzureusCore;
import com.aelitis.azureus.core.download.DownloadManagerEnhancer;
import com.aelitis.azureus.core.download.EnhancedDownloadManager;
import com.aelitis.azureus.core.messenger.config.PlatformAdManager;
import com.aelitis.azureus.core.torrent.MetaDataUpdateListener;
import com.aelitis.azureus.core.torrent.PlatformTorrentUtils;
import com.aelitis.net.magneturi.MagnetURIHandler;
/**
* @author TuxPaper
* @created May 31, 2007
*
*/
public class AdManager
{
private final static long EXPIRE_ASX = 1000L * 60 * 10; // 10 min
private final static AdManager instance;
static {
instance = new AdManager();
}
public static AdManager getInstance() {
return instance;
}
private AzureusCore core;
private List adsDMList = new ArrayList();
private List adSupportedDMList = new ArrayList();
// key = DM, value = Semaphore
private Map asxInProgress = new HashMap();
private AEMonitor asxInProgress_mon = new AEMonitor("asxInProgress");
private Object lastImpressionID;
public void intialize(final AzureusCore core) {
this.core = core;
ExternalStimulusHandler.addListener(new ExternalStimulusListener() {
public boolean receive(String name, Map values) {
if (values == null) {
return false;
}
if (name.equals("adtracker")) {
processImpression(values);
return true;
}
return false;
}
});
GlobalManager gm = core.getGlobalManager();
gm.addListener(new GlobalManagerAdapter() {
public void downloadManagerRemoved(DownloadManager dm) {
adsDMList.remove(dm);
File asxFile = (File) dm.getData("ASX");
if (asxFile != null) {
try {
asxFile.delete();
} catch (Exception e) {
}
}
}
public void downloadManagerAdded(final DownloadManager dm) {
TOTorrent torrent = dm.getTorrent();
if (PlatformTorrentUtils.isContentAdEnabled(torrent)) {
dm.setData("ASX", buildASXFileLocation(dm));
}
hookDM(new DownloadManager[] {
dm
});
}
}, false);
DownloadManager[] dms = (DownloadManager[]) gm.getDownloadManagers().toArray(
new DownloadManager[0]);
hookDM(dms);
PlatformAdManager.loadUnsentImpressions();
PlatformAdManager.sendUnsentImpressions(5000);
PlatformTorrentUtils.addListener(new MetaDataUpdateListener() {
public void metaDataUpdated(TOTorrent torrent) {
GlobalManager gm = core.getGlobalManager();
DownloadManager dm = gm.getDownloadManager(torrent);
if (dm != null
&& PlatformTorrentUtils.isContentAdEnabled(dm.getTorrent())) {
hookDM(new DownloadManager[] {
dm
});
}
}
});
}
private void hookDM(final DownloadManager[] dms) {
AEThread thread = new AEThread("hookDM", true) {
public void runSupport() {
// build list of ad supported content
List list = new ArrayList();
for (int i = 0; i < dms.length; i++) {
final DownloadManager dm = dms[i];
TOTorrent torrent = dm.getTorrent();
if (torrent == null) {
return;
}
if (PlatformTorrentUtils.getAdId(torrent) != null) {
// one of us!
// TODO: Check expirey
try {
PlatformAdManager.debug("found ad " + dm + ": "
+ PlatformTorrentUtils.getAdId(torrent) + ": "
+ dm.getTorrent().getHashWrapper().toBase32String());
} catch (TOTorrentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (!adsDMList.contains(dm)) {
adsDMList.add(dm);
}
if (dm.getAssumedComplete()) {
dm.setForceStart(false);
} else {
dm.addListener(new DownloadManagerAdapter() {
public void downloadComplete(DownloadManager manager) {
if (!adsDMList.contains(manager)) {
adsDMList.add(manager);
}
manager.setForceStart(false);
manager.removeListener(this);
}
});
}
}
if (PlatformTorrentUtils.isContent(torrent, true)
&& PlatformTorrentUtils.getContentHash(torrent) != null
&& PlatformTorrentUtils.isContentAdEnabled(torrent)) {
list.add(dm);
if (!adSupportedDMList.contains(dm)) {
adSupportedDMList.add(dm);
if (!dm.getAssumedComplete()) {
dm.addListener(new DownloadManagerAdapter() {
public void downloadComplete(DownloadManager manager) {
// good chance we still have internet here, so get/cache
// the asx
EnhancedDownloadManager edm = DownloadManagerEnhancer.getSingleton().getEnhancedDownload(
dm);
File file;
if (edm != null) {
file = edm.getPrimaryFile().getFile(true);
} else {
file = new File(dm.getDownloadState().getPrimaryFile());
}
String url;
try {
url = file.toURL().toString();
} catch (MalformedURLException e) {
url = file.getAbsolutePath();
}
createASX(dm, url, null);
}
});
}
}
}
}
if (list.size() == 0) {
PlatformAdManager.debug("no ad enabled content. skipping ad get.");
return;
}
try {
PlatformAdManager.debug("sending ad request for " + list.size()
+ " pieces of content. We already have " + adsDMList.size()
+ " ads");
DownloadManager[] dmAdable = (DownloadManager[]) list.toArray(new DownloadManager[0]);
PlatformAdManager.getAds(dmAdable, 1000,
new PlatformAdManager.GetAdsDataReplyListener() {
public void replyReceived(String replyType, Map mapHashes) {
PlatformAdManager.debug("bad reply. " + mapHashes.get("text"));
}
public void messageSent() {
}
public void adsReceived(List torrents) {
PlatformAdManager.debug(torrents.size() + " Ads recieved");
for (Iterator iter = torrents.iterator(); iter.hasNext();) {
TOTorrent torrent = (TOTorrent) iter.next();
try {
PlatformAdManager.debug("Ad: "
+ new String(torrent.getName()));
TorrentUtils.setFlag(torrent,
TorrentUtils.TORRENT_FLAG_LOW_NOISE, true);
File tempFile = File.createTempFile("AZ_", ".torrent");
PlatformAdManager.debug(" Writing to " + tempFile);
torrent.serialiseToBEncodedFile(tempFile);
String sDefDir = null;
try {
sDefDir = COConfigurationManager.getDirectoryParameter("Default save path");
} catch (IOException e) {
}
if (sDefDir == null) {
sDefDir = tempFile.getParent();
}
DownloadManager adDM = core.getGlobalManager().addDownloadManager(
tempFile.getAbsolutePath(), sDefDir);
if (adDM != null) {
if (adDM.getAssumedComplete()) {
adsDMList.add(adDM);
adDM.setForceStart(false);
} else {
adDM.setForceStart(true);
PlatformAdManager.debug("Force Start " + adDM);
adDM.addListener(new DownloadManagerAdapter() {
public void downloadComplete(DownloadManager manager) {
if (!adsDMList.contains(manager)) {
adsDMList.add(manager);
}
manager.setForceStart(false);
manager.removeListener(this);
}
});
}
// TODO: Add Expiry date
PlatformAdManager.debug(" ADDED ad "
+ adDM.getDisplayName());
}
tempFile.deleteOnExit();
} catch (Exception e) {
Debug.out(e);
}
}
}
});
} catch (Exception e) {
Debug.out(e);
}
}
};
thread.run();
}
protected void processImpression(Map values) {
final String PREFIX = "Yum";
try {
String impressionID = (String) values.get("impressionTracker");
if (impressionID == null || impressionID.equals(lastImpressionID)) {
return;
}
lastImpressionID = impressionID;
String adHash = (String) values.get("srcURL");
if (adHash == null) {
return;
}
String contentHash = (String) values.get("contentHash");
if (contentHash == null) {
PlatformAdManager.debug("No Content Hash!");
return;
}
String torrentHash = (String) values.get("hash");
String adID = (String) values.get(PREFIX + "eURI");
PlatformAdManager.debug("imp " + impressionID + " commencing on "
+ contentHash);
DownloadManager dm = core.getGlobalManager().getDownloadManager(
new HashWrapper(Base32.decode(adHash)));
if (dm == null) {
System.err.println("DM for Ad not found. CHEATER!!");
}
DownloadManager dmContent = core.getGlobalManager().getDownloadManager(
new HashWrapper(Base32.decode(contentHash)));
if (dmContent != null) {
dmContent.setData("LastASX", null);
}
PlatformAdManager.storeImpresssion(impressionID,
SystemTime.getCurrentTime(), contentHash, torrentHash, adHash, adID,
5000);
} catch (Exception e) {
Debug.out(e);
}
}
public DownloadManager[] getAds(boolean bIncludeIncomplete) {
if (bIncludeIncomplete) {
return (DownloadManager[]) adsDMList.toArray(new DownloadManager[0]);
}
ArrayList ads = new ArrayList(adsDMList);
for (Iterator iter = ads.iterator(); iter.hasNext();) {
DownloadManager dm = (DownloadManager) iter.next();
if (!dm.getAssumedComplete()) {
iter.remove();
}
}
PlatformAdManager.debug("Get Ads"
+ (bIncludeIncomplete ? " including incomplete" : "") + ads.size());
return (DownloadManager[]) ads.toArray(new DownloadManager[0]);
}
public List getIncompleteAds() {
ArrayList ads = new ArrayList(adsDMList);
for (Iterator iter = ads.iterator(); iter.hasNext();) {
DownloadManager dm = (DownloadManager) iter.next();
if (dm.getAssumedComplete()) {
iter.remove();
}
}
PlatformAdManager.debug("Get Incomplate Ads: " + ads.size());
return ads;
}
public void createASX(final DownloadManager dm, String URLToPlay,
final ASXCreatedListener l) {
try {
TOTorrent torrent = dm.getTorrent();
if (torrent == null || !PlatformTorrentUtils.isContent(torrent, true)) {
return;
}
Object lastASXObject = dm.getData("LastASX");
if (lastASXObject instanceof Long) {
long lastASX = ((Long) lastASXObject).longValue();
if (SystemTime.getCurrentTime() - lastASX < EXPIRE_ASX) {
File asxFile = buildASXFileLocation(dm);
if (asxFile.isFile()) {
PlatformAdManager.debug("playing using existing asx: " + asxFile);
if (l != null) {
l.asxCreated(asxFile);
}
return;
}
}
}
final String contentHash = PlatformTorrentUtils.getContentHash(torrent);
final String hash = dm.getTorrent().getHashWrapper().toBase32String();
try {
asxInProgress_mon.enter();
AESemaphore sem = (AESemaphore) asxInProgress.get(hash);
if (sem != null) {
PlatformAdManager.debug("already getting asx.. waiting..");
asxInProgress_mon.exit();
sem.reserve();
asxInProgress_mon.enter();
File asxFile = buildASXFileLocation(dm);
if (asxFile.isFile()) {
PlatformAdManager.debug("playing using existing asx: " + asxFile);
if (l != null) {
l.asxCreated(asxFile);
}
return;
}
} else {
asxInProgress.put(hash, new AESemaphore(hash));
}
} finally {
asxInProgress_mon.exit();
}
PlatformAdManager.debug("getting asx");
PlatformAdManager.getPlayList(dm, URLToPlay, "http://127.0.0.1:"
+ MagnetURIHandler.getSingleton().getPort()
+ "/setinfo?name=adtracker&contentHash=" + contentHash + "&hash="
+ hash, 0, new PlatformAdManager.GetPlaylistReplyListener() {
public void replyReceived(String replyType, String playlist) {
try {
if (playlist == null) {
PlatformAdManager.debug("no asx in reply");
if (l != null) {
l.asxFailed();
}
return;
}
File asxFile = buildASXFileLocation(dm);
PlatformAdManager.debug("got asx. Writing to " + asxFile);
FileUtil.writeBytesAsFile(asxFile.getAbsolutePath(),
playlist.getBytes());
dm.setData("LastASX", new Long(SystemTime.getCurrentTime()));
dm.setData("ASX", asxFile);
if (l != null) {
l.asxCreated(asxFile);
}
} catch (Exception e) {
PlatformAdManager.debug("asx reply", e);
if (l != null) {
l.asxFailed();
}
} finally {
try {
asxInProgress_mon.enter();
AESemaphore sem = (AESemaphore) asxInProgress.remove(hash);
if (sem != null) {
sem.releaseForever();
} else {
}
} finally {
asxInProgress_mon.exit();
}
}
}
public void messageSent() {
}
});
} catch (Exception e) {
if (l != null) {
l.asxFailed();
}
}
}
private File buildASXFileLocation(DownloadManager dm) {
EnhancedDownloadManager edm = DownloadManagerEnhancer.getSingleton().getEnhancedDownload(
dm);
File file;
if (edm != null) {
file = edm.getPrimaryFile().getFile(true);
} else {
file = new File(dm.getDownloadState().getPrimaryFile());
}
return new File(file.getAbsolutePath() + ".asx");
}
public interface ASXCreatedListener
{
public void asxCreated(File asxFile);
public void asxFailed();
}
/**
* @param nowPlaying
*
* @since 3.0.2.3
*/
public boolean isAd(String nowPlaying) {
File file = new File(nowPlaying);
DownloadManager[] ads = getAds(true);
for (int i = 0; i < ads.length; i++) {
DownloadManager downloadManager = ads[i];
DiskManagerFileInfo[] fileInfos = downloadManager.getDiskManagerFileInfo();
for (int j = 0; j < fileInfos.length; j++) {
DiskManagerFileInfo fileinfo = fileInfos[j];
File adFile = fileinfo.getFile(true);
if (adFile.equals(file)) {
return true;
}
}
}
return false;
}
}
|