Portal > Foren > Java > Allgemeine Java-Programmierung > Speichern von Einstellungen - Welche API?
Antwort
 
Themen-Optionen Thema durchsuchen
Alt 01.11.2005, 12:00 Nach oben    #1
Projektleiter
 
Registriert seit: 30.11.2005
Ort: Bottrop
Beiträge: 1.160
Standard Speichern von Einstellungen - Welche API?

Aktuell stoße ich an die Grenzen, ab denen die Properties-API beginnt, extrem hässlich zu werden, deswegen suche ich nach nem geeigneten Ersatz.

Die Preferences-API wäre ein möglicher Zufluchtspunkt, verfügt aber auch nicht über alle notwendigen Funktionen.

Vielleicht sollte ich erstmal erklären, worum es geht. Folgendes also:

Ich möchte nicht nur einfache String-String-Paare speichern, sondern String-List<Object>.
z.B. möchte ich eine Liste von FTP-Daten speichern können, ohne mit hundertausend Keys rumspielen zu müssen (ich hab's aktuell mit der Properties-API realisiert und es ist ekelhaft).

Zur Verdeutlichung, hier mal ein Beispiel dessen, was ich mir vorstelle:
PHP-Code:
Registry registry Registry.getInstance("ftpdata");
// oder Registry registry = Registry.getInstance(org.simpleedit.vfs.ftp.ConnectionData.class);

// Da eine Liste von "ConnectionData"-Beans gespeichert wurde, kann man diese gleich als Model verwenden
new JList(registry.getList("connectiondata"));

// schreiben der Liste:
List data = new ArrayList();
data.add(new ConnectionData("server""user""password"));
data.add(new ConnectionData("server""user""password"));
data.add(new ConnectionData("server""user""password"));
registry.set("connectiondata"data);

// Speichern der Registry
registry.store();

// Kind-Knoten ansprechen
Registry child registry.getNode("somechild");

// Einfaches name-value-Paar ansprechen
System.out.println(child.get("name")); 
Ein toller Zusatz wäre es, wenn die API auch noch XPath oder etwas ähnliches implementieren würde.
PHP-Code:
System.out.println(((ConnectionData)registry.xpath("/connectiondata[1]")).getUsername()); 
Mir wäre Commons-Configuration fast genug (auch wenn es nicht mit Serializable arbeitet), aber ich möchte mir nur ungern Commons-Collection (>500kb) und Commons-Lang (>130kb) mit aufhalsen müssen, für eine so kleine Aufgabe. Vorallem deshalb, weil ich die zusätzlichen Funktionen dieser Bibliotheken nicht verwenden würde.

Meine Frage wäre nun also, ob jemand von euch eine entsprechende API kennt oder selbst geschrieben hat und bereit wäre, sie mit dem Rest der Welt (bzw. für den Anfang mit mir) zu teilen.
Weil aktuell hab ich nur begrenzte Lust, sowas selbst zu schreiben.
__________________
Patrick Gotthardts Weblog.
pago ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.11.2005, 15:43 Nach oben    #2
Erfahrener Benutzer
 
Registriert seit: 28.08.2004
Ort: konstanz am bodensee
Beiträge: 190
Standard

hallo,
wenn es darum geht mehrdimensonale daten abzuspeichern sind properties sicherlich nicht das richtige format, entweder es ended wie du schon sagtest damit das man hunterttausend schlüssel für ein object/array hat oder man speichert die objekte/arrays als serialisierter werte, was aber dann unübersichtlich und umständlich wird wenn man von hand in der konfiguration rumhacken will...

ich benutze einen selbstgeschriebenen properties manager, der einfache arrays in einem wert speichert und das ganze auch noch für einen menschen zu lesen ist...
ein simples beispiel:
Code:
frame.background.color=[255,255,255]
frame.size=[600,400]
...
wenn man aber objekte speiechern will wird das umständlich weil man ja für jedes einzelne objekt ein mapping erstellen muss.

ich würde hier empfehlen die daten als xml datei zu speichern.
normalerweise müsste man ja auch hier ein spezielles mapping für jedes objekt erstellen, aber glücklicherweise gibt es ja genug kluge köpfe die sich um sowas gedanken machen...
so bin ich im letzen javamagazin auf XStream gestoßen, ein kleines framework (die grundausstattung ist 242kb sind zwar eigentlich auch viele nullen und einsen, aber immerhin ists mehr als die hälfte kleiner als die commons) mit dem man ohne mapping objekte und primitive datentypen serialisieren kann...
die verwendung ist sehr einfach, alle features werden durch eine Fassade angesprochen.

Code:
public class XTest {

	static class ConnectionData{
	 String host;
	 String user;
	 String pass;
	 public ConnectionData(String host,String user,String pass){
		 this.host=host;
		 this.user=user;
		 this.pass=pass;
	 }
	
	}
	public static void main(String[] args) {
		
		XStream x = new XStream();
		x.alias("ConnectionData",ConnectionData.class);
	   
		// serialisieren
		String xml = x.toXML(new ConnectionData("google.de","test","geheim"));

		// desierialisieren
		ConnectionData p = (ConnectionData)x.fromXML(xml);


	}

}
der xml output für Person sieht dann so aus
Code:
<ConnectionData>
  <host>google.de</host>
  <user>test</user>
  <pass>geheim</pass>
</ConnectionData>
du müsstest zwar die registry noch selbst programmieren, aber mit xstream währ der aufwand ziemlich gering...

mfg beny
beny_mcde ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.11.2005, 16:28 Nach oben    #3
Projektleiter
 
Registriert seit: 30.11.2005
Ort: Bottrop
Beiträge: 1.160
Standard

XStream sieht wirklich unglaublich gut aus! Das werde ich wohl nicht nur hier gebrauchen können.

Die ~250kb investiere ich gerne, weil ich dann direkt dom4j (~1MB) wieder rausschmeißen kann.
Wirklich sehr nett. Mal schaun, was ich damit alles anstellen kann. Danke dir.
__________________
Patrick Gotthardts Weblog.
pago ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 02.11.2005, 20:19 Nach oben    #4
Erfahrener Benutzer
 
Registriert seit: 28.08.2004
Ort: konstanz am bodensee
Beiträge: 190
Standard

unkomplizierter gehts nicht.
hab echt nicht geglaubt das es so einfach ist, bis ichs mit eigenen augen gesehen hab...
kein stundenlanges rumgefummel mehr mit dom bäumen und auch kein dauerndes implementieren von SAXHandler für jeden scheiß...

wenn du eine schöne registry gebaut hast kannst du sie ja mal hier posten oder mir an beny_mcde ät gmx.de mailen,
ich mach im moment alle config geschichten mit strings und das wird mit der zeit nerfig weil man die werte immer umwandeln muss bevor man sie verwenden kann...

werd mir bald mal zeit nehmen um xstream ein bischen auszutesten...
was performance und so angeht, insbesonders wenn man große objektbäume(z.b. eine komplette benutzeroberfläche usw) serialisiert...
beny_mcde ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 04.11.2005, 20:25 Nach oben    #5
Projektleiter
 
Registriert seit: 30.11.2005
Ort: Bottrop
Beiträge: 1.160
Standard

Soo... hab mir jetzt endlich was zusammengehackt.
PHP-Code:
/*
 * Copyright 2005 Patrick Gotthardt
 *
 * 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 org.simpleedit;

import com.thoughtworks.xstream.XStream;

import java.util.*;
import java.io.*;

/**
 * <p>This class is our powerful configuration-storage.</p>
 * <p>In opposition to the common Java APIs like Properties and
 * Preferences, this class is able to store every class you put into it.</p>
 * <p>While it offers this really nice feature, its API is really simple and
 * easy to use. Just use it like any other Map after you got an instance of it.</p>
 * <p>You'll have to use the static {@link #getInstance(String id)}-method to get
 * such an instance. Here is a simple example application:</p>
 *
 * <pre><code>public class RegistryTest {
    public static void main(String[] args) {
        // Obtain instance
        Registry reg = Registry.getInstance("test");
        // create a list and fill it
        List testList = new ArrayList();
        for(int i = 1; i &lt;= 5; i++) {
            testList.add("test "+i);
        }
        // store the list
        reg.put("list", testList);
        // store and close the registry
        reg.store();
        reg.close();
        System.out.println("Registry created successfully");

        System.out.println();
        System.out.println("Loading registry, printing list:");
        // Obtain a new instance
        reg = Registry.getInstance("test");
        testList = reg.getList("list");
        for (int i = 0; i &lt; testList.size(); i++) {
            System.out.println(testList.get(i));
        }
    }
}</code></pre>
 *
 * <p>We won't waste any time explaining the obvious things now, instead we'll
 * go to the more important parts.</p>
 * <p>There's a small difference between {@link #store()} and {@link #save()}.
 * The first one will call the second one, but hide its exception - if an exception
 * was raised. Ok, it won't "hide" it, but it'll print its stack trace.</p>
 * <p>If you're sure that no IOException will happen, then use {@link #store()}.</p>
 *
 * <p>The {@link #getInstance(String)}-method will use a cache so you won't get
 * two or more instances of one registry object. Otherwise one part of your application
 * might crash the changes of another part.</p>
 * <p>To remove a Registry from the cache (for example if you only need it
 * once in a long time and it'd make more sense to reload it when its required)
 * you'll have to call the {@link #close()} method.</p>
 * <p>Note that you won't be able to use the Registry-object after you
 * called {@link #close()}. You'll get a lot of NullPointerExceptions if you use
 * it after closing it, so just don't try.</p>
 *
 * <p>The registry won't store itself when it's closed. You'll have to do that manually.</p>
 *
 * <p>You might want to listen to changes of a specific registry (if you now some part of your application
 * depends on this: don't close the registry as all listeners will be lost!).</p>
 *
 * @author Patrick Gotthardt
 */
public class Registry implements Map {
    public static 
File configDirectory = new File(System.getProperty("user.home"), ".simpleedit/config");

    
// construction
    
private static XStream xstream;
    private static 
Map<FileRegistrycache = new HashMap<FileRegistry>();

    private static 
XStream getXStream() {
        if(
xstream == null) {
            
xstream = new XStream();
        }
        return 
xstream;
    }

    public static 
Registry getInstance(String id) {
        
File configFile = new File(configDirectoryid+".xml");
        
Registry cachedRegistry cache.get(configFile);
        if(
cachedRegistry != null) {
            return 
cachedRegistry;
        }
        
Registry reg = new Registry(configFile);
        if(
configFile.exists()) {
            
Reader config null;
            try {
                
config = new FileReader(configFile);
                
reg.delegate = (Map)getXStream().fromXML(config);
            } catch (
IOException e) {
                
e.printStackTrace();
            } 
finally {
                if(
config != null) {
                    try {
                        
config.close();
                    } catch (
IOException e) {
                        
e.printStackTrace();
                    }
                }
            }
        } else {
            
reg.delegate = new HashMap();
        }
        
cache.put(configFilereg);
        return 
reg;
    }

    
// implementation details
    
private Map delegate;
    private 
File configFile;
    private List<
RegistryListenerlisteners;

    protected 
Registry(File configFile) {
        
this.configFile configFile;
        
listeners = new ArrayList<RegistryListener>();
    }

    public 
void store() {
        try {
            
save();
        } catch (
IOException e) {
            
e.printStackTrace();
        }
    }

    public 
void save() throws IOException {
        
Writer out = new FileWriter(configFile);
        
getXStream().toXML(delegateout);
        
out.close();
    }

    public 
void close() {
        
cache.remove(configFile);
        
delegate null;
        
configFile null;
    }

    
// event-stuff
    
public void addRegistryListener(RegistryListener l) {
        
listeners.add(l);
    }

    public 
void removeRegistryListener(RegistryListener l) {
        
listeners.remove(l);
    }

    protected 
void firePropertyChangedEvent(RegistryEvent e) {
        for(
int i listeners.size()-1>= 0i--) {
            
listeners.get(i).propertyChanged(e);
        }
    }

    protected 
void firePropertyRemovedEvent(RegistryEvent e) {
        for(
int i listeners.size()-1>= 0i--) {
            
listeners.get(i).propertyRemoved(e);
        }
    }

    
// getXYZ-methods
    
public List getList(Object key) {
        return (List)
get(key);
    }

    public 
Map getMap(Object key) {
        return (
Map)get(key);
    }

    public 
int getInt(Object key) {
        return ((Integer)
get(key)).intValue();
    }

    public 
boolean is(Object key) {
        return ((Boolean)
get(key)).booleanValue();
    }

    public 
String getString(Object key) {
        return (String)
get(key);
    }

    
// Simply delegate every Map-interface-method to delegate
    
public void clear() {
        
delegate.clear();
    }

    public 
boolean containsKey(Object key) {
        return 
delegate.containsKey(key);
    }

    public 
boolean containsValue(Object value) {
        return 
delegate.containsValue(value);
    }

    public 
Set entrySet() {
        return 
delegate.entrySet();
    }

    public 
boolean equals(Object o) {
        return 
delegate.equals(o);
    }

    public 
Object get(Object key) {
        return 
delegate.get(key);
    }

    public 
int hashCode() {
        return 
delegate.hashCode();
    }

    public 
boolean isEmpty() {
        return 
delegate.isEmpty();
    }

    public 
Set keySet() {
        return 
delegate.keySet();
    }

    public 
Object put(Object keyObject value) {
        
Object result delegate.put(keyvalue);
        
firePropertyChangedEvent(new RegistryEvent(thiskey));
        return 
result;
    }

    public 
void putAll(Map t) {
        
delegate.putAll(t);
        
Set keys t.keySet();
        for(
Object key keys) {
            
firePropertyChangedEvent(new RegistryEvent(thiskey));
        }
    }

    public 
Object remove(Object key) {
        
firePropertyRemovedEvent(new RegistryEvent(thiskey));
        return 
delegate.remove(key);
    }

    public 
int size() {
        return 
delegate.size();
    }

    public 
Collection values() {
        return 
delegate.values();
    }

PHP-Code:
/*
 * Copyright 2005 Patrick Gotthardt
 *
 * 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 org.simpleedit;

import java.util.EventObject;

/**
 * @author Patrick Gotthardt
 */
public class RegistryEvent extends EventObject {
    private 
Object key;

    public 
RegistryEvent(Object sourceObject key) {
        
super(source);
        
this.key key;
    }

    public 
Object getKey() {
        return 
key;
    }

    public 
Registry getRegistry() {
        return (
Registry)getSource();
    }

PHP-Code:
package org.simpleedit;

/**
 * @author Patrick Gotthardt
 */
public interface RegistryListener {
    public 
void propertyChanged(RegistryEvent event);
    public 
void propertyRemoved(RegistryEvent event);

Wie deutlich zu erkennen ist, fehlt noch ein Großteil der Dokumentation, aber ich denke, dass das ganze so akzeptabel ist.

Kommentare, Vorschläge, etc. wären mir lieb.
(Ich hab da jetzt nicht allzu lang drüber nachgedacht.)
__________________
Patrick Gotthardts Weblog.
pago ist offline  
Diesen Beitrag zu to del.icio.us hinzufügen!Diesen Beitrag zu Technorati hinzufügen!Diesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
PingBacks sind an
RefBacks sind aus

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
[Anmeldeseite]Firefox will Passwort speichern WarrenFaith HTML, XML und CSS 13 10.09.2007 11:54
DAtensatz in Variable Speichern und in eine Tabbele speichern kampfgnom Datenbanken 11 10.12.2006 20:45
Schwachstelle in PHP - Umgehung von Einstellungen möglich WarrenFaith Nachrichten 9 14.09.2006 17:40
[Rezension] Professionelle PHP 5-Programmierung, Ben Literatur 11 27.07.2006 20:48


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:28 Uhr.


Powered by vBulletin® Version 3.7.4 (Deutsch)
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45