You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by da...@apache.org on 2006/04/06 05:15:43 UTC
svn commit: r391886 - in /geronimo/branches/1.1/modules:
kernel/src/java/org/apache/geronimo/kernel/config/
kernel/src/java/org/apache/geronimo/kernel/config/xstream/
system/src/java/org/apache/geronimo/system/configuration/
system/src/test/org/apache/...
Author: dain
Date: Wed Apr 5 20:15:39 2006
New Revision: 391886
URL: http://svn.apache.org/viewcvs?rev=391886&view=rev
Log:
Added sha-1 based checksum on config.ser files so we can determine if a configuration has been modified.
If a configuration has been modified, a warnign will be logged at startup.
Added:
geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ConfigurationStoreUtil.java
geronimo/branches/1.1/modules/system/src/test/org/apache/geronimo/system/configuration/ConfigurationStoreUtilTest.java
Modified:
geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationData.java
geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/xstream/XStreamConfigurationMarshaler.java
geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ExecutableConfigurationUtil.java
geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/RepositoryConfigurationStore.java
Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationData.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationData.java?rev=391886&r1=391885&r2=391886&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationData.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/ConfigurationData.java Wed Apr 5 20:15:39 2006
@@ -132,6 +132,10 @@
return gbeanState.addGBean(name, gbeanInfo, naming, environment);
}
+ public GBeanState getGbeanState() {
+ return gbeanState;
+ }
+
public Map getChildConfigurations() {
return Collections.unmodifiableMap(childConfigurations);
}
Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/xstream/XStreamConfigurationMarshaler.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/xstream/XStreamConfigurationMarshaler.java?rev=391886&r1=391885&r2=391886&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/xstream/XStreamConfigurationMarshaler.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/xstream/XStreamConfigurationMarshaler.java Wed Apr 5 20:15:39 2006
@@ -43,7 +43,7 @@
public ConfigurationData readConfigurationData(InputStream in) throws IOException, ClassNotFoundException {
PushbackInputStream pushbackInputStream = new PushbackInputStream(in, 2);
byte[] streamHeader = new byte[2];
- pushbackInputStream.read(streamHeader);
+ if (pushbackInputStream.read(streamHeader) != 2) throw new AssertionError("Cound not read stream header");
pushbackInputStream.unread(streamHeader);
// if this is a serialized config, fallback to the serialization marshaler
Added: geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ConfigurationStoreUtil.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ConfigurationStoreUtil.java?rev=391886&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ConfigurationStoreUtil.java (added)
+++ geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ConfigurationStoreUtil.java Wed Apr 5 20:15:39 2006
@@ -0,0 +1,217 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * 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.apache.geronimo.system.configuration;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.LineNumberReader;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConfigurationStoreUtil {
+ private static final Log log = LogFactory.getLog(ConfigurationStoreUtil.class);
+
+ public static void writeChecksumFor(File file) throws IOException {
+ // check if the sum already exists
+ File sumFile = new File(file.getParentFile(), file.getName() + ".sha1");
+ if (sumFile.exists()) {
+ throw new IOException("Sum file already exists");
+ }
+
+ // calculate the checksum
+ String actualChecksum;
+ try {
+ actualChecksum = calculateChecksum(file);
+ } catch (NoSuchAlgorithmException e) {
+ throw new IOException("SHA-1 algorithm not available");
+ }
+
+ // write it
+ FileWriter writer = new FileWriter(sumFile);
+ try {
+ writer.write(actualChecksum);
+ } finally {
+ try {
+ writer.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+
+ public static boolean verifyChecksum(File file) {
+ String expectedChecksum = getExpectedChecksum(file);
+ if (expectedChecksum == null) {
+ // log message already printed
+ return false;
+ }
+
+ String actualChecksum = getActualChecksum(file);
+ if (actualChecksum == null) {
+ // log message already printed
+ return false;
+ }
+
+
+ if (!actualChecksum.equals(expectedChecksum)) {
+ log.warn("Configuration file was modified: " + file.getAbsolutePath());
+ return false;
+ }
+
+ return true;
+ }
+
+ public static String getExpectedChecksum(File file) {
+ File sumFile = new File(file.getParentFile(), file.getName() + ".sha1");
+ if (!sumFile.exists()) {
+ log.warn("Checksum file not found: " + sumFile.getAbsolutePath());
+ return null;
+ }
+ if (!sumFile.canRead()) {
+ log.warn("Checksum file is not readable: " + sumFile.getAbsolutePath());
+ return null;
+ }
+ LineNumberReader lineNumberReader = null;
+ try {
+ lineNumberReader = new LineNumberReader(new FileReader(sumFile));
+ String expectedChecksum = lineNumberReader.readLine();
+ if (expectedChecksum == null) {
+ log.error("Checksum file was empty: " + sumFile.getAbsolutePath());
+ return null;
+ }
+ return expectedChecksum.trim();
+ } catch (IOException e) {
+ log.error("Unable to read checksum file: " + sumFile.getAbsolutePath(), e);
+ } finally {
+ if (lineNumberReader != null) {
+ try {
+ lineNumberReader.close();
+ } catch (IOException ignored) {
+ }
+ }
+
+ }
+ return null;
+ }
+
+ public static String getActualChecksum(File file) {
+ try {
+ return calculateChecksum(file);
+ } catch (Exception e) {
+ log.error("Unable to calculate checksum for configuration file: " + file.getAbsolutePath(), e);
+ }
+ return null;
+ }
+
+ private static String calculateChecksum(File file) throws NoSuchAlgorithmException, IOException {
+ InputStream stream = new FileInputStream(file);
+
+ try {
+ MessageDigest digester = MessageDigest.getInstance("SHA-1");
+ digester.reset();
+
+ byte buf[] = new byte[4096];
+ int len = 0;
+
+ while ((len = stream.read(buf, 0, 1024)) != -1) {
+ digester.update(buf, 0, len);
+ }
+
+ String actualChecksum = encode(digester.digest());
+ return actualChecksum;
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+
+ private static String encode(byte[] binaryData) {
+ if (binaryData.length != 16 && binaryData.length != 20) {
+ int bitLength = binaryData.length * 8;
+ throw new IllegalArgumentException("Unrecognised length for binary data: " + bitLength + " bits");
+ }
+
+ String retValue = "";
+
+ for (int i = 0; i < binaryData.length; i++) {
+ String t = Integer.toHexString(binaryData[i] & 0xff);
+
+ if (t.length() == 1) {
+ retValue += ("0" + t);
+ } else {
+ retValue += t;
+ }
+ }
+
+ return retValue.trim();
+ }
+
+ public static class ChecksumOutputStream extends OutputStream {
+ private final OutputStream out;
+ private MessageDigest digester;
+
+ public ChecksumOutputStream(OutputStream out) throws IOException {
+ this.out = out;
+ try {
+ digester = MessageDigest.getInstance("SHA-1");
+ digester.reset();
+ } catch (NoSuchAlgorithmException e) {
+ throw new IOException("SHA-1 algorithm not available");
+ }
+ }
+
+ public String getChecksum() {
+ String actualChecksum = encode(digester.digest());
+ return actualChecksum;
+ }
+
+ public void write(int b) throws IOException {
+ digester.update((byte) b);
+ out.write(b);
+ }
+
+ public void write(byte[] b) throws IOException {
+ digester.update(b);
+ out.write(b);
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException {
+ digester.update(b, off, len);
+ out.write(b, off, len);
+ }
+
+ public void flush() throws IOException {
+ out.flush();
+ }
+
+ public void close() throws IOException {
+ out.close();
+ }
+ }
+}
Modified: geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ExecutableConfigurationUtil.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ExecutableConfigurationUtil.java?rev=391886&r1=391885&r2=391886&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ExecutableConfigurationUtil.java (original)
+++ geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/ExecutableConfigurationUtil.java Wed Apr 5 20:15:39 2006
@@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
@@ -88,8 +89,19 @@
public static void writeConfiguration(ConfigurationData configurationData, JarOutputStream out) throws IOException {
// save the persisted form in the source directory
out.putNextEntry(new ZipEntry("META-INF/config.ser"));
+ ConfigurationStoreUtil.ChecksumOutputStream sumOut = new ConfigurationStoreUtil.ChecksumOutputStream(out);
try {
- ConfigurationUtil.writeConfigurationData(configurationData, out);
+ ConfigurationUtil.writeConfigurationData(configurationData, sumOut);
+ } finally {
+ out.closeEntry();
+ }
+
+ // write the checksum file
+ out.putNextEntry(new ZipEntry("META-INF/config.ser.sha1"));
+ try {
+ OutputStreamWriter writer = new OutputStreamWriter(out);
+ writer.write(sumOut.getChecksum());
+ writer.flush();
} finally {
out.closeEntry();
}
@@ -116,6 +128,7 @@
}
}
}
+ ConfigurationStoreUtil.writeChecksumFor(configSer);
}
private static Collection listRecursiveFiles(File file) {
Modified: geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/RepositoryConfigurationStore.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/RepositoryConfigurationStore.java?rev=391886&r1=391885&r2=391886&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/RepositoryConfigurationStore.java (original)
+++ geronimo/branches/1.1/modules/system/src/java/org/apache/geronimo/system/configuration/RepositoryConfigurationStore.java Wed Apr 5 20:15:39 2006
@@ -96,6 +96,8 @@
throw new InvalidConfigException("Can not read configuration META-INF/config.ser file: " + serFile);
}
+ ConfigurationStoreUtil.verifyChecksum(serFile);
+
InputStream in = new FileInputStream(serFile);
try {
configurationData = ConfigurationUtil.readConfigurationData(in);
@@ -126,7 +128,6 @@
return configurationData;
}
-
public boolean containsConfiguration(Artifact configId) {
File location = repository.getLocation(configId);
Added: geronimo/branches/1.1/modules/system/src/test/org/apache/geronimo/system/configuration/ConfigurationStoreUtilTest.java
URL: http://svn.apache.org/viewcvs/geronimo/branches/1.1/modules/system/src/test/org/apache/geronimo/system/configuration/ConfigurationStoreUtilTest.java?rev=391886&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/system/src/test/org/apache/geronimo/system/configuration/ConfigurationStoreUtilTest.java (added)
+++ geronimo/branches/1.1/modules/system/src/test/org/apache/geronimo/system/configuration/ConfigurationStoreUtilTest.java Wed Apr 5 20:15:39 2006
@@ -0,0 +1,152 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * 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.apache.geronimo.system.configuration;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import junit.framework.TestCase;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConfigurationStoreUtilTest extends TestCase {
+ private File testFile;
+ private static final String BAD_SUM = "Stinky Cheese";
+ private File sumFile;
+
+ public void testChecksum() throws IOException {
+ String actualChecksum = ConfigurationStoreUtil.getActualChecksum(testFile);
+ assertNotNull(actualChecksum);
+
+ // we haven't writen the checksum yet so it should be null
+ String expectedChecksum = ConfigurationStoreUtil.getExpectedChecksum(testFile);
+ assertNull(expectedChecksum);
+
+ // write the sum file
+ ConfigurationStoreUtil.writeChecksumFor(testFile);
+
+ // get the new sum
+ expectedChecksum = ConfigurationStoreUtil.getExpectedChecksum(testFile);
+ assertNotNull(expectedChecksum);
+
+ // should be the same
+ assertEquals(expectedChecksum, actualChecksum);
+
+ assertTrue(ConfigurationStoreUtil.verifyChecksum(testFile));
+ }
+
+ public void testBadChecksum() throws IOException {
+ String actualChecksum = ConfigurationStoreUtil.getActualChecksum(testFile);
+ assertNotNull(actualChecksum);
+
+ // we haven't writen the checksum yet so it should be null
+ String expectedChecksum = ConfigurationStoreUtil.getExpectedChecksum(testFile);
+ assertNull(expectedChecksum);
+
+ // write the bad sum file
+ FileWriter writer = new FileWriter(sumFile);
+ writer.write(BAD_SUM);
+ writer.close();
+
+ // get the new sum
+ expectedChecksum = ConfigurationStoreUtil.getExpectedChecksum(testFile);
+ assertEquals(BAD_SUM, expectedChecksum);
+
+ // should not be the same
+ assertFalse(expectedChecksum.equals(actualChecksum));
+
+ assertFalse(ConfigurationStoreUtil.verifyChecksum(testFile));
+ }
+
+ public void testEmptyFile() throws IOException {
+ testFile.delete();
+ testFile.createNewFile();
+
+ String actualChecksum = ConfigurationStoreUtil.getActualChecksum(testFile);
+ assertNotNull(actualChecksum);
+
+
+ // we haven't writen the checksum yet so it should be null
+ String expectedChecksum = ConfigurationStoreUtil.getExpectedChecksum(testFile);
+ assertNull(expectedChecksum);
+
+ // create an empty sum file
+ sumFile.createNewFile();
+
+ expectedChecksum = ConfigurationStoreUtil.getExpectedChecksum(testFile);
+ assertNull(expectedChecksum);
+ }
+
+ public void testOutputStreamChecksum() throws Exception {
+ testFile.delete();
+ ConfigurationStoreUtil.ChecksumOutputStream out = new ConfigurationStoreUtil.ChecksumOutputStream(new FileOutputStream(testFile));
+ OutputStreamWriter writer = new OutputStreamWriter(out);
+ writer.write("cvmnxc,vmnx,cmvn,xmcvlsjnv,mcnvjshfgmsnfvoiwrhjfjlnvkjhnfgornfgonviohjfowehldnf\n");
+ writer.write("uncwcdwncicjevhinfmcnrfviefjnvun4d49jf93efv78y4bhc3hf3jdf83hf8ejkdhyfuh9iuwdhfw\n");
+ writer.write("cvmnxc,vmnx,cmvn,xmcvlsjnv,mcnvjshfgmsnfvoiwrhjfjlnvkjhnfgornfgonviohjfowehldnf\n");
+ writer.write("uncwcdwncicjevhinfmcnrfviefjnvun4d49jf93efv78y4bhc3hf3jdf83hf8ejkdhyfuh9iuwdhfw\n");
+ writer.write("cvmnxc,vmnx,cmvn,xmcvlsjnv,mcnvjshfgmsnfvoiwrhjfjlnvkjhnfgornfgonviohjfowehldnf\n");
+ writer.write("uncwcdwncicjevhinfmcnrfviefjnvun4d49jf93efv78y4bhc3hf3jdf83hf8ejkdhyfuh9iuwdhfw\n");
+ writer.write("cvmnxc,vmnx,cmvn,xmcvlsjnv,mcnvjshfgmsnfvoiwrhjfjlnvkjhnfgornfgonviohjfowehldnf\n");
+ writer.write("uncwcdwncicjevhinfmcnrfviefjnvun4d49jf93efv78y4bhc3hf3jdf83hf8ejkdhyfuh9iuwdhfw\n");
+ writer.write("cvmnxc,vmnx,cmvn,xmcvlsjnv,mcnvjshfgmsnfvoiwrhjfjlnvkjhnfgornfgonviohjfowehldnf\n");
+ writer.write("uncwcdwncicjevhinfmcnrfviefjnvun4d49jf93efv78y4bhc3hf3jdf83hf8ejkdhyfuh9iuwdhfw\n");
+ writer.write("cvmnxc,vmnx,cmvn,xmcvlsjnv,mcnvjshfgmsnfvoiwrhjfjlnvkjhnfgornfgonviohjfowehldnf\n");
+ writer.write("uncwcdwncicjevhinfmcnrfviefjnvun4d49jf93efv78y4bhc3hf3jdf83hf8ejkdhyfuh9iuwdhfw\n");
+ writer.write("cvmnxc,vmnx,cmvn,xmcvlsjnv,mcnvjshfgmsnfvoiwrhjfjlnvkjhnfgornfgonviohjfowehldnf\n");
+ writer.write("uncwcdwncicjevhinfmcnrfviefjnvun4d49jf93efv78y4bhc3hf3jdf83hf8ejkdhyfuh9iuwdhfw\n");
+ writer.write("end\n");
+ writer.close();
+
+ String actualChecksum = out.getChecksum();
+ String expectedChecksum = ConfigurationStoreUtil.getActualChecksum(testFile);
+ assertEquals(expectedChecksum, actualChecksum);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ testFile = new File("target/checksumTest/test.data");
+ testFile.getParentFile().mkdirs();
+ FileWriter writer = new FileWriter(testFile);
+ writer.write("lflkfjkljkldfaskljsadflkjasdflweoiurhlmvniouwehnflikmnfubhgkajnbfgk;ausuhfoubhr\n");
+ writer.write("uweyrueruewrncihweruhnwjnfduhfrwejbnruhnfuhfjnceucnfierouhfljkdnciuehfinbvcusdu\n");
+ writer.write("lflkfjkljkldfaskljsadflkjasdflweoiurhlmvniouwehnflikmnfubhgkajnbfgk;ausuhfoubhr\n");
+ writer.write("uweyrueruewrncihweruhnwjnfduhfrwejbnruhnfuhfjnceucnfierouhfljkdnciuehfinbvcusdu\n");
+ writer.write("lflkfjkljkldfaskljsadflkjasdflweoiurhlmvniouwehnflikmnfubhgkajnbfgk;ausuhfoubhr\n");
+ writer.write("uweyrueruewrncihweruhnwjnfduhfrwejbnruhnfuhfjnceucnfierouhfljkdnciuehfinbvcusdu\n");
+ writer.write("lflkfjkljkldfaskljsadflkjasdflweoiurhlmvniouwehnflikmnfubhgkajnbfgk;ausuhfoubhr\n");
+ writer.write("uweyrueruewrncihweruhnwjnfduhfrwejbnruhnfuhfjnceucnfierouhfljkdnciuehfinbvcusdu\n");
+ writer.write("lflkfjkljkldfaskljsadflkjasdflweoiurhlmvniouwehnflikmnfubhgkajnbfgk;ausuhfoubhr\n");
+ writer.write("uweyrueruewrncihweruhnwjnfduhfrwejbnruhnfuhfjnceucnfierouhfljkdnciuehfinbvcusdu\n");
+ writer.write("lflkfjkljkldfaskljsadflkjasdflweoiurhlmvniouwehnflikmnfubhgkajnbfgk;ausuhfoubhr\n");
+ writer.write("uweyrueruewrncihweruhnwjnfduhfrwejbnruhnfuhfjnceucnfierouhfljkdnciuehfinbvcusdu\n");
+ writer.write("end\n");
+ writer.close();
+ sumFile = new File(testFile.getParentFile(), testFile.getName() + ".sha1");
+ sumFile.delete();
+ }
+
+ protected void tearDown() throws Exception {
+ testFile.delete();
+ sumFile.delete();
+ super.tearDown();
+ }
+}