1
0
mirror of https://github.com/essentials/Essentials.git synced 2025-08-15 11:04:29 +02:00

Add support for zipped User / Warp files

This commit is contained in:
snowleo
2012-11-03 00:24:54 +01:00
parent 3ce525f032
commit c60beda40f
4 changed files with 175 additions and 22 deletions

3
.gitignore vendored
View File

@@ -31,4 +31,5 @@ manifest.mf
*.iws
.idea/
EssentialsRelease/
EssentialsRelease/
/Essentials/dependency-reduced-pom.xml

View File

@@ -21,7 +21,17 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>0.11.4</version>
<version>0.11.6</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.4.1</version>
</dependency>
<!-- Test Depends -->
<dependency>
@@ -63,4 +73,37 @@
<version>1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>commons-io:*</include>
<include>org.apache.commons:*</include>
</includes>
</artifactSet>
<minimizeJar>true</minimizeJar>
<relocations>
<relocation>
<pattern>org.apache.commons</pattern>
<shadedPattern>net.ess3.commons</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -5,16 +5,23 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.UncheckedExecutionException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.regex.Pattern;
import net.ess3.api.IEssentials;
import net.ess3.api.InvalidNameException;
import net.ess3.utils.Util;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.io.IOUtils;
public abstract class StorageObjectMap<I> extends CacheLoader<String, I> implements IStorageObjectMap<I>
@@ -23,6 +30,7 @@ public abstract class StorageObjectMap<I> extends CacheLoader<String, I> impleme
private final transient File folder;
protected final transient Cache<String, I> cache = CacheBuilder.newBuilder().softValues().build(this);
protected final transient ConcurrentSkipListSet<String> keys = new ConcurrentSkipListSet<String>();
protected final transient ConcurrentSkipListMap<String, File> zippedfiles = new ConcurrentSkipListMap<String, File>();
public StorageObjectMap(final IEssentials ess, final String folderName)
{
@@ -51,20 +59,77 @@ public abstract class StorageObjectMap<I> extends CacheLoader<String, I> impleme
cache.invalidateAll();
for (String string : folder.list())
{
final File file = new File(folder, string);
if (!file.isFile() || !file.canRead())
{
continue;
}
if (string.endsWith(".yml"))
{
addFileToKeys(string.substring(0, string.length() - 4));
}
if (string.endsWith(".zip"))
{
addZipFile(file);
}
}
}
private void addFileToKeys(String filename)
{
try
{
final String name = Util.decodeFileName(filename);
keys.add(name.toLowerCase(Locale.ENGLISH));
}
catch (InvalidNameException ex)
{
ess.getLogger().log(Level.WARNING, "Invalid filename: " + filename, ex);
}
}
private final Pattern zipCheck = Pattern.compile("^[a-zA-Z0-9-]+\\.yml$");
private void addZipFile(File file)
{
try
{
ZipFile zipFile = new ZipFile(file);
try
{
if (!string.endsWith(".yml"))
Enumeration<ZipArchiveEntry> entries = zipFile.getEntriesInPhysicalOrder();
while (entries.hasMoreElements())
{
continue;
ZipArchiveEntry entry = entries.nextElement();
String name = entry.getName();
if (entry.isDirectory() || entry.getSize() == 0 || !zipCheck.matcher(name).matches())
{
continue;
}
try
{
String shortName = name.substring(0, name.length() - 4);
addFileToKeys(shortName);
final String decodedName = Util.decodeFileName(shortName).toLowerCase(Locale.ENGLISH);
zippedfiles.put(decodedName, file);
}
catch (InvalidNameException ex)
{
ess.getLogger().log(Level.WARNING, "Invalid filename " + name + " in " + file.getAbsoluteFile(), ex);
}
}
final String name = Util.decodeFileName(string.substring(0, string.length() - 4));
keys.add(name.toLowerCase(Locale.ENGLISH));
}
catch (InvalidNameException ex)
finally
{
ess.getLogger().log(Level.WARNING, "Invalid filename: " + string, ex);
zipFile.close();
}
}
catch (IOException ex)
{
ess.getLogger().log(Level.WARNING, "Error opening file " + file.getAbsolutePath(), ex);
}
}
});
}
@@ -98,13 +163,18 @@ public abstract class StorageObjectMap<I> extends CacheLoader<String, I> impleme
@Override
public void removeObject(final String name) throws InvalidNameException
{
keys.remove(name.toLowerCase(Locale.ENGLISH));
cache.invalidate(name.toLowerCase(Locale.ENGLISH));
String lowerCaseName = name.toLowerCase(Locale.ENGLISH);
keys.remove(lowerCaseName);
cache.invalidate(lowerCaseName);
final File file = getStorageFile(name);
if (file.exists())
{
file.delete();
}
if (zippedfiles.containsKey(lowerCaseName))
{
zippedfiles.put(lowerCaseName, null);
}
}
@Override
@@ -126,7 +196,14 @@ public abstract class StorageObjectMap<I> extends CacheLoader<String, I> impleme
{
throw new InvalidNameException(new IOException("Folder does not exists: " + folder));
}
return new File(folder, Util.sanitizeFileName(name) + ".yml");
String sanitizedFilename = Util.sanitizeFileName(name) + ".yml";
File file = new File(folder, sanitizedFilename);
if (!file.exists())
{
extractFileFromZip(name, sanitizedFilename, file);
}
return file;
}
@Override
@@ -134,4 +211,44 @@ public abstract class StorageObjectMap<I> extends CacheLoader<String, I> impleme
{
loadAllObjectsAsync();
}
private void extractFileFromZip(final String name, String sanitizedFilename, File file)
{
String lowerCaseName = name.toLowerCase(Locale.ENGLISH);
File zipFile = zippedfiles.get(lowerCaseName);
if (zipFile != null)
{
try
{
ZipFile zip = new ZipFile(zipFile);
try
{
ZipArchiveEntry entry = zip.getEntry(sanitizedFilename);
if (entry != null)
{
try
{
IOUtils.copy(zip.getInputStream(entry), new FileOutputStream(file));
}
catch (IOException ex)
{
ess.getLogger().log(Level.WARNING, "Failed to write file: " + file.getAbsolutePath(), ex);
}
}
else
{
ess.getLogger().log(Level.WARNING, "File " + file.getAbsolutePath() + " not found in zip file " + zipFile.getAbsolutePath());
}
}
finally
{
zip.close();
}
}
catch (IOException ex)
{
ess.getLogger().log(Level.WARNING, "File " + file.getAbsolutePath() + " could not be extracted from " + zipFile.getAbsolutePath(), ex);
}
}
}
}

View File

@@ -7,6 +7,7 @@ import java.util.List;
import java.util.logging.Logger;
import junit.framework.TestCase;
import net.ess3.api.IPlugin;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
@@ -82,17 +83,8 @@ public abstract class EssentialsTest extends TestCase
plugin = mock(IPlugin.class);
File tmp;
try
{
tmp = File.createTempFile("ess", "tmp");
}
catch (IOException ex)
{
throw new RuntimeException(ex);
}
tmp.deleteOnExit();
when(plugin.getDataFolder()).thenReturn(tmp.getParentFile());
File folder = FileUtils.getTempDirectory();
when(plugin.getDataFolder()).thenReturn(folder);
when(world.getName()).thenReturn("world");
ess = new Essentials(server, logger, plugin);