Crossfire JXClient, Trunk
ServerCache.java
Go to the documentation of this file.
1 /*
2  * This file is part of JXClient, the Fullscreen Java Crossfire Client.
3  *
4  * JXClient is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * JXClient is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with JXClient; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * Copyright (C) 2005-2008 Yann Chachkoff
19  * Copyright (C) 2006-2017,2019-2023 Andreas Kirschbaum
20  * Copyright (C) 2010-2012,2014-2018,2020-2023 Nicolas Weeger
21  */
22 
23 package com.realtime.crossfire.jxclient.metaserver;
24 
25 import java.io.BufferedWriter;
26 import java.io.IOException;
27 import java.io.LineNumberReader;
28 import java.io.Reader;
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.Files;
31 import java.nio.file.NoSuchFileException;
32 import java.nio.file.Path;
33 import java.util.HashMap;
34 import java.util.Map;
35 import java.util.Map.Entry;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
38 
43 public class ServerCache {
44 
48  @NotNull
49  public static final CharSequence DEFAULT_ENTRY_LOCALHOST = "0|localhost|0|--|Local server. Start server before you try to connect.|0|0|0|||";
50 
55  @NotNull
56  private final Map<String, Info> entries = new HashMap<>();
57 
61  @Nullable
62  private final Path file;
63 
68  public ServerCache(@Nullable final Path file) {
69  this.file = file;
70 
71  load();
72  }
73 
79  public void put(@NotNull final MetaserverEntry metaserverEntry) {
80  entries.put(metaserverEntry.getKey(), new Info(metaserverEntry));
81  }
82 
87  public void expire(final long timestamp) {
88  final long now = System.currentTimeMillis();
89  entries.values().removeIf(info -> now-info.getTimestamp() > timestamp);
90  }
91 
97  @NotNull
98  public Map<String, MetaserverEntry> getAll() {
99  final Map<String, MetaserverEntry> result = new HashMap<>();
100  for (Entry<String, Info> entry : entries.entrySet()) {
101  result.put(entry.getKey(), entry.getValue().getMetaserverEntry());
102  }
103  return result;
104  }
105 
109  private void load() {
110  if (file == null) {
111  return;
112  }
113 
114  try {
115  try (Reader isr = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
116  try (LineNumberReader lnr = new LineNumberReader(isr)) {
117  while (true) {
118  final String line = lnr.readLine();
119  if (line == null) {
120  break;
121  }
122 
123  final String[] tmp = line.split(" ", 2);
124  if (tmp.length != 2) {
125  System.err.println(file+":"+lnr.getLineNumber()+": syntax error");
126  continue;
127  }
128 
129  final long timestamp;
130  try {
131  timestamp = Long.parseLong(tmp[0]);
132  } catch (final NumberFormatException ignored) {
133  System.err.println(file+":"+lnr.getLineNumber()+": syntax error");
134  continue;
135  }
136  if (!addEntry(tmp[1], timestamp)) {
137  System.err.println(file+":"+lnr.getLineNumber()+": syntax error");
138  //noinspection UnnecessaryContinue
139  continue;
140  }
141  }
142  }
143  }
144  } catch (final NoSuchFileException ignored) {
145  // add default entries if the cache files does not exist
146  final long now = System.currentTimeMillis()-1;
148  addEntry("0|crossfire.metalforge.net|0|--|Release Candidate 1.12.0<br>Eden Prairie, MN US<br><a href=\"http://www.metalforge.net\">http://www.metalforge.net</a>|0|0|0|Standard|Standard|Standard", now);
149  addEntry("0|invidious2.meflin.net|0|--|<b>Invidious</b> - the next generation of Crossfire|0|0|0|Standard|Standard|Standard", now);
150  } catch (final IOException ex) {
151  System.err.println(file+": "+ex.getMessage());
152  }
153  }
154 
161  private boolean addEntry(@NotNull final CharSequence metaserverEntryLine, final long timestamp) {
162  final MetaserverEntry metaserverEntry = MetaserverEntryParser.parseEntry(metaserverEntryLine);
163  if (metaserverEntry == null) {
164  return false;
165  }
166 
167  entries.put(metaserverEntry.getKey(), new Info(metaserverEntry, timestamp));
168  return true;
169  }
170 
174  public void save() {
175  if (file == null) {
176  return;
177  }
178 
179  try {
181  } catch (final IOException ex) {
182  System.err.println(file+": "+ex.getMessage());
183  }
184  }
185 
191  private void saveInternal(@NotNull final Path file) throws IOException {
192  try (BufferedWriter bw = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
193  for (Info info : entries.values()) {
194  bw.write(Long.toString(info.getTimestamp()));
195  bw.write(' ');
196  bw.write(MetaserverEntryParser.format(info.getMetaserverEntry()));
197  bw.write('\n');
198  }
199  }
200  }
201 
202 }
com.realtime.crossfire.jxclient.metaserver.MetaserverEntry
Represents a response line from the metaserver.
Definition: MetaserverEntry.java:33
com.realtime.crossfire.jxclient.metaserver.MetaserverEntryParser.parseEntry
static MetaserverEntry parseEntry(@NotNull final CharSequence entry)
Parses a metaserver response line.
Definition: MetaserverEntryParser.java:140
com.realtime.crossfire.jxclient.metaserver.ServerCache.file
final Path file
The backing file.
Definition: ServerCache.java:62
com.realtime.crossfire.jxclient.metaserver.ServerCache.expire
void expire(final long timestamp)
Expires entries older than a given timestamp from the cache.
Definition: ServerCache.java:87
com.realtime.crossfire.jxclient.metaserver.ServerCache.entries
final Map< String, Info > entries
The cached entries.
Definition: ServerCache.java:56
com.realtime.crossfire.jxclient.metaserver.Info
An entry in the cache.
Definition: Info.java:32
com.realtime.crossfire.jxclient.metaserver.ServerCache.saveInternal
void saveInternal(@NotNull final Path file)
Saves all entries to the backing file.
Definition: ServerCache.java:191
com.realtime.crossfire.jxclient.metaserver.ServerCache.put
void put(@NotNull final MetaserverEntry metaserverEntry)
Adds an entry to the cache.
Definition: ServerCache.java:79
com.realtime.crossfire.jxclient.metaserver.ServerCache.DEFAULT_ENTRY_LOCALHOST
static final CharSequence DEFAULT_ENTRY_LOCALHOST
The default entry for the "localhost" server.
Definition: ServerCache.java:49
com.realtime.crossfire.jxclient.metaserver.MetaserverEntryParser
Parser for response lines of metaserver response lines.
Definition: MetaserverEntryParser.java:35
com.realtime.crossfire.jxclient.metaserver.ServerCache
Maintains a set of known servers backed up in a file.
Definition: ServerCache.java:43
com.realtime.crossfire.jxclient.metaserver.MetaserverEntryParser.format
static String format(@NotNull final MetaserverEntry entry)
Formats a metaserver entry that returns the metaserver entry when parse with parseEntry(CharSequence)...
Definition: MetaserverEntryParser.java:311
com.realtime.crossfire.jxclient.metaserver.ServerCache.load
void load()
Loads the entries from the backing file.
Definition: ServerCache.java:109
com.realtime.crossfire.jxclient.metaserver.MetaserverEntry.getKey
String getKey()
Returns the unique key for this entry.
Definition: MetaserverEntry.java:229
com.realtime.crossfire.jxclient.metaserver.ServerCache.ServerCache
ServerCache(@Nullable final Path file)
Creates a new instance.
Definition: ServerCache.java:68
com.realtime.crossfire.jxclient.metaserver.ServerCache.getAll
Map< String, MetaserverEntry > getAll()
Returns all cached entries.
Definition: ServerCache.java:98
com.realtime.crossfire.jxclient.metaserver.ServerCache.save
void save()
Saves all entries to the backing file.
Definition: ServerCache.java:174
com.realtime.crossfire.jxclient.metaserver.ServerCache.addEntry
boolean addEntry(@NotNull final CharSequence metaserverEntryLine, final long timestamp)
Parses a metaserver entry line and adds the result to entries.
Definition: ServerCache.java:161