added UnArchiver api and SystemUtil

This commit is contained in:
Sebastian Sdorra
2010-12-23 18:03:47 +01:00
parent f289517653
commit 297d7f617d
5 changed files with 620 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.io;
//~--- non-JDK imports --------------------------------------------------------
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.util.ChecksumUtil;
import sonia.scm.util.IOUtil;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
/**
*
* @author Sebastian Sdorra
*/
public abstract class AbstractUnArchiver implements UnArchiver
{
/** Field description */
public static final String FILE_SOURCE_PROPERTIES = "scm-source.properties";
/** Field description */
public static final String PROPERTY_CHECKSUM = "scm.unarchiver.checksum";
/** Field description */
public static final String PROPERTY_SOURCEFILE = "scm.unarchiver.source";
/** the logger for AbstractUnArchiver */
private static final Logger logger =
LoggerFactory.getLogger(AbstractUnArchiver.class);
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param archive
* @param outputDirectory
*
* @throws IOException
*/
protected abstract void extractArchive(File archive, File outputDirectory)
throws IOException;
/**
* Method description
*
*
* @param archive
* @param outputDirectory
*
* @throws IOException
*/
@Override
public void extract(File archive, File outputDirectory) throws IOException
{
extract(archive, outputDirectory, false);
}
/**
* Method description
*
*
* @param archive
* @param outputDirectory
* @param force
*
* @throws IOException
*/
@Override
public void extract(File archive, File outputDirectory, boolean force)
throws IOException
{
if (!outputDirectory.exists())
{
IOUtil.mkdirs(outputDirectory);
extractAndCreateProperties(archive, outputDirectory);
}
else if (force || isModified(archive, outputDirectory))
{
IOUtil.delete(outputDirectory);
IOUtil.mkdirs(outputDirectory);
extractAndCreateProperties(archive, outputDirectory);
}
}
/**
* Method description
*
*
* @param archive
* @param outputDirectory
*
* @throws IOException
*/
private void extractAndCreateProperties(File archive, File outputDirectory)
throws IOException
{
extractArchive(archive, outputDirectory);
String checksum = ChecksumUtil.createChecksum(archive);
writeProperties(outputDirectory, checksum);
}
/**
* Method description
*
*
* @param outputDirectory
* @param checksum
*
* @throws IOException
*/
private void writeProperties(File outputDirectory, String checksum)
throws IOException
{
Properties properties = new Properties();
properties.setProperty(PROPERTY_CHECKSUM, checksum);
properties.setProperty(PROPERTY_SOURCEFILE,
outputDirectory.getAbsolutePath());
FileOutputStream output = null;
try
{
output = new FileOutputStream(new File(outputDirectory,
FILE_SOURCE_PROPERTIES));
properties.store(
output, AbstractUnArchiver.class.getName().concat(" properties"));
}
finally
{
IOUtil.close(output);
}
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param sourcePropsFile
*
* @return
*/
private String getChecksumProperty(File sourcePropsFile)
{
Properties properties = new Properties();
FileInputStream input = null;
try
{
input = new FileInputStream(sourcePropsFile);
properties.load(input);
}
catch (IOException ex)
{
logger.error(ex.getMessage(), ex);
}
finally
{
IOUtil.close(input);
}
return properties.getProperty(PROPERTY_CHECKSUM);
}
/**
* Method description
*
*
* @param archive
* @param outputDirectory
*
* @return
*/
private boolean isModified(File archive, File outputDirectory)
{
boolean modified = true;
File sourcePropsFile = new File(outputDirectory, FILE_SOURCE_PROPERTIES);
if (sourcePropsFile.exists())
{
String checksumProperty = getChecksumProperty(sourcePropsFile);
if (Util.isNotEmpty(checksumProperty))
{
try
{
String checksum = ChecksumUtil.createChecksum(archive);
if (checksumProperty.equals(checksum))
{
if (logger.isDebugEnabled())
{
logger.debug("file {} is not modified", archive.getPath());
}
modified = false;
}
else if (logger.isDebugEnabled())
{
logger.debug("file {} is modified", archive.getPath());
}
}
catch (IOException ex)
{
logger.error(ex.getMessage(), ex);
}
}
}
return modified;
}
}

View File

@@ -0,0 +1,71 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.io;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
/**
*
* @author Sebastian Sdorra
*/
public interface UnArchiver
{
/**
* Method description
*
*
* @param archive
* @param outputDirectory
* @param force
*
* @throws IOException
*/
public void extract(File archive, File outputDirectory, boolean force)
throws IOException;
/**
* Method description
*
*
* @param archive
* @param outputDirectory
*
* @throws IOException
*/
public void extract(File archive, File outputDirectory) throws IOException;
}

View File

@@ -0,0 +1,199 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.io;
//~--- non-JDK imports --------------------------------------------------------
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
*
* @author Sebastian Sdorra
*/
public class ZipUnArchiver extends AbstractUnArchiver
{
/** Field description */
public static final String EXTENSION = ".zip";
/** the logger for ZipUnArchiver */
private static final Logger logger =
LoggerFactory.getLogger(ZipUnArchiver.class);
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param archive
* @param outputDirectory
*
* @throws IOException
*/
@Override
protected void extractArchive(File archive, File outputDirectory)
throws IOException
{
if (logger.isDebugEnabled())
{
logger.debug("extract zip \"{}\" to \"{}\"", archive.getPath(),
outputDirectory.getAbsolutePath());
}
ZipInputStream input = null;
try
{
input = new ZipInputStream(new FileInputStream(archive));
ZipEntry entry = input.getNextEntry();
while (entry != null)
{
extractEntry(outputDirectory, input, entry);
entry = input.getNextEntry();
}
}
finally
{
IOUtil.close(input);
}
}
/**
* Method description
*
*
* @param outputDirectory
* @param name
*
* @return
*/
private File createFile(File outputDirectory, String name)
{
if (name.contains(".."))
{
throw new IllegalArgumentException("name is invalid");
}
return new File(outputDirectory, name);
}
/**
* Method description
*
*
* @param outputDirectory
* @param input
* @param entry
*
* @throws IOException
*/
private void extractEntry(File outputDirectory, ZipInputStream input,
ZipEntry entry)
throws IOException
{
try
{
File file = createFile(outputDirectory, entry.getName());
if (!entry.isDirectory())
{
File parent = file.getParentFile();
if (parent != null)
{
IOUtil.mkdirs(parent);
extractFile(input, file);
}
else
{
logger.warn("file {} has no parent", file.getPath());
}
}
else
{
IOUtil.mkdirs(file);
}
}
finally
{
input.closeEntry();
}
}
/**
* Method description
*
*
* @param input
* @param outputFile
*
* @throws IOException
*/
private void extractFile(ZipInputStream input, File outputFile)
throws IOException
{
if (logger.isDebugEnabled())
{
logger.debug("extract file {}", outputFile.getPath());
}
FileOutputStream output = null;
try
{
output = new FileOutputStream(outputFile);
IOUtil.copy(input, output);
}
finally
{
IOUtil.close(output);
}
}
}

View File

@@ -38,6 +38,8 @@ package sonia.scm.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.io.ZipUnArchiver;
//~--- JDK imports ------------------------------------------------------------
import java.io.Closeable;
@@ -161,6 +163,30 @@ public class IOUtil
}
}
/**
* Method description
*
*
* @param archive
* @param outputDirectory
*
* @throws IOException
*/
public static void extract(File archive, File outputDirectory)
throws IOException
{
String name = archive.getName().toLowerCase();
if (name.endsWith(ZipUnArchiver.EXTENSION))
{
new ZipUnArchiver().extract(archive, outputDirectory);
}
else
{
throw new IOException("no unarchiver found for ".concat(name));
}
}
/**
* Method description
*

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.util;
/**
*
* @author Sebastian Sdorra
*/
public class SystemUtil
{
/** Field description */
public static final String PROPERTY_OSNAME = "os.name";
/** Field description */
public static final String PROPERTY_VALUE_WINDOWS = "Windows";
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public static boolean isWindows()
{
String os = System.getProperty(PROPERTY_OSNAME);
return (os != null) && os.startsWith(PROPERTY_VALUE_WINDOWS);
}
}