Inital commit
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
//Gruppe 01 (Übung 4)
|
||||
//Aufgabe 4-3
|
||||
|
||||
package uebung04.aufgabe03;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.HashSet;
|
||||
import javax.swing.text.MutableAttributeSet;
|
||||
import javax.swing.text.html.HTML;
|
||||
import javax.swing.text.html.HTML.Tag;
|
||||
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
|
||||
import javax.swing.text.html.parser.ParserDelegator;
|
||||
|
||||
/**
|
||||
* Sucht in einer HTML-Ressource nach eingebetten Objekten und summiert die Dateigrößen auf,
|
||||
* wobei mehrfach verlinkte Objekte nur einmal gezählt werden.
|
||||
* Bei Framesets werden sämtliche Frames ausgewertet, in mehreren Frames dargestellte Seiten
|
||||
* werden nur einfach gezählt.
|
||||
*
|
||||
* @author Tilman Walther
|
||||
* @version 2.1
|
||||
*/
|
||||
public class SiteSize extends ParserCallback {
|
||||
|
||||
private URL url; // die URL der HTML-Ressource
|
||||
private URLConnection connection; // Verbindung zur HTML-Ressource
|
||||
private HashSet objects = null; // speichert URLs der bereits gezählten Objekten
|
||||
private long size = 0; // die Größe aller gezählten Objekte
|
||||
|
||||
private ParserDelegator parser = new ParserDelegator(); // parst die Ressource und ruft handleSimpleTag() auf
|
||||
|
||||
/**
|
||||
* Parses the resource behind the given URL and measures the size.
|
||||
* If the URL points to a non-HTML resource the size will be zero.
|
||||
* @param url the URL for the resource to parse
|
||||
* @return the size of the website including all embedded objects
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
public long getSize(URL url) throws IOException {
|
||||
|
||||
/* Für Testzwecke: Durchleitungsproxy einstellen /
|
||||
|
||||
java.util.Properties props = System.getProperties();
|
||||
props.put("proxySet", "true");
|
||||
props.put("proxyHost", "127.0.0.1");
|
||||
props.put("proxyPort", "10000");
|
||||
|
||||
/* --------------------------------------------- */
|
||||
|
||||
System.out.println("\nparsing "+url);
|
||||
|
||||
this.url = url;
|
||||
connection = url.openConnection();
|
||||
|
||||
// Daten vom Server im "identity"-Format anfordern
|
||||
connection.addRequestProperty("Accept-Encoding", "identity");
|
||||
|
||||
// TODO für Testzwecke:
|
||||
//connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12");
|
||||
|
||||
connection.connect();
|
||||
|
||||
//System.out.println("Transfer-Encoding: "+connection.getHeaderField("transfer-encoding")+"\n");
|
||||
|
||||
// falls objects nicht bereits durch den privaten Konstruktor
|
||||
// inititalisiert wurde, neues HashSet erzeugen
|
||||
if (objects == null) objects = new HashSet();
|
||||
|
||||
// auf HTML-Inhalt prüfen
|
||||
if (connection.getContentType().startsWith("text/html")) {
|
||||
// Größe der Seite zur Gesamtgröße addieren
|
||||
addSize(url);
|
||||
|
||||
// eingebettete Objekte mit Parser finden/addieren
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
parser.parse(br, this, true);
|
||||
}
|
||||
|
||||
// Gesamtgröße zurückgeben
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* This private method is used for recursive processing of framesets.
|
||||
* In order not to count linked objects twice, the HashSet 'objects' is passed.
|
||||
* @param url the URL for the actual frame
|
||||
* @param objects the HashSet containing all objects that have already been counted
|
||||
* @return the size if the subframe
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private long getSize(URL url, HashSet objects) throws IOException {
|
||||
this.objects = objects;
|
||||
return getSize(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides javax.swing.text.html.HTMLEditorKit.ParserCallback.handleSimpleTag() which is called by the ParserDelegator
|
||||
* @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleSimpleTag(javax.swing.text.html.HTML.Tag, javax.swing.text.MutableAttributeSet, int)
|
||||
*/
|
||||
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
|
||||
|
||||
String objLink = null;
|
||||
|
||||
try {
|
||||
if (t == HTML.Tag.FRAME) {
|
||||
// leider trifft man öfter auf dummy-frames (Dreamweaver!), deswegen
|
||||
// fehlt ab und zu die Quelle
|
||||
if (a.getAttribute(HTML.Attribute.SRC) != null) {
|
||||
// absuluten Pfad zur Ressource nachvollziehen, um mehrfache Zählung zu vermeiden
|
||||
URL frameUrl = generateURL(a.getAttribute(HTML.Attribute.SRC).toString());
|
||||
|
||||
// Frame von neuem SiteSize-Objekt parsen lassen
|
||||
SiteSize frameSize = new SiteSize();
|
||||
size += frameSize.getSize(frameUrl, objects);
|
||||
}
|
||||
} else {
|
||||
if (t == HTML.Tag.APPLET) {
|
||||
// Applets können direkt via CODE-Attribut oder als Archiv verlinkt sein
|
||||
if (a.getAttribute(HTML.Attribute.ARCHIVE) != null) {
|
||||
objLink = a.getAttribute(HTML.Attribute.ARCHIVE).toString();
|
||||
} else {
|
||||
objLink = a.getAttribute(HTML.Attribute.CODE).toString();
|
||||
}
|
||||
} else if (t == HTML.Tag.IMG) {
|
||||
objLink = a.getAttribute(HTML.Attribute.SRC).toString();
|
||||
} else if (t == HTML.Tag.OBJECT) {
|
||||
objLink = a.getAttribute(HTML.Attribute.DATA).toString();
|
||||
} else if (t == HTML.Tag.LINK) {
|
||||
objLink = a.getAttribute(HTML.Attribute.HREF).toString();
|
||||
}
|
||||
|
||||
if (objLink != null) {
|
||||
try {
|
||||
// absuluten Pfad zur Ressource nachvollziehen, um mehrfache Zählung zu vermeiden
|
||||
addSize(generateURL(objLink));
|
||||
} catch (MalformedURLException mue) {
|
||||
System.out.println("MalformedURLException on position " + pos + ": '" + objLink + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
System.out.println("IOException (" + pos + "): Could not connect to linked object. ("+objLink+")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides javax.swing.text.html.HTMLEditorKit.ParserCallback.handleStartTag() which is called by the ParserDelegator.
|
||||
* @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleStartTag(javax.swing.text.html.HTML.Tag, javax.swing.text.MutableAttributeSet, int)
|
||||
*/
|
||||
public void handleStartTag(Tag t, MutableAttributeSet a, int pos) {
|
||||
// Da APPLET- und OBJECT-Tags auch als StartTags vorkommen können, wird das der Aufruf
|
||||
// in diesem Fall an handleSimpleTag() weitergegeben
|
||||
if ((t == HTML.Tag.APPLET) || (t == HTML.Tag.OBJECT)) handleSimpleTag(t, a, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the size of the resource that the given URLConnection points to if it has not already been counted
|
||||
* @param connection an URLConnection to a resource
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private void addSize(URL url) throws IOException {
|
||||
|
||||
URLConnection resConn = url.openConnection();
|
||||
|
||||
// TODO für Testzwecke:
|
||||
//resConn.addRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; de-DE; rv:1.7) Gecko/20040803 Firefox/0.9.3");
|
||||
|
||||
resConn.connect();
|
||||
|
||||
String resUrlStr = url.toString();
|
||||
|
||||
if (!objects.contains(resUrlStr)) {
|
||||
objects.add(resUrlStr);
|
||||
int resLength = resConn.getContentLength();
|
||||
|
||||
if (resLength >= 0) {
|
||||
size += resLength;
|
||||
}
|
||||
else {
|
||||
// da der Content-Length Header nicht übermittelt wurde, muss zur
|
||||
// Messung die Ressource übertragen werden
|
||||
|
||||
int bytesRead;
|
||||
byte[] buffer = new byte[1024];
|
||||
BufferedInputStream input = new BufferedInputStream(resConn.getInputStream());
|
||||
|
||||
resLength = 0;
|
||||
|
||||
while ((bytesRead = input.read(buffer)) >= 0) {
|
||||
resLength += bytesRead;
|
||||
}
|
||||
|
||||
size += resLength;
|
||||
}
|
||||
|
||||
System.out.println("added '" + resUrlStr + "' (" + resLength + " bytes)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the URL for a (relative) link extracted from a tag attribute
|
||||
* @param link a resource link from a tag attribute
|
||||
* @return the URL to the resource
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
// TODO wahrscheinlich lässt sich diese Methode (zumindest teilw.) durch URI.relativize() ersetzen
|
||||
private URL generateURL(String link) throws MalformedURLException {
|
||||
|
||||
if (link.startsWith("//")) link = "http:" + link;
|
||||
|
||||
String resUrlStr = null;
|
||||
|
||||
if (link.indexOf("://") > 0) {
|
||||
resUrlStr = new String(link);
|
||||
} else if (link.startsWith("/")) {
|
||||
resUrlStr = new String(url.getProtocol() + "://" + url.getAuthority() + link);
|
||||
} else {
|
||||
String path = url.getPath();
|
||||
if (path.length() > 0) path = path.substring(0, path.lastIndexOf("/"));
|
||||
resUrlStr= new String(url.getProtocol() + "://" + url.getAuthority() + path + "/" + link);
|
||||
}
|
||||
|
||||
int i, j;
|
||||
while ( ((i = resUrlStr.indexOf("../")) > -1) && ((j = resUrlStr.indexOf("/", i+3)) > -1) ){
|
||||
resUrlStr = resUrlStr.substring(0,i) + resUrlStr.substring(j+1);
|
||||
}
|
||||
|
||||
//new URL(URLEncoder.encode(resUrlStr, "UTF-8"));
|
||||
|
||||
return new URL(resUrlStr);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
String urlString;
|
||||
if (args.length == 0) {
|
||||
// URL von der Kommandozeile lesen
|
||||
BufferedReader din = new BufferedReader(new InputStreamReader(System.in));
|
||||
System.out.print("URL: ");
|
||||
urlString = din.readLine();
|
||||
} else {
|
||||
urlString = args[0];
|
||||
}
|
||||
|
||||
// URL erzeugen
|
||||
URL url = new URL(urlString);
|
||||
|
||||
// SiteSize-Objekt erzeugen
|
||||
SiteSize siteSize = new SiteSize();
|
||||
|
||||
// Brutto-Größe messen und ausgeben
|
||||
System.out.println("\nSize of content: " + siteSize.getSize(url) + " bytes");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user