/******************************************************************************* * Copyright (c) 2001, 2010 Mathew A. Nelson and Robocode contributors * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://robocode.sourceforge.net/license/epl-v10.html * * Contributors: * Pavel Savara * - Initial implementation *******************************************************************************/ package net.sf.robocode.repository.root; import net.sf.robocode.io.FileUtil; import net.sf.robocode.io.Logger; import net.sf.robocode.io.URLJarCollector; import net.sf.robocode.io.JarJar; import net.sf.robocode.repository.Database; import net.sf.robocode.repository.packager.JarExtractor; import net.sf.robocode.repository.items.IItem; import net.sf.robocode.repository.items.RobotItem; import net.sf.robocode.repository.items.handlers.ItemHandler; import net.sf.robocode.ui.IWindowManager; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; /** * Represents one .jar file * @author Pavel Savara (original) */ public class JarRoot extends BaseRoot implements IRepositoryRoot { private static final long serialVersionUID = 1L; private URL jarUrl; private String jarNoSeparator; private long lastModified; public JarRoot(Database db, File rootPath) { super(db, rootPath); try { jarNoSeparator = "jar:" + rootPath.toURI().toString(); jarUrl = new URL(jarNoSeparator + "!/"); } catch (MalformedURLException e) { Logger.logError(e); } } public void update(boolean force) { final IWindowManager windowManager = net.sf.robocode.core.Container.getComponent(IWindowManager.class); setStatus(windowManager, "Updating .jar: " + rootPath.toString()); long lm = rootPath.lastModified(); if (lm > this.lastModified) { db.moveOldItems(this); this.lastModified = lm; final ArrayList<IItem> items = new ArrayList<IItem>(); visitItems(items); for (IItem item : items) { item.update(lastModified, force); } } } private void visitItems(ArrayList<IItem> items) { final String root = jarNoSeparator; InputStream is = null; BufferedInputStream bis = null; JarInputStream jarIS = null; try { final URLConnection con = URLJarCollector.openConnection(rootURL); is = con.getInputStream(); bis = new BufferedInputStream(is); jarIS = new JarInputStream(bis); readJarStream(items, root, jarIS); } catch (Exception e) { Logger.logError(rootURL + " is probably corrupted (" + e.getClass().getName() + " " + e.getMessage() + ")"); } finally { FileUtil.cleanupStream(jarIS); FileUtil.cleanupStream(bis); FileUtil.cleanupStream(is); } } private void readJarStream(ArrayList<IItem> items, String root, JarInputStream jarIS) throws IOException { JarEntry entry = jarIS.getNextJarEntry(); while (entry != null) { String name = entry.getName().toLowerCase(); if (!entry.isDirectory()) { if (name.contains(".data/") && !name.contains(".robotcache/")) { JarExtractor.extractFile(FileUtil.getRobotsDataDir(), jarIS, entry); } else { if (name.endsWith(".jar") || name.endsWith(".zip")) { JarInputStream inner = null; try { inner = new JarInputStream(jarIS); readJarStream(items, "jar:jar" + root + JarJar.SEPARATOR + entry.getName(), inner); } finally { if (inner != null) { inner.closeEntry(); } } } else { createItem(items, new URL(root + "!/"), entry); } } } entry = jarIS.getNextJarEntry(); } } private void createItem(ArrayList<IItem> items, URL root, JarEntry entry) { try { String pUrl = root.toString() + entry.getName(); final IItem item = ItemHandler.registerItems(new URL(pUrl), JarRoot.this, db); if (item != null) { if (item instanceof RobotItem) { RobotItem robotItem = (RobotItem) item; robotItem.setClassPathURL(root); } items.add(item); } } catch (MalformedURLException e) { Logger.logError(e); } } public void update(IItem item, boolean force) { item.update(rootPath.lastModified(), force); } public boolean isChanged(IItem item) { return rootPath.lastModified() > lastModified; } public URL getURL() { return jarUrl; } public boolean isDevelopmentRoot() { return false; } public boolean isJAR() { return true; } public void extractJAR() { JarExtractor.extractJar(rootURL); } private static void setStatus(IWindowManager windowManager, String message) { if (windowManager != null) { windowManager.setStatus(message); } } }