debian/0000775000000000000000000000000013110576334007173 5ustar debian/control0000664000000000000000000001256113077354155010612 0ustar Source: activemq Section: java Priority: optional Maintainer: Debian Java Maintainers Uploaders: Damien Raude-Morvan Build-Depends: cdbs, debhelper (>= 7), default-jdk, maven-debian-helper (>= 1.4) Build-Depends-Indep: ant, default-jdk-doc, glassfish-javaee (>= 2.1.1-b31g), libactivemq-activeio-java, libactivemq-protobuf-java, libaopalliance-java, libaxis-java, libaxis-java-doc, libbuild-helper-maven-plugin-java, libcommons-beanutils-java, libcommons-beanutils-java-doc, libcommons-collections3-java, libcommons-daemon-java, libcommons-httpclient-java, libcommons-io-java, libcommons-logging-java, libcommons-logging-java-doc, libcommons-net2-java, libcommons-net2-java-doc, libcommons-pool-java, libcommons-pool-java-doc, libgentlyweb-utils-java, libgentlyweb-utils-java-doc, libjasypt-java, libjasypt-java-doc, libjavacc-maven-plugin-java, libjdom1-java (>= 1.0), libjdom1-java-doc, libjettison-java, libjosql-java, libjosql-java-doc, liblog4j1.2-java, libmaven-antrun-plugin-java, libmaven-bundle-plugin-java, libmaven-enforcer-plugin-java, libmaven-install-plugin-java, libmaven-javadoc-plugin-java, libmaven-shade-plugin-java, libmaven-war-plugin-java, libslf4j-java, libspring-context-java (>= 3.0.5.RELEASE-3), libspring-jms-java, libspring-test-java, libspring-web-java, libspring-web-servlet-java, libstax-java, libxalan2-java, libxbean-java (>= 3.7), libxbean-java-doc, libxpp3-java, libxstream-java (>= 1.4) Standards-Version: 3.9.3 Vcs-Git: git://git.debian.org/pkg-java/activemq.git Vcs-Browser: http://git.debian.org/?p=pkg-java/activemq.git Homepage: http://activemq.apache.org Package: libactivemq-java Architecture: all Depends: ${maven:Depends}, ${misc:Depends} Recommends: ${maven:OptionalDepends} Suggests: libactivemq-java-doc Description: Java message broker core libraries Apache ActiveMQ is a message broker built around Java Message Service (JMS) API : allow sending messages between two or more clients in a loosely coupled, reliable, and asynchronous way. . This message broker supports : * JMS 1.1 and J2EE 1.4 with support for transient, persistent, transactional and XA messaging * Spring Framework, CXF and Axis integration * pluggable transport protocols such as in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA * persistence using JDBC along with journaling * OpenWire (cross language wire protocol) and Stomp (Streaming Text Orientated Messaging Protocol) protocols . This package contains a core Java library for ActiveMQ. Package: libactivemq-java-doc Architecture: all Section: doc Depends: ${maven:DocDepends}, ${misc:Depends} Recommends: ${maven:DocOptionalDepends} Suggests: libactivemq-java Description: Java message broker core libraries - documentation Apache ActiveMQ is a message broker built around Java Message Service (JMS) API : allow sending messages between two or more clients in a loosely coupled, reliable, and asynchronous way. . This message broker supports : * JMS 1.1 and J2EE 1.4 with support for transient, persistent, transactional and XA messaging * Spring Framework, CXF and Axis integration * pluggable transport protocols such as in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA * persistence using JDBC along with journaling * OpenWire (cross language wire protocol) and Stomp (Streaming Text Orientated Messaging Protocol) protocols . This package contains Javadoc API for libactivemq-java. Package: activemq Architecture: all Depends: adduser (>= 3.11), libactivemq-java (= ${source:Version}), openjdk-6-jre-headless | java6-runtime-headless, ${misc:Depends} Description: Java message broker - server Apache ActiveMQ is a message broker built around Java Message Service (JMS) API : allow sending messages between two or more clients in a loosely coupled, reliable, and asynchronous way. . This message broker supports : * JMS 1.1 and J2EE 1.4 with support for transient, persistent, transactional and XA messaging * Spring Framework, CXF and Axis integration * pluggable transport protocols such as in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA * persistence using JDBC along with journaling * OpenWire (cross language wire protocol) and Stomp (Streaming Text Orientated Messaging Protocol) protocols . This package contains a server installation of ActiveMQ. debian/activemq.default0000664000000000000000000000030313077354155012355 0ustar # Whether to start ActiveMQ (as a daemon or not) NO_START=0 # Use Debian create user to run ActiveMQ process ACTIVEMQ_USER="activemq" # Time to wait for the server to die, in seconds DIETIME=2 debian/patches/0000775000000000000000000000000013077354155010631 5ustar debian/patches/exclude_spring_osgi.diff0000664000000000000000000000244313077354155015522 0ustar Description: Disable Spring OSGi support because it's not yet in Debian. Author: Damien Raude-Morvan Last-Update: 2011-06-21 Forwarded: not-needed --- a/activemq-spring/src/main/java/org/apache/activemq/hooks/SpringContextHook.java +++ b/activemq-spring/src/main/java/org/apache/activemq/hooks/SpringContextHook.java @@ -23,7 +23,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext; public class SpringContextHook implements Runnable, ApplicationContextAware { @@ -34,13 +33,13 @@ if (applicationContext instanceof ConfigurableApplicationContext) { ((ConfigurableApplicationContext) applicationContext).close(); } - if (applicationContext instanceof OsgiBundleXmlApplicationContext){ + /*if (applicationContext instanceof OsgiBundleXmlApplicationContext){ try { ((OsgiBundleXmlApplicationContext)applicationContext).getBundle().stop(); } catch (BundleException e) { LOG.info("Error stopping OSGi bundle " + e, e); } - } + }*/ } debian/patches/drop_derby_use.diff0000664000000000000000000000231613077354155014472 0ustar Description: Drop usage of derby inside activemq-core/src/main/java/org/apache/activemq/store/jdbc/DataSourceSupport.java Author: Damien Raude-Morvan Last-Update: 2011-05-08 Forwarded: not-needed --- a/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DataSourceSupport.java +++ b/activemq-core/src/main/java/org/apache/activemq/store/jdbc/DataSourceSupport.java @@ -22,7 +22,7 @@ import javax.sql.DataSource; import org.apache.activemq.util.IOHelper; -import org.apache.derby.jdbc.EmbeddedDataSource; +//import org.apache.derby.jdbc.EmbeddedDataSource; /** * A helper class which provides a factory method to create a default @@ -83,10 +83,11 @@ System.setProperty("derby.storage.fileSyncTransactionLog", "true"); System.setProperty("derby.storage.pageCacheSize", "100"); - final EmbeddedDataSource ds = new EmbeddedDataSource(); - ds.setDatabaseName("derbydb"); - ds.setCreateDatabase("create"); - return ds; + //final EmbeddedDataSource ds = new EmbeddedDataSource(); + //ds.setDatabaseName("derbydb"); + //ds.setCreateDatabase("create"); + //return ds; + return null; } public String toString() { debian/patches/activemq-admin.patch0000664000000000000000000000117013077354155014550 0ustar Description: Fix running activemq-admin without any argument which led to "132: [: =: unexpected operator". Author: Mathieu Mitchell Last-Update: 2012-03-05 Forwarded: no --- a/assembly/src/release/bin/activemq-admin +++ b/assembly/src/release/bin/activemq-admin @@ -146,7 +146,7 @@ # Set default classpath ACTIVEMQ_CLASSPATH="${ACTIVEMQ_CONF};"$ACTIVEMQ_CLASSPATH -if [ ""$1 = "start" ] ; then +if [ "$1" = "start" ] ; then if [ -z "$ACTIVEMQ_OPTS" ] ; then ACTIVEMQ_OPTS="-Xmx512M -Dorg.apache.activemq.UseDedicatedTaskRunner=true -Djava.util.logging.config.file=logging.properties" fi debian/patches/CVE-2014-3576.patch0000664000000000000000000000116013077354155013253 0ustar Description: Fix for CVE-2014-3576: DoS via unauthenticated remote shutdown command Origin: backport, https://github.com/apache/activemq/commit/00921f2 --- a/activemq-core/src/main/java/org/apache/activemq/broker/TransportConnection.java +++ b/activemq-core/src/main/java/org/apache/activemq/broker/TransportConnection.java @@ -1408,10 +1408,6 @@ } public Response processControlCommand(ControlCommand command) throws Exception { - String control = command.getCommand(); - if (control != null && control.equals("shutdown")) { - System.exit(0); - } return null; } debian/patches/series0000664000000000000000000000046413077354155012052 0ustar drop_derby_use.diff disable_some_modules.diff exclude_geronimo_jca.diff exclude_spring_osgi.diff javadoc_links.diff init_debian_default_values.diff activemq-admin.patch exclude_mqtt.diff exclude_leveldb.diff CVE-2014-3600.patch CVE-2014-3612.patch CVE-2014-3576.patch CVE-2015-5254.patch CVE-2015-7559.patch debian/patches/CVE-2014-3612.patch0000664000000000000000000003067513077354155013257 0ustar Description: Fix CVE-2014-3612: ActiveMQ JAAS: LDAPLoginModule allows empty password authentication. This patch can be removed after upgrading to ActiveMQ 5.10.1 or later. Origin: backport, https://github.com/apache/activemq/commit/0b5231ad Bug: https://issues.apache.org/jira/browse/AMQ-5345 --- a/activemq-core/src/main/java/org/apache/activemq/security/LDAPAuthorizationMap.java +++ b/activemq-core/src/main/java/org/apache/activemq/security/LDAPAuthorizationMap.java @@ -465,11 +465,15 @@ try { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory); - if (connectionUsername != null || !"".equals(connectionUsername)) { + if (connectionUsername != null && !"".equals(connectionUsername)) { env.put(Context.SECURITY_PRINCIPAL, connectionUsername); + } else { + throw new NamingException("Empty username is not allowed"); } - if (connectionPassword != null || !"".equals(connectionPassword)) { + if (connectionPassword != null && !"".equals(connectionPassword)) { env.put(Context.SECURITY_CREDENTIALS, connectionPassword); + } else { + throw new NamingException("Empty password is not allowed"); } env.put(Context.SECURITY_PROTOCOL, connectionProtocol); env.put(Context.PROVIDER_URL, connectionURL); --- a/activemq-jaas/src/main/java/org/apache/activemq/jaas/LDAPLoginModule.java +++ b/activemq-jaas/src/main/java/org/apache/activemq/jaas/LDAPLoginModule.java @@ -194,7 +194,7 @@ try { String filter = userSearchMatchingFormat.format(new String[] { - username + doRFC2254Encoding(username) }); SearchControls constraints = new SearchControls(); if (userSearchSubtreeBool) { @@ -291,7 +291,7 @@ return list; } String filter = roleSearchMatchingFormat.format(new String[] { - doRFC2254Encoding(dn), username + doRFC2254Encoding(dn), doRFC2254Encoding(username) }); SearchControls constraints = new SearchControls(); @@ -408,9 +408,14 @@ env.put(Context.INITIAL_CONTEXT_FACTORY, getLDAPPropertyValue(INITIAL_CONTEXT_FACTORY)); if (isLoginPropertySet(CONNECTION_USERNAME)) { env.put(Context.SECURITY_PRINCIPAL, getLDAPPropertyValue(CONNECTION_USERNAME)); + } else { + throw new NamingException("Empty username is not allowed"); } + if (isLoginPropertySet(CONNECTION_PASSWORD)) { env.put(Context.SECURITY_CREDENTIALS, getLDAPPropertyValue(CONNECTION_PASSWORD)); + } else { + throw new NamingException("Empty password is not allowed"); } env.put(Context.SECURITY_PROTOCOL, getLDAPPropertyValue(CONNECTION_PROTOCOL)); env.put(Context.PROVIDER_URL, getLDAPPropertyValue(CONNECTION_URL)); @@ -433,7 +438,7 @@ private boolean isLoginPropertySet(String propertyName) { for (int i=0; i < config.length; i++ ) { - if (config[i].getPropertyName() == propertyName && config[i].getPropertyValue() != null) + if (config[i].getPropertyName() == propertyName && (config[i].getPropertyValue() != null && !"".equals(config[i].getPropertyValue()))) return true; } return false; --- a/activemq-jaas/src/test/java/org/apache/activemq/jaas/LDAPLoginModuleTest.java +++ b/activemq-jaas/src/test/java/org/apache/activemq/jaas/LDAPLoginModuleTest.java @@ -41,7 +41,9 @@ import java.util.HashSet; import java.util.Hashtable; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; @RunWith ( FrameworkRunner.class ) @CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP", port=1024)}) @@ -121,4 +123,29 @@ context.logout(); } + @Test + public void testUnauthenticated() throws LoginException { + LoginContext context = new LoginContext("UnAuthenticatedLDAPLogin", new CallbackHandler() { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof NameCallback) { + ((NameCallback) callbacks[i]).setName("first"); + } else if (callbacks[i] instanceof PasswordCallback) { + ((PasswordCallback) callbacks[i]).setPassword("secret".toCharArray()); + } else { + throw new UnsupportedCallbackException(callbacks[i]); + } + } + } + }); + try { + context.login(); + } catch (LoginException le) { + assertEquals(le.getCause().getMessage(), "Empty password is not allowed"); + return; + } + fail("Should have failed authenticating"); + } + + } --- a/activemq-jaas/src/test/resources/login.config +++ b/activemq-jaas/src/test/resources/login.config @@ -40,6 +40,25 @@ ; }; +UnAuthenticatedLDAPLogin { + org.apache.activemq.jaas.LDAPLoginModule required + debug=true + initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory + connectionURL="ldap://localhost:1024" + connectionUsername="uid=admin,ou=system" + connectionPassword="" + connectionProtocol=s + authentication=simple + userBase="ou=system" + userSearchMatching="(uid={0})" + userSearchSubtree=false + roleBase="ou=system" + roleName=dummyRoleName + roleSearchMatching="(uid={1})" + roleSearchSubtree=false + ; +}; + GuestLogin { org.apache.activemq.jaas.GuestLoginModule required debug=true --- /dev/null +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/security/LDAPAuthenticationTest.java @@ -0,0 +1,83 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.activemq.security; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; + +import org.apache.activemq.ActiveMQConnectionFactory; +import org.apache.activemq.broker.BrokerFactory; +import org.apache.activemq.broker.BrokerService; +import org.apache.directory.server.annotations.CreateLdapServer; +import org.apache.directory.server.annotations.CreateTransport; +import org.apache.directory.server.core.annotations.ApplyLdifFiles; +import org.apache.directory.server.core.integ.AbstractLdapTestUnit; +import org.apache.directory.server.core.integ.FrameworkRunner; +import org.apache.directory.server.ldap.LdapServer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith( FrameworkRunner.class ) +@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP", port=1024)}) +@ApplyLdifFiles( + "org/apache/activemq/security/activemq.ldif" +) +public class LDAPAuthenticationTest extends AbstractLdapTestUnit { + + public BrokerService broker; + + public static LdapServer ldapServer; + + @Before + public void setup() throws Exception { + System.setProperty("ldapPort", String.valueOf(getLdapServer().getPort())); + + broker = BrokerFactory.createBroker("xbean:org/apache/activemq/security/activemq-ldap-auth.xml"); + broker.start(); + broker.waitUntilStarted(); + } + + @After + public void shutdown() throws Exception { + broker.stop(); + broker.waitUntilStopped(); + } + + @Test + public void testWildcard() throws Exception { + ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616"); + Connection conn = factory.createQueueConnection("*", "sunflower"); + try { + conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + } catch (Exception e) { + e.printStackTrace(); + return; + } + fail("Should have failed connecting"); + } +} \ No newline at end of file --- a/activemq-core/src/test/java/org/apache/activemq/security/LDAPSecurityTest.java +++ b/activemq-core/src/test/java/org/apache/activemq/security/LDAPSecurityTest.java @@ -38,7 +38,7 @@ @RunWith( FrameworkRunner.class ) -@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP")}) +@CreateLdapServer(transports = {@CreateTransport(protocol = "LDAP", port=1024)}) @ApplyLdifFiles( "org/apache/activemq/security/activemq.ldif" ) --- a/activemq-core/src/test/resources/login.config +++ b/activemq-core/src/test/resources/login.config @@ -65,4 +65,23 @@ debug=true org.apache.activemq.jaas.textfiledn.user="org/apache/activemq/security/users2.properties" org.apache.activemq.jaas.textfiledn.group="org/apache/activemq/security/groups.properties"; +}; + +LDAPLogin { + org.apache.activemq.jaas.LDAPLoginModule required + debug=true + initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory + connectionURL="ldap://localhost:1024" + connectionUsername="uid=admin,ou=system" + connectionPassword=secret + connectionProtocol=s + authentication=simple + userBase="ou=User,ou=ActiveMQ,ou=system" + userSearchMatching="(uid={0})" + userSearchSubtree=false + roleBase="ou=Group,ou=ActiveMQ,ou=system" + roleName=cn + roleSearchMatching="(uid={1})" + roleSearchSubtree=true + ; }; \ No newline at end of file --- /dev/null +++ b/activemq-unit-tests/src/test/resources/org/apache/activemq/security/activemq-ldap-auth.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + debian/patches/exclude_geronimo_jca.diff0000664000000000000000000000343613077354155015636 0ustar Description: Disabled usage of Geronimo JCA provider because its not yet in Debian. Author: Damien Raude-Morvan Last-Update: 2011-06-21 Forwarded: not-needed --- a/activemq-pool/pom.xml +++ b/activemq-pool/pom.xml @@ -42,6 +42,21 @@ + + + + maven-compiler-plugin + + + **/JcaPooledConnectionFactory.* + **/JcaConnectionPool.* + **/ActiveMQResourceManager.* + + + + + + --- a/activemq-spring/src/main/java/org/apache/activemq/pool/PooledConnectionFactoryBean.java +++ b/activemq-spring/src/main/java/org/apache/activemq/pool/PooledConnectionFactoryBean.java @@ -112,7 +112,7 @@ */ @PostConstruct public void afterPropertiesSet() throws Exception { - if (pooledConnectionFactory == null && transactionManager != null && resourceName != null) { + /*if (pooledConnectionFactory == null && transactionManager != null && resourceName != null) { try { LOGGER.debug("Trying to build a JcaPooledConnectionFactory"); JcaPooledConnectionFactory f = new JcaPooledConnectionFactory(); @@ -126,7 +126,7 @@ } catch (Throwable t) { LOGGER.debug("Could not create JCA enabled connection factory: " + t, t); } - } + }*/ if (pooledConnectionFactory == null && transactionManager != null) { try { LOGGER.debug("Trying to build a XaPooledConnectionFactory"); debian/patches/javadoc_links.diff0000664000000000000000000000506613077354155014301 0ustar Description: Use Javadoc installed system-wide for HTML links. Author: Damien Raude-Morvan Last-Update: 2011-07-22 Forwarded: not-needed --- a/activemq-core/pom.xml +++ b/activemq-core/pom.xml @@ -303,7 +303,7 @@ ${javase-javadoc-url} ${javaee-javadoc-url} ${slf4j-javadoc-url} - http://junit.sourceforge.net/javadoc/ + /usr/share/doc/junit4/api/ ${basedir}/../etc/css/stylesheet.css true --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ scpexe://people.apache.org/www/activemq.apache.org/maven/ 1.6 1.6 - http://download.oracle.com/javase/6/docs/api/ + /usr/share/doc/default-jdk-doc/api/ http://download.oracle.com/javaee/6/api/ http://www.slf4j.org/apidocs/ @@ -1268,14 +1268,14 @@ ${javase-javadoc-url} ${javaee-javadoc-url} - http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ - http://jakarta.apache.org/commons/dbcp/apidocs/ - http://jakarta.apache.org/commons/fileupload/apidocs/ - http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/ + /usr/share/doc/libcommons-collections3-java-doc/api/ + /usr/share/doc/libcommons-dbcp-java/api/ + /usr/share/doc/libcommons-fileupload-java/api/ + /usr/share/doc/libcommons-httpclient-java-doc/docs/apidocs/ ${slf4j-javadoc-url} - http://jakarta.apache.org/commons/pool/apidocs/ - http://junit.sourceforge.net/javadoc/ - http://logging.apache.org/log4j/docs/api/ + /usr/share/doc/libcommons-pool-java/api/ + /usr/share/doc/junit4/api/ + /usr/share/doc/liblog4j1.2-java/api/ ${basedir}/../etc/css/stylesheet.css true debian/patches/CVE-2014-3600.patch0000664000000000000000000002512313077354155013244 0ustar Description: Fix CVE-2014-3600: XML External Entity expansion when evaluating XPath expressions. This patch can be removed after upgrading to ActiveMQ 5.10.1 or later. Origin: backport, https://github.com/apache/activemq/commit/b9696ac Bug: https://issues.apache.org/jira/browse/AMQ-5333 --- a/activemq-optional/src/main/java/org/apache/activemq/filter/JAXPXPathEvaluator.java +++ b/activemq-optional/src/main/java/org/apache/activemq/filter/JAXPXPathEvaluator.java @@ -21,11 +21,13 @@ import javax.jms.BytesMessage; import javax.jms.JMSException; import javax.jms.TextMessage; +import javax.xml.parsers.DocumentBuilder; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.apache.activemq.command.Message; @@ -61,8 +63,9 @@ private boolean evaluate(byte[] data) { try { InputSource inputSource = new InputSource(new ByteArrayInputStream(data)); - return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue(); - } catch (XPathExpressionException e) { + Document inputDocument = builder.parse(inputSource); + return ((Boolean)xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue(); + } catch (Exception e) { return false; } } @@ -70,8 +73,9 @@ private boolean evaluate(String text) { try { InputSource inputSource = new InputSource(new StringReader(text)); - return ((Boolean)expression.evaluate(inputSource, XPathConstants.BOOLEAN)).booleanValue(); - } catch (XPathExpressionException e) { + Document inputDocument = builder.parse(inputSource); + return ((Boolean)xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue(); + } catch (Exception e) { return false; } } --- a/activemq-core/src/main/java/org/apache/activemq/filter/XalanXPathEvaluator.java +++ b/activemq-core/src/main/java/org/apache/activemq/filter/XalanXPathEvaluator.java @@ -25,6 +25,8 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.traversal.NodeIterator; @@ -35,13 +37,20 @@ import org.apache.xpath.CachedXPathAPI; import org.apache.xpath.objects.XObject; - public class XalanXPathEvaluator implements XPathExpression.XPathEvaluator { - private final String xpath; - - public XalanXPathEvaluator(String xpath) { - this.xpath = xpath; + private static final XPathFactory FACTORY = XPathFactory.newInstance(); + private final String xpathExpression; + private final DocumentBuilder builder; + private final XPath xpath = FACTORY.newXPath(); + + public XalanXPathEvaluator(String xpathExpression, DocumentBuilder builder) throws Exception { + this.xpathExpression = xpathExpression; + if (builder != null) { + this.builder = builder; + } else { + throw new RuntimeException("No document builder available"); + } } public boolean evaluate(Message m) throws JMSException { @@ -61,22 +70,9 @@ try { InputSource inputSource = new InputSource(new ByteArrayInputStream(data)); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - DocumentBuilder dbuilder = factory.newDocumentBuilder(); - Document doc = dbuilder.parse(inputSource); - - CachedXPathAPI cachedXPathAPI = new CachedXPathAPI(); - XObject result = cachedXPathAPI.eval(doc, xpath); - if (result.bool()) - return true; - else { - NodeIterator iterator = cachedXPathAPI.selectNodeIterator(doc, xpath); - return (iterator.nextNode() != null); - } - - } catch (Throwable e) { + Document inputDocument = builder.parse(inputSource); + return ((Boolean) xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue(); + } catch (Exception e) { return false; } } @@ -84,28 +80,15 @@ private boolean evaluate(String text) { try { InputSource inputSource = new InputSource(new StringReader(text)); - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - DocumentBuilder dbuilder = factory.newDocumentBuilder(); - Document doc = dbuilder.parse(inputSource); - - //An XPath expression could return a true or false value instead of a node. - //eval() is a better way to determine the boolean value of the exp. - //For compliance with legacy behavior where selecting an empty node returns true, - //selectNodeIterator is attempted in case of a failure. - - CachedXPathAPI cachedXPathAPI = new CachedXPathAPI(); - XObject result = cachedXPathAPI.eval(doc, xpath); - if (result.bool()) - return true; - else { - NodeIterator iterator = cachedXPathAPI.selectNodeIterator(doc, xpath); - return (iterator.nextNode() != null); - } - - } catch (Throwable e) { + Document inputDocument = builder.parse(inputSource); + return ((Boolean) xpath.evaluate(xpathExpression, inputDocument, XPathConstants.BOOLEAN)).booleanValue(); + } catch (Exception e) { return false; } } + + @Override + public String toString() { + return xpathExpression; + } } --- a/activemq-core/src/main/java/org/apache/activemq/filter/XPathExpression.java +++ b/activemq-core/src/main/java/org/apache/activemq/filter/XPathExpression.java @@ -19,8 +19,15 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; import javax.jms.JMSException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import org.apache.activemq.command.Message; import org.apache.activemq.util.JMSExceptionSupport; @@ -35,8 +42,10 @@ private static final Logger LOG = LoggerFactory.getLogger(XPathExpression.class); private static final String EVALUATOR_SYSTEM_PROPERTY = "org.apache.activemq.XPathEvaluatorClassName"; private static final String DEFAULT_EVALUATOR_CLASS_NAME = XalanXPathEvaluator.class.getName(); + public static final String DOCUMENT_BUILDER_FACTORY_FEATURE = "org.apache.activemq.documentBuilderFactory.feature"; private static final Constructor EVALUATOR_CONSTRUCTOR; + private static DocumentBuilder builder = null; static { String cn = System.getProperty(EVALUATOR_SYSTEM_PROPERTY, DEFAULT_EVALUATOR_CLASS_NAME); @@ -44,6 +53,21 @@ try { try { m = getXPathEvaluatorConstructor(cn); + DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); + builderFactory.setNamespaceAware(true); + builderFactory.setIgnoringElementContentWhitespace(true); + builderFactory.setIgnoringComments(true); + try { + // set some reasonable defaults + builderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); + builderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + } catch (ParserConfigurationException e) { + LOG.warn("Error setting document builder factory feature", e); + } + // setup the feature from the system property + setupFeatures(builderFactory); + builder = builderFactory.newDocumentBuilder(); } catch (Throwable e) { LOG.warn("Invalid " + XPathEvaluator.class.getName() + " implementation: " + cn + ", reason: " + e, e); cn = DEFAULT_EVALUATOR_CLASS_NAME; @@ -75,12 +99,41 @@ if (!XPathEvaluator.class.isAssignableFrom(c)) { throw new ClassCastException("" + c + " is not an instance of " + XPathEvaluator.class); } - return c.getConstructor(new Class[] {String.class}); + return c.getConstructor(new Class[] {String.class, DocumentBuilder.class}); + } + + protected static void setupFeatures(DocumentBuilderFactory factory) { + Properties properties = System.getProperties(); + List features = new ArrayList(); + for (Map.Entry prop : properties.entrySet()) { + String key = (String) prop.getKey(); + if (key.startsWith(DOCUMENT_BUILDER_FACTORY_FEATURE)) { + String uri = key.split(DOCUMENT_BUILDER_FACTORY_FEATURE + ":")[1]; + Boolean value = Boolean.valueOf((String)prop.getValue()); + try { + factory.setFeature(uri, value); + features.add("feature " + uri + " value " + value); + } catch (ParserConfigurationException e) { + LOG.warn("DocumentBuilderFactory doesn't support the feature {} with value {}, due to {}.", new Object[]{uri, value, e}); + } + } + } + if (features.size() > 0) { + StringBuffer featureString = new StringBuffer(); + // just log the configured feature + for (String feature : features) { + if (featureString.length() != 0) { + featureString.append(", "); + } + featureString.append(feature); + } + } + } private XPathEvaluator createEvaluator(String xpath2) { try { - return (XPathEvaluator)EVALUATOR_CONSTRUCTOR.newInstance(new Object[] {xpath}); + return (XPathEvaluator)EVALUATOR_CONSTRUCTOR.newInstance(new Object[] {xpath, builder}); } catch (InvocationTargetException e) { Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { debian/patches/CVE-2015-5254.patch0000664000000000000000000035630213077354155013262 0ustar From: Markus Koschany Date: Wed, 16 Mar 2016 18:35:42 +0100 Subject: CVE-2015-5254 Apache ActiveMQ 5.x before 5.13.0 does not restrict the classes that can be serialized in the broker, which allows remote attackers to execute arbitrary code via a crafted serialized Java Message Service (JMS) ObjectMessage object. Origin: https://git-wip-us.apache.org/repos/asf?p=activemq.git;h=6f03921b31d9fefeddb0f4fa63150ed1f94a14b1 Origin: https://git-wip-us.apache.org/repos/asf?p=activemq.git;h=73a0caf758f9e4916783a205c7e422b4db27905c Origin: http://pkgs.fedoraproject.org/cgit/activemq.git/diff/activemq-5.6.0-CVE-2015-5254.patch?id=e3ef8a1b62d10273a814090be9168aa3019ace72 Debian-Bug: https://bugs.debian.org/809733 --- .../java/com/thoughtworks/xstream/XStream.java | 1928 ++++++++++++++++++++ .../xstream/mapper/FieldAliasingMapper.java | 99 + .../xstream/mapper/SecurityMapper.java | 79 + .../xstream/security/AnyTypePermission.java | 32 + .../xstream/security/ArrayTypePermission.java | 32 + .../xstream/security/ExplicitTypePermission.java | 54 + .../xstream/security/ForbiddenClassException.java | 27 + .../xstream/security/InterfaceTypePermission.java | 33 + .../xstream/security/NoPermission.java | 39 + .../xstream/security/NoTypePermission.java | 36 + .../xstream/security/NullPermission.java | 26 + .../xstream/security/PrimitiveTypePermission.java | 34 + .../xstream/security/ProxyTypePermission.java | 37 + .../xstream/security/RegExpTypePermission.java | 48 + .../xstream/security/TypeHierarchyPermission.java | 32 + .../xstream/security/TypePermission.java | 25 + .../xstream/security/WildcardTypePermission.java | 84 + .../transport/stomp/JmsFrameTranslator.java | 5 +- .../activemq/transport/stomp/XStreamSupport.java | 47 + .../util/ClassLoadingAwareObjectInputStream.java | 48 +- .../transport/xstream/XStreamWireFormat.java | 29 +- .../java/org/apache/activemq/web/MessageQuery.java | 4 +- 22 files changed, 2769 insertions(+), 9 deletions(-) create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/XStream.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/mapper/FieldAliasingMapper.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/mapper/SecurityMapper.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/AnyTypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/ArrayTypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/ForbiddenClassException.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/InterfaceTypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/NoPermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/NoTypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/NullPermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/ProxyTypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/RegExpTypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/TypePermission.java create mode 100644 activemq-core/src/main/java/com/thoughtworks/xstream/security/WildcardTypePermission.java create mode 100644 activemq-core/src/main/java/org/apache/activemq/transport/stomp/XStreamSupport.java diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/XStream.java b/activemq-core/src/main/java/com/thoughtworks/xstream/XStream.java new file mode 100644 index 0000000..29c047a --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/XStream.java @@ -0,0 +1,1928 @@ +/* + * Copyright (C) 2003, 2004, 2005, 2006 Joe Walnes. + * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 XStream Committers. + * All rights reserved. + * + * The software in this package is published under the terms of the BSD + * style license a copy of which has been included with this distribution in + * the LICENSE.txt file. + * + * Created on 26. September 2003 by Joe Walnes + */ +package com.thoughtworks.xstream; + +import java.io.EOFException; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.NotActiveException; +import java.io.ObjectInputStream; +import java.io.ObjectInputValidation; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Vector; +import java.util.regex.Pattern; + +import com.thoughtworks.xstream.converters.ConversionException; +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.ConverterLookup; +import com.thoughtworks.xstream.converters.ConverterRegistry; +import com.thoughtworks.xstream.converters.DataHolder; +import com.thoughtworks.xstream.converters.SingleValueConverter; +import com.thoughtworks.xstream.converters.SingleValueConverterWrapper; +import com.thoughtworks.xstream.converters.basic.BigDecimalConverter; +import com.thoughtworks.xstream.converters.basic.BigIntegerConverter; +import com.thoughtworks.xstream.converters.basic.BooleanConverter; +import com.thoughtworks.xstream.converters.basic.ByteConverter; +import com.thoughtworks.xstream.converters.basic.CharConverter; +import com.thoughtworks.xstream.converters.basic.DateConverter; +import com.thoughtworks.xstream.converters.basic.DoubleConverter; +import com.thoughtworks.xstream.converters.basic.FloatConverter; +import com.thoughtworks.xstream.converters.basic.IntConverter; +import com.thoughtworks.xstream.converters.basic.LongConverter; +import com.thoughtworks.xstream.converters.basic.NullConverter; +import com.thoughtworks.xstream.converters.basic.ShortConverter; +import com.thoughtworks.xstream.converters.basic.StringBufferConverter; +import com.thoughtworks.xstream.converters.basic.StringConverter; +import com.thoughtworks.xstream.converters.basic.URIConverter; +import com.thoughtworks.xstream.converters.basic.URLConverter; +import com.thoughtworks.xstream.converters.collections.ArrayConverter; +import com.thoughtworks.xstream.converters.collections.BitSetConverter; +import com.thoughtworks.xstream.converters.collections.CharArrayConverter; +import com.thoughtworks.xstream.converters.collections.CollectionConverter; +import com.thoughtworks.xstream.converters.collections.MapConverter; +import com.thoughtworks.xstream.converters.collections.PropertiesConverter; +import com.thoughtworks.xstream.converters.collections.SingletonCollectionConverter; +import com.thoughtworks.xstream.converters.collections.SingletonMapConverter; +import com.thoughtworks.xstream.converters.collections.TreeMapConverter; +import com.thoughtworks.xstream.converters.collections.TreeSetConverter; +import com.thoughtworks.xstream.converters.extended.ColorConverter; +import com.thoughtworks.xstream.converters.extended.DynamicProxyConverter; +import com.thoughtworks.xstream.converters.extended.EncodedByteArrayConverter; +import com.thoughtworks.xstream.converters.extended.FileConverter; +import com.thoughtworks.xstream.converters.extended.FontConverter; +import com.thoughtworks.xstream.converters.extended.GregorianCalendarConverter; +import com.thoughtworks.xstream.converters.extended.JavaClassConverter; +import com.thoughtworks.xstream.converters.extended.JavaFieldConverter; +import com.thoughtworks.xstream.converters.extended.JavaMethodConverter; +import com.thoughtworks.xstream.converters.extended.LocaleConverter; +import com.thoughtworks.xstream.converters.extended.LookAndFeelConverter; +import com.thoughtworks.xstream.converters.extended.SqlDateConverter; +import com.thoughtworks.xstream.converters.extended.SqlTimeConverter; +import com.thoughtworks.xstream.converters.extended.SqlTimestampConverter; +import com.thoughtworks.xstream.converters.extended.TextAttributeConverter; +import com.thoughtworks.xstream.converters.reflection.ExternalizableConverter; +import com.thoughtworks.xstream.converters.reflection.ReflectionConverter; +import com.thoughtworks.xstream.converters.reflection.ReflectionProvider; +import com.thoughtworks.xstream.converters.reflection.SelfStreamingInstanceChecker; +import com.thoughtworks.xstream.converters.reflection.SerializableConverter; +import com.thoughtworks.xstream.core.DefaultConverterLookup; +import com.thoughtworks.xstream.core.JVM; +import com.thoughtworks.xstream.core.MapBackedDataHolder; +import com.thoughtworks.xstream.core.ReferenceByIdMarshallingStrategy; +import com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy; +import com.thoughtworks.xstream.core.TreeMarshallingStrategy; +import com.thoughtworks.xstream.core.util.ClassLoaderReference; +import com.thoughtworks.xstream.core.util.CompositeClassLoader; +import com.thoughtworks.xstream.core.util.CustomObjectInputStream; +import com.thoughtworks.xstream.core.util.CustomObjectOutputStream; +import com.thoughtworks.xstream.io.HierarchicalStreamDriver; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.StatefulWriter; +import com.thoughtworks.xstream.io.xml.XppDriver; +import com.thoughtworks.xstream.mapper.AnnotationConfiguration; +import com.thoughtworks.xstream.mapper.ArrayMapper; +import com.thoughtworks.xstream.mapper.AttributeAliasingMapper; +import com.thoughtworks.xstream.mapper.AttributeMapper; +import com.thoughtworks.xstream.mapper.CachingMapper; +import com.thoughtworks.xstream.mapper.ClassAliasingMapper; +import com.thoughtworks.xstream.mapper.DefaultImplementationsMapper; +import com.thoughtworks.xstream.mapper.DefaultMapper; +import com.thoughtworks.xstream.mapper.DynamicProxyMapper; +import com.thoughtworks.xstream.mapper.FieldAliasingMapper; +import com.thoughtworks.xstream.mapper.ImmutableTypesMapper; +import com.thoughtworks.xstream.mapper.ImplicitCollectionMapper; +import com.thoughtworks.xstream.mapper.LocalConversionMapper; +import com.thoughtworks.xstream.mapper.Mapper; +import com.thoughtworks.xstream.mapper.MapperWrapper; +import com.thoughtworks.xstream.mapper.OuterClassMapper; +import com.thoughtworks.xstream.mapper.PackageAliasingMapper; +import com.thoughtworks.xstream.mapper.SystemAttributeAliasingMapper; +import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper; +import com.thoughtworks.xstream.security.AnyTypePermission; +import com.thoughtworks.xstream.security.ExplicitTypePermission; +import com.thoughtworks.xstream.security.NoPermission; +import com.thoughtworks.xstream.security.NoTypePermission; +import com.thoughtworks.xstream.security.RegExpTypePermission; +import com.thoughtworks.xstream.security.TypeHierarchyPermission; +import com.thoughtworks.xstream.security.TypePermission; +import com.thoughtworks.xstream.security.WildcardTypePermission; +import com.thoughtworks.xstream.mapper.SecurityMapper; + + +/** + * Simple facade to XStream library, a Java-XML serialization tool.

+ *

+ *


+ * Example
+ * + *
+ * XStream xstream = new XStream();
+ * String xml = xstream.toXML(myObject); // serialize to XML
+ * Object myObject2 = xstream.fromXML(xml); // deserialize from XML
+ * 
+ * + *
+ *
+ *

+ *

Aliasing classes

+ *

+ *

+ * To create shorter XML, you can specify aliases for classes using the alias() + * method. For example, you can shorten all occurrences of element + * <com.blah.MyThing> to <my-thing> by registering an + * alias for the class. + *

+ *


+ *
+ * + *
+ * xstream.alias("my-thing", MyThing.class);
+ * 
+ * + *
+ *
+ *

+ *

Converters

+ *

+ *

+ * XStream contains a map of {@link com.thoughtworks.xstream.converters.Converter} instances, each + * of which acts as a strategy for converting a particular type of class to XML and back again. Out + * of the box, XStream contains converters for most basic types (String, Date, int, boolean, etc) + * and collections (Map, List, Set, Properties, etc). For other objects reflection is used to + * serialize each field recursively. + *

+ *

+ *

+ * Extra converters can be registered using the registerConverter() method. Some + * non-standard converters are supplied in the {@link com.thoughtworks.xstream.converters.extended} + * package and you can create your own by implementing the + * {@link com.thoughtworks.xstream.converters.Converter} interface. + *

+ *

+ *

+ *


+ * Example
+ * + *
+ * xstream.registerConverter(new SqlTimestampConverter());
+ * xstream.registerConverter(new DynamicProxyConverter());
+ * 
+ * + *
+ *
+ *

+ * The converters can be registered with an explicit priority. By default they are registered with + * XStream.PRIORITY_NORMAL. Converters of same priority will be used in the reverse sequence + * they have been registered. The default converter, i.e. the converter which will be used if + * no other registered converter is suitable, can be registered with priority + * XStream.PRIORITY_VERY_LOW. XStream uses by default the + * {@link com.thoughtworks.xstream.converters.reflection.ReflectionConverter} as the fallback + * converter. + *

+ *

+ *

+ *


+ * Example
+ * + *
+ * xstream.registerConverter(new CustomDefaultConverter(), XStream.PRIORITY_VERY_LOW);
+ * 
+ * + *
+ *
+ *

+ *

Object graphs

+ *

+ *

+ * XStream has support for object graphs; a deserialized object graph will keep references intact, + * including circular references. + *

+ *

+ *

+ * XStream can signify references in XML using either relative/absolute XPath or IDs. The mode can be changed using + * setMode(): + *

+ *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
xstream.setMode(XStream.XPATH_RELATIVE_REFERENCES);(Default) Uses XPath relative references to signify duplicate references. This produces XML + * with the least clutter.
xstream.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);Uses XPath absolute references to signify duplicate + * references. This produces XML with the least clutter.
xstream.setMode(XStream.SINGLE_NODE_XPATH_RELATIVE_REFERENCES);Uses XPath relative references to signify duplicate references. The XPath expression ensures that + * a single node only is selected always.
xstream.setMode(XStream.SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES);Uses XPath absolute references to signify duplicate references. The XPath expression ensures that + * a single node only is selected always.
xstream.setMode(XStream.ID_REFERENCES);Uses ID references to signify duplicate references. In some scenarios, such as when using + * hand-written XML, this is easier to work with.
xstream.setMode(XStream.NO_REFERENCES);This disables object graph support and treats the object structure like a tree. Duplicate + * references are treated as two separate objects and circular references cause an exception. This + * is slightly faster and uses less memory than the other two modes.
+ *

Thread safety

+ *

+ * The XStream instance is thread-safe. That is, once the XStream instance has been created and + * configured, it may be shared across multiple threads allowing objects to be + * serialized/deserialized concurrently. Note, that this only applies if annotations are not + * auto-detected on -the-fly. + *

+ *

Implicit collections

+ *

+ *

+ * To avoid the need for special tags for collections, you can define implicit collections using one + * of the addImplicitCollection methods. + *

+ * + * @author Joe Walnes + * @author Jörg Schaible + * @author Mauro Talevi + * @author Guilherme Silveira + */ +public class XStream { + + // CAUTION: The sequence of the fields is intentional for an optimal XML output of a + // self-serialization! + private ReflectionProvider reflectionProvider; + private HierarchicalStreamDriver hierarchicalStreamDriver; + private ClassLoaderReference classLoaderReference; + private MarshallingStrategy marshallingStrategy; + private ConverterLookup converterLookup; + private ConverterRegistry converterRegistry; + private Mapper mapper; + + private PackageAliasingMapper packageAliasingMapper; + private ClassAliasingMapper classAliasingMapper; + private FieldAliasingMapper fieldAliasingMapper; + private AttributeAliasingMapper attributeAliasingMapper; + private SystemAttributeAliasingMapper systemAttributeAliasingMapper; + private AttributeMapper attributeMapper; + private DefaultImplementationsMapper defaultImplementationsMapper; + private ImmutableTypesMapper immutableTypesMapper; + private ImplicitCollectionMapper implicitCollectionMapper; + private LocalConversionMapper localConversionMapper; + private AnnotationConfiguration annotationConfiguration; + private SecurityMapper securityMapper; + + private transient JVM jvm = new JVM(); + + public static final int NO_REFERENCES = 1001; + public static final int ID_REFERENCES = 1002; + public static final int XPATH_RELATIVE_REFERENCES = 1003; + public static final int XPATH_ABSOLUTE_REFERENCES = 1004; + public static final int SINGLE_NODE_XPATH_RELATIVE_REFERENCES = 1005; + public static final int SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES = 1006; + + public static final int PRIORITY_VERY_HIGH = 10000; + public static final int PRIORITY_NORMAL = 0; + public static final int PRIORITY_LOW = -10; + public static final int PRIORITY_VERY_LOW = -20; + + private static final String ANNOTATION_MAPPER_TYPE = "com.thoughtworks.xstream.mapper.AnnotationMapper"; + private static final Pattern IGNORE_ALL = Pattern.compile(".*"); + + /** + * Constructs a default XStream. The instance will use the {@link XppDriver} as default and + * tries to determine the best match for the {@link ReflectionProvider} on its own. + * + * @throws InitializationException in case of an initialization problem + */ + public XStream() { + this(null, (Mapper)null, new XppDriver()); + } + + /** + * Constructs an XStream with a special {@link ReflectionProvider}. The instance will use + * the {@link XppDriver} as default. + * + * @throws InitializationException in case of an initialization problem + */ + public XStream(ReflectionProvider reflectionProvider) { + this(reflectionProvider, (Mapper)null, new XppDriver()); + } + + /** + * Constructs an XStream with a special {@link HierarchicalStreamDriver}. The instance will + * tries to determine the best match for the {@link ReflectionProvider} on its own. + * + * @throws InitializationException in case of an initialization problem + */ + public XStream(HierarchicalStreamDriver hierarchicalStreamDriver) { + this(null, (Mapper)null, hierarchicalStreamDriver); + } + + /** + * Constructs an XStream with a special {@link HierarchicalStreamDriver} and + * {@link ReflectionProvider}. + * + * @throws InitializationException in case of an initialization problem + */ + public XStream( + ReflectionProvider reflectionProvider, HierarchicalStreamDriver hierarchicalStreamDriver) { + this(reflectionProvider, (Mapper)null, hierarchicalStreamDriver); + } + + /** + * Constructs an XStream with a special {@link HierarchicalStreamDriver} and + * {@link ReflectionProvider} and additionally with a prepared {@link Mapper}. + * + * @throws InitializationException in case of an initialization problem + * @deprecated As of 1.3, use + * {@link #XStream(ReflectionProvider, HierarchicalStreamDriver, ClassLoader, Mapper)} + * instead + */ + public XStream( + ReflectionProvider reflectionProvider, Mapper mapper, HierarchicalStreamDriver driver) { + this( + reflectionProvider, driver, new ClassLoaderReference(new CompositeClassLoader()), + mapper, new DefaultConverterLookup(), null); + } + + /** + * Constructs an XStream with a special {@link HierarchicalStreamDriver} and + * {@link ReflectionProvider} and additionally with a prepared {@link ClassLoader} to use. + * + * @throws InitializationException in case of an initialization problem + * @since 1.3 + */ + public XStream( + ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver, + ClassLoader classLoader) { + this(reflectionProvider, driver, classLoader, null); + } + + /** + * Constructs an XStream with a special {@link HierarchicalStreamDriver} and + * {@link ReflectionProvider} and additionally with a prepared {@link Mapper} and the + * {@link ClassLoader} in use. + *

+ * Note, if the class loader should be changed later again, you should provide a + * {@link ClassLoaderReference} as {@link ClassLoader} that is also use in the + * {@link Mapper} chain. + *

+ * + * @throws InitializationException in case of an initialization problem + * @since 1.3 + */ + public XStream( + ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver, + ClassLoader classLoader, Mapper mapper) { + this( + reflectionProvider, driver, classLoader, mapper, new DefaultConverterLookup(), null); + } + + /** + * Constructs an XStream with a special {@link HierarchicalStreamDriver}, + * {@link ReflectionProvider}, a prepared {@link Mapper} and the {@link ClassLoader} in use + * and an own {@link ConverterRegistry}. + *

+ * Note, if the class loader should be changed later again, you should provide a + * {@link ClassLoaderReference} as {@link ClassLoader} that is also use in the + * {@link Mapper} chain. + *

+ * + * @throws InitializationException in case of an initialization problem + * @since 1.3 + */ + public XStream( + ReflectionProvider reflectionProvider, HierarchicalStreamDriver driver, + ClassLoader classLoader, Mapper mapper, ConverterLookup converterLookup, + ConverterRegistry converterRegistry) { + jvm = new JVM(); + if (reflectionProvider == null) { + reflectionProvider = jvm.bestReflectionProvider(); + } + this.reflectionProvider = reflectionProvider; + this.hierarchicalStreamDriver = driver; + this.classLoaderReference = classLoader instanceof ClassLoaderReference + ? (ClassLoaderReference)classLoader + : new ClassLoaderReference(classLoader); + this.converterLookup = converterLookup; + this.converterRegistry = converterRegistry != null + ? converterRegistry + : (converterLookup instanceof ConverterRegistry + ? (ConverterRegistry)converterLookup + : null); + this.mapper = mapper == null ? buildMapper() : mapper; + + setupMappers(); + setupAliases(); + setupDefaultImplementations(); + setupConverters(); + setupImmutableTypes(); + setMode(XPATH_RELATIVE_REFERENCES); + } + + private Mapper buildMapper() { + Mapper mapper = new DefaultMapper(classLoaderReference); + if (useXStream11XmlFriendlyMapper()) { + mapper = new XStream11XmlFriendlyMapper(mapper); + } + mapper = new DynamicProxyMapper(mapper); + mapper = new PackageAliasingMapper(mapper); + mapper = new ClassAliasingMapper(mapper); + mapper = new FieldAliasingMapper(mapper); + mapper = new AttributeAliasingMapper(mapper); + mapper = new SystemAttributeAliasingMapper(mapper); + mapper = new ImplicitCollectionMapper(mapper); + mapper = new OuterClassMapper(mapper); + mapper = new ArrayMapper(mapper); + mapper = new DefaultImplementationsMapper(mapper); + mapper = new AttributeMapper(mapper, converterLookup, reflectionProvider); + if (JVM.is15()) { + mapper = buildMapperDynamically( + "com.thoughtworks.xstream.mapper.EnumMapper", new Class[]{Mapper.class}, + new Object[]{mapper}); + } + mapper = new LocalConversionMapper(mapper); + mapper = new ImmutableTypesMapper(mapper); + if (JVM.is15()) { + mapper = buildMapperDynamically(ANNOTATION_MAPPER_TYPE, new Class[]{ + Mapper.class, ConverterRegistry.class, ConverterLookup.class, + ClassLoader.class, ReflectionProvider.class, JVM.class}, new Object[]{ + mapper, converterLookup, converterLookup, classLoaderReference, + reflectionProvider, jvm}); + } + mapper = wrapMapper((MapperWrapper)mapper); + mapper = new CachingMapper(mapper); + return mapper; + } + + private Mapper buildMapperDynamically(String className, Class[] constructorParamTypes, + Object[] constructorParamValues) { + try { + Class type = Class.forName(className, false, classLoaderReference.getReference()); + Constructor constructor = type.getConstructor(constructorParamTypes); + return (Mapper)constructor.newInstance(constructorParamValues); + } catch (Exception e) { + throw new com.thoughtworks.xstream.InitializationException( + "Could not instantiate mapper : " + className, e); + } + } + + protected MapperWrapper wrapMapper(MapperWrapper next) { + return next; + } + + protected boolean useXStream11XmlFriendlyMapper() { + return false; + } + + private void setupMappers() { + packageAliasingMapper = (PackageAliasingMapper)this.mapper + .lookupMapperOfType(PackageAliasingMapper.class); + classAliasingMapper = (ClassAliasingMapper)this.mapper + .lookupMapperOfType(ClassAliasingMapper.class); + fieldAliasingMapper = (FieldAliasingMapper)this.mapper + .lookupMapperOfType(FieldAliasingMapper.class); + attributeMapper = (AttributeMapper)this.mapper + .lookupMapperOfType(AttributeMapper.class); + attributeAliasingMapper = (AttributeAliasingMapper)this.mapper + .lookupMapperOfType(AttributeAliasingMapper.class); + systemAttributeAliasingMapper = (SystemAttributeAliasingMapper)this.mapper + .lookupMapperOfType(SystemAttributeAliasingMapper.class); + implicitCollectionMapper = (ImplicitCollectionMapper)this.mapper + .lookupMapperOfType(ImplicitCollectionMapper.class); + defaultImplementationsMapper = (DefaultImplementationsMapper)this.mapper + .lookupMapperOfType(DefaultImplementationsMapper.class); + immutableTypesMapper = (ImmutableTypesMapper)this.mapper + .lookupMapperOfType(ImmutableTypesMapper.class); + localConversionMapper = (LocalConversionMapper)this.mapper + .lookupMapperOfType(LocalConversionMapper.class); + annotationConfiguration = (AnnotationConfiguration)this.mapper + .lookupMapperOfType(AnnotationConfiguration.class); + } + + protected void setupAliases() { + if (classAliasingMapper == null) { + return; + } + + alias("null", Mapper.Null.class); + alias("int", Integer.class); + alias("float", Float.class); + alias("double", Double.class); + alias("long", Long.class); + alias("short", Short.class); + alias("char", Character.class); + alias("byte", Byte.class); + alias("boolean", Boolean.class); + alias("number", Number.class); + alias("object", Object.class); + alias("big-int", BigInteger.class); + alias("big-decimal", BigDecimal.class); + + alias("string-buffer", StringBuffer.class); + alias("string", String.class); + alias("java-class", Class.class); + alias("method", Method.class); + alias("constructor", Constructor.class); + alias("field", Field.class); + alias("date", Date.class); + alias("uri", URI.class); + alias("url", URL.class); + alias("bit-set", BitSet.class); + + alias("map", Map.class); + alias("entry", Map.Entry.class); + alias("properties", Properties.class); + alias("list", List.class); + alias("set", Set.class); + alias("sorted-set", SortedSet.class); + + alias("linked-list", LinkedList.class); + alias("vector", Vector.class); + alias("tree-map", TreeMap.class); + alias("tree-set", TreeSet.class); + alias("hashtable", Hashtable.class); + + alias("empty-list", Collections.EMPTY_LIST.getClass()); + alias("empty-map", Collections.EMPTY_MAP.getClass()); + alias("empty-set", Collections.EMPTY_SET.getClass()); + alias("singleton-list", Collections.singletonList(this).getClass()); + alias("singleton-map", Collections.singletonMap(this, null).getClass()); + alias("singleton-set", Collections.singleton(this).getClass()); + + if (jvm.supportsAWT()) { + // Instantiating these two classes starts the AWT system, which is undesirable. + // Calling loadClass ensures a reference to the class is found but they are not + // instantiated. + alias("awt-color", jvm.loadClass("java.awt.Color")); + alias("awt-font", jvm.loadClass("java.awt.Font")); + alias("awt-text-attribute", jvm.loadClass("java.awt.font.TextAttribute")); + } + + if (jvm.supportsSQL()) { + alias("sql-timestamp", jvm.loadClass("java.sql.Timestamp")); + alias("sql-time", jvm.loadClass("java.sql.Time")); + alias("sql-date", jvm.loadClass("java.sql.Date")); + } + + alias("file", File.class); + alias("locale", Locale.class); + alias("gregorian-calendar", Calendar.class); + + if (JVM.is14()) { + aliasDynamically("auth-subject", "javax.security.auth.Subject"); + alias("linked-hash-map", jvm.loadClass("java.util.LinkedHashMap")); + alias("linked-hash-set", jvm.loadClass("java.util.LinkedHashSet")); + alias("trace", jvm.loadClass("java.lang.StackTraceElement")); + alias("currency", jvm.loadClass("java.util.Currency")); + aliasType("charset", jvm.loadClass("java.nio.charset.Charset")); + } + + if (JVM.is15()) { + aliasDynamically("duration", "javax.xml.datatype.Duration"); + alias("enum-set", jvm.loadClass("java.util.EnumSet")); + alias("enum-map", jvm.loadClass("java.util.EnumMap")); + alias("string-builder", jvm.loadClass("java.lang.StringBuilder")); + alias("uuid", jvm.loadClass("java.util.UUID")); + } + } + + private void aliasDynamically(String alias, String className) { + Class type = jvm.loadClass(className); + if (type != null) { + alias(alias, type); + } + } + + protected void setupDefaultImplementations() { + if (defaultImplementationsMapper == null) { + return; + } + addDefaultImplementation(HashMap.class, Map.class); + addDefaultImplementation(ArrayList.class, List.class); + addDefaultImplementation(HashSet.class, Set.class); + addDefaultImplementation(TreeSet.class, SortedSet.class); + addDefaultImplementation(GregorianCalendar.class, Calendar.class); + } + + protected void setupConverters() { + final ReflectionConverter reflectionConverter = new ReflectionConverter( + mapper, reflectionProvider); + registerConverter(reflectionConverter, PRIORITY_VERY_LOW); + + registerConverter( + new SerializableConverter(mapper, reflectionProvider, classLoaderReference), PRIORITY_LOW); + registerConverter(new ExternalizableConverter(mapper, classLoaderReference), PRIORITY_LOW); + + registerConverter(new NullConverter(), PRIORITY_VERY_HIGH); + registerConverter(new IntConverter(), PRIORITY_NORMAL); + registerConverter(new FloatConverter(), PRIORITY_NORMAL); + registerConverter(new DoubleConverter(), PRIORITY_NORMAL); + registerConverter(new LongConverter(), PRIORITY_NORMAL); + registerConverter(new ShortConverter(), PRIORITY_NORMAL); + registerConverter((Converter)new CharConverter(), PRIORITY_NORMAL); + registerConverter(new BooleanConverter(), PRIORITY_NORMAL); + registerConverter(new ByteConverter(), PRIORITY_NORMAL); + + registerConverter(new StringConverter(), PRIORITY_NORMAL); + registerConverter(new StringBufferConverter(), PRIORITY_NORMAL); + registerConverter(new DateConverter(), PRIORITY_NORMAL); + registerConverter(new BitSetConverter(), PRIORITY_NORMAL); + registerConverter(new URIConverter(), PRIORITY_NORMAL); + registerConverter(new URLConverter(), PRIORITY_NORMAL); + registerConverter(new BigIntegerConverter(), PRIORITY_NORMAL); + registerConverter(new BigDecimalConverter(), PRIORITY_NORMAL); + + registerConverter(new ArrayConverter(mapper), PRIORITY_NORMAL); + registerConverter(new CharArrayConverter(), PRIORITY_NORMAL); + registerConverter(new CollectionConverter(mapper), PRIORITY_NORMAL); + registerConverter(new MapConverter(mapper), PRIORITY_NORMAL); + registerConverter(new TreeMapConverter(mapper), PRIORITY_NORMAL); + registerConverter(new TreeSetConverter(mapper), PRIORITY_NORMAL); + registerConverter(new SingletonCollectionConverter(mapper), PRIORITY_NORMAL); + registerConverter(new SingletonMapConverter(mapper), PRIORITY_NORMAL); + registerConverter(new PropertiesConverter(), PRIORITY_NORMAL); + registerConverter((Converter)new EncodedByteArrayConverter(), PRIORITY_NORMAL); + + registerConverter(new FileConverter(), PRIORITY_NORMAL); + if (jvm.supportsSQL()) { + registerConverter(new SqlTimestampConverter(), PRIORITY_NORMAL); + registerConverter(new SqlTimeConverter(), PRIORITY_NORMAL); + registerConverter(new SqlDateConverter(), PRIORITY_NORMAL); + } + registerConverter( + new DynamicProxyConverter(mapper, classLoaderReference), PRIORITY_NORMAL); + registerConverter(new JavaClassConverter(classLoaderReference), PRIORITY_NORMAL); + registerConverter(new JavaMethodConverter(classLoaderReference), PRIORITY_NORMAL); + registerConverter(new JavaFieldConverter(classLoaderReference), PRIORITY_NORMAL); + if (jvm.supportsAWT()) { + registerConverter(new FontConverter(), PRIORITY_NORMAL); + registerConverter(new ColorConverter(), PRIORITY_NORMAL); + registerConverter(new TextAttributeConverter(), PRIORITY_NORMAL); + } + if (jvm.supportsSwing()) { + registerConverter( + new LookAndFeelConverter(mapper, reflectionProvider), PRIORITY_NORMAL); + } + registerConverter(new LocaleConverter(), PRIORITY_NORMAL); + registerConverter(new GregorianCalendarConverter(), PRIORITY_NORMAL); + + if (JVM.is14()) { + // late bound converters - allows XStream to be compiled on earlier JDKs + registerConverterDynamically( + "com.thoughtworks.xstream.converters.extended.SubjectConverter", + PRIORITY_NORMAL, new Class[]{Mapper.class}, new Object[]{mapper}); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.extended.ThrowableConverter", + PRIORITY_NORMAL, new Class[]{Converter.class}, + new Object[]{reflectionConverter}); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.extended.StackTraceElementConverter", + PRIORITY_NORMAL, null, null); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.extended.CurrencyConverter", + PRIORITY_NORMAL, null, null); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.extended.RegexPatternConverter", + PRIORITY_NORMAL, new Class[]{Converter.class}, + new Object[]{reflectionConverter}); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.extended.CharsetConverter", + PRIORITY_NORMAL, null, null); + } + + if (JVM.is15()) { + // late bound converters - allows XStream to be compiled on earlier JDKs + if (jvm.loadClass("javax.xml.datatype.Duration") != null) { + registerConverterDynamically( + "com.thoughtworks.xstream.converters.extended.DurationConverter", + PRIORITY_NORMAL, null, null); + } + registerConverterDynamically( + "com.thoughtworks.xstream.converters.enums.EnumConverter", PRIORITY_NORMAL, + null, null); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.enums.EnumSetConverter", PRIORITY_NORMAL, + new Class[]{Mapper.class}, new Object[]{mapper}); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.enums.EnumMapConverter", PRIORITY_NORMAL, + new Class[]{Mapper.class}, new Object[]{mapper}); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.basic.StringBuilderConverter", + PRIORITY_NORMAL, null, null); + registerConverterDynamically( + "com.thoughtworks.xstream.converters.basic.UUIDConverter", PRIORITY_NORMAL, + null, null); + } + + registerConverter( + new SelfStreamingInstanceChecker(reflectionConverter, this), PRIORITY_NORMAL); + } + + private void registerConverterDynamically(String className, int priority, + Class[] constructorParamTypes, Object[] constructorParamValues) { + try { + Class type = Class.forName(className, false, classLoaderReference.getReference()); + Constructor constructor = type.getConstructor(constructorParamTypes); + Object instance = constructor.newInstance(constructorParamValues); + if (instance instanceof Converter) { + registerConverter((Converter)instance, priority); + } else if (instance instanceof SingleValueConverter) { + registerConverter((SingleValueConverter)instance, priority); + } + } catch (Exception e) { + throw new com.thoughtworks.xstream.InitializationException( + "Could not instantiate converter : " + className, e); + } + } + + protected void setupImmutableTypes() { + if (immutableTypesMapper == null) { + return; + } + + // primitives are always immutable + addImmutableType(boolean.class); + addImmutableType(Boolean.class); + addImmutableType(byte.class); + addImmutableType(Byte.class); + addImmutableType(char.class); + addImmutableType(Character.class); + addImmutableType(double.class); + addImmutableType(Double.class); + addImmutableType(float.class); + addImmutableType(Float.class); + addImmutableType(int.class); + addImmutableType(Integer.class); + addImmutableType(long.class); + addImmutableType(Long.class); + addImmutableType(short.class); + addImmutableType(Short.class); + + // additional types + addImmutableType(Mapper.Null.class); + addImmutableType(BigDecimal.class); + addImmutableType(BigInteger.class); + addImmutableType(String.class); + addImmutableType(URI.class); + addImmutableType(URL.class); + addImmutableType(File.class); + addImmutableType(Class.class); + + addImmutableType(Collections.EMPTY_LIST.getClass()); + addImmutableType(Collections.EMPTY_SET.getClass()); + addImmutableType(Collections.EMPTY_MAP.getClass()); + + if (jvm.supportsAWT()) { + addImmutableTypeDynamically("java.awt.font.TextAttribute"); + } + + if (JVM.is14()) { + // late bound types - allows XStream to be compiled on earlier JDKs + addImmutableTypeDynamically("java.nio.charset.Charset"); + addImmutableTypeDynamically("java.util.Currency"); + } + } + + private void addImmutableTypeDynamically(String className) { + Class type = jvm.loadClass(className); + if (type != null) { + addImmutableType(type); + } + } + + public void setMarshallingStrategy(MarshallingStrategy marshallingStrategy) { + this.marshallingStrategy = marshallingStrategy; + } + + /** + * Serialize an object to a pretty-printed XML String. + * + * @throws XStreamException if the object cannot be serialized + */ + public String toXML(Object obj) { + Writer writer = new StringWriter(); + toXML(obj, writer); + return writer.toString(); + } + + /** + * Serialize an object to the given Writer as pretty-printed XML. The Writer will be flushed + * afterwards and in case of an exception. + * + * @throws XStreamException if the object cannot be serialized + */ + public void toXML(Object obj, Writer out) { + HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out); + try { + marshal(obj, writer); + } finally { + writer.flush(); + } + } + + /** + * Serialize an object to the given OutputStream as pretty-printed XML. The OutputStream + * will be flushed afterwards and in case of an exception. + * + * @throws XStreamException if the object cannot be serialized + */ + public void toXML(Object obj, OutputStream out) { + HierarchicalStreamWriter writer = hierarchicalStreamDriver.createWriter(out); + try { + marshal(obj, writer); + } finally { + writer.flush(); + } + } + + /** + * Serialize and object to a hierarchical data structure (such as XML). + * + * @throws XStreamException if the object cannot be serialized + */ + public void marshal(Object obj, HierarchicalStreamWriter writer) { + marshal(obj, writer, null); + } + + /** + * Serialize and object to a hierarchical data structure (such as XML). + * + * @param dataHolder Extra data you can use to pass to your converters. Use this as you + * want. If not present, XStream shall create one lazily as needed. + * @throws XStreamException if the object cannot be serialized + */ + public void marshal(Object obj, HierarchicalStreamWriter writer, DataHolder dataHolder) { + marshallingStrategy.marshal(writer, obj, converterLookup, mapper, dataHolder); + } + + /** + * Deserialize an object from an XML String. + * + * @throws XStreamException if the object cannot be deserialized + */ + public Object fromXML(String xml) { + return fromXML(new StringReader(xml)); + } + + /** + * Deserialize an object from an XML Reader. + * + * @throws XStreamException if the object cannot be deserialized + */ + public Object fromXML(Reader reader) { + return unmarshal(hierarchicalStreamDriver.createReader(reader), null); + } + + /** + * Deserialize an object from an XML InputStream. + * + * @throws XStreamException if the object cannot be deserialized + */ + public Object fromXML(InputStream input) { + return unmarshal(hierarchicalStreamDriver.createReader(input), null); + } + + /** + * Deserialize an object from a URL. + * + * Depending on the parser implementation, some might take the file path as SystemId to + * resolve additional references. + * + * @throws XStreamException if the object cannot be deserialized + * @since 1.4 + */ + public Object fromXML(URL url) { + return unmarshal(hierarchicalStreamDriver.createReader(url), null); + } + + /** + * Deserialize an object from a file. + * + * Depending on the parser implementation, some might take the file path as SystemId to + * resolve additional references. + * + * @throws XStreamException if the object cannot be deserialized + * @since 1.4 + */ + public Object fromXML(File file) { + return unmarshal(hierarchicalStreamDriver.createReader(file), null); + } + + /** + * Deserialize an object from an XML String, populating the fields of the given root object + * instead of instantiating a new one. Note, that this is a special use case! With the + * ReflectionConverter XStream will write directly into the raw memory area of the existing + * object. Use with care! + * + * @throws XStreamException if the object cannot be deserialized + */ + public Object fromXML(String xml, Object root) { + return fromXML(new StringReader(xml), root); + } + + /** + * Deserialize an object from an XML Reader, populating the fields of the given root object + * instead of instantiating a new one. Note, that this is a special use case! With the + * ReflectionConverter XStream will write directly into the raw memory area of the existing + * object. Use with care! + * + * @throws XStreamException if the object cannot be deserialized + */ + public Object fromXML(Reader xml, Object root) { + return unmarshal(hierarchicalStreamDriver.createReader(xml), root); + } + + /** + * Deserialize an object from a URL, populating the fields of the given root + * object instead of instantiating a new one. Note, that this is a special use case! With + * the ReflectionConverter XStream will write directly into the raw memory area of the + * existing object. Use with care! + * + * Depending on the parser implementation, some might take the file path as SystemId to + * resolve additional references. + * + * @throws XStreamException if the object cannot be deserialized + * @since 1.4 + */ + public Object fromXML(URL url, Object root) { + return unmarshal(hierarchicalStreamDriver.createReader(url), root); + } + + /** + * Deserialize an object from a file, populating the fields of the given root + * object instead of instantiating a new one. Note, that this is a special use case! With + * the ReflectionConverter XStream will write directly into the raw memory area of the + * existing object. Use with care! + * + * Depending on the parser implementation, some might take the file path as SystemId to + * resolve additional references. + * + * @throws XStreamException if the object cannot be deserialized + * @since 1.4 + */ + public Object fromXML(File file, Object root) { + return unmarshal(hierarchicalStreamDriver.createReader(file), root); + } + + /** + * Deserialize an object from an XML InputStream, populating the fields of the given root + * object instead of instantiating a new one. Note, that this is a special use case! With + * the ReflectionConverter XStream will write directly into the raw memory area of the + * existing object. Use with care! + * + * @throws XStreamException if the object cannot be deserialized + */ + public Object fromXML(InputStream input, Object root) { + return unmarshal(hierarchicalStreamDriver.createReader(input), root); + } + + /** + * Deserialize an object from a hierarchical data structure (such as XML). + * + * @throws XStreamException if the object cannot be deserialized + */ + public Object unmarshal(HierarchicalStreamReader reader) { + return unmarshal(reader, null, null); + } + + /** + * Deserialize an object from a hierarchical data structure (such as XML), populating the + * fields of the given root object instead of instantiating a new one. Note, that this is a + * special use case! With the ReflectionConverter XStream will write directly into the raw + * memory area of the existing object. Use with care! + * + * @throws XStreamException if the object cannot be deserialized + */ + public Object unmarshal(HierarchicalStreamReader reader, Object root) { + return unmarshal(reader, root, null); + } + + /** + * Deserialize an object from a hierarchical data structure (such as XML). + * + * @param root If present, the passed in object will have its fields populated, as opposed + * to XStream creating a new instance. Note, that this is a special use case! + * With the ReflectionConverter XStream will write directly into the raw memory + * area of the existing object. Use with care! + * @param dataHolder Extra data you can use to pass to your converters. Use this as you + * want. If not present, XStream shall create one lazily as needed. + * @throws XStreamException if the object cannot be deserialized + */ + public Object unmarshal(HierarchicalStreamReader reader, Object root, DataHolder dataHolder) { + try { + return marshallingStrategy.unmarshal( + root, reader, dataHolder, converterLookup, mapper); + + } catch (ConversionException e) { + Package pkg = getClass().getPackage(); + e.add("version", pkg != null ? pkg.getImplementationVersion() : "not available"); + throw e; + } + } + + /** + * Alias a Class to a shorter name to be used in XML elements. + * + * @param name Short name + * @param type Type to be aliased + * @throws InitializationException if no {@link ClassAliasingMapper} is available + */ + public void alias(String name, Class type) { + if (classAliasingMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + ClassAliasingMapper.class.getName() + + " available"); + } + classAliasingMapper.addClassAlias(name, type); + } + + /** + * Alias a type to a shorter name to be used in XML elements. Any class that is assignable + * to this type will be aliased to the same name. + * + * @param name Short name + * @param type Type to be aliased + * @since 1.2 + * @throws InitializationException if no {@link ClassAliasingMapper} is available + */ + public void aliasType(String name, Class type) { + if (classAliasingMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + ClassAliasingMapper.class.getName() + + " available"); + } + classAliasingMapper.addTypeAlias(name, type); + } + + /** + * Alias a Class to a shorter name to be used in XML elements. + * + * @param name Short name + * @param type Type to be aliased + * @param defaultImplementation Default implementation of type to use if no other specified. + * @throws InitializationException if no {@link DefaultImplementationsMapper} or no + * {@link ClassAliasingMapper} is available + */ + public void alias(String name, Class type, Class defaultImplementation) { + alias(name, type); + addDefaultImplementation(defaultImplementation, type); + } + + /** + * Alias a package to a shorter name to be used in XML elements. + * + * @param name Short name + * @param pkgName package to be aliased + * @throws InitializationException if no {@link DefaultImplementationsMapper} or no + * {@link PackageAliasingMapper} is available + * @since 1.3.1 + */ + public void aliasPackage(String name, String pkgName) { + if (packageAliasingMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + PackageAliasingMapper.class.getName() + + " available"); + } + packageAliasingMapper.addPackageAlias(name, pkgName); + } + + /** + * Create an alias for a field name. + * + * @param alias the alias itself + * @param definedIn the type that declares the field + * @param fieldName the name of the field + * @throws InitializationException if no {@link FieldAliasingMapper} is available + */ + public void aliasField(String alias, Class definedIn, String fieldName) { + if (fieldAliasingMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + FieldAliasingMapper.class.getName() + + " available"); + } + fieldAliasingMapper.addFieldAlias(alias, definedIn, fieldName); + } + + /** + * Create an alias for an attribute + * + * @param alias the alias itself + * @param attributeName the name of the attribute + * @throws InitializationException if no {@link AttributeAliasingMapper} is available + */ + public void aliasAttribute(String alias, String attributeName) { + if (attributeAliasingMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + AttributeAliasingMapper.class.getName() + + " available"); + } + attributeAliasingMapper.addAliasFor(attributeName, alias); + } + + /** + * Create an alias for a system attribute. XStream will not write a system attribute if its + * alias is set to null. However, this is not reversible, i.e. deserialization + * of the result is likely to fail afterwards and will not produce an object equal to the + * originally written one. + * + * @param alias the alias itself (may be null) + * @param systemAttributeName the name of the system attribute + * @throws InitializationException if no {@link SystemAttributeAliasingMapper} is available + * @since 1.3.1 + */ + public void aliasSystemAttribute(String alias, String systemAttributeName) { + if (systemAttributeAliasingMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + SystemAttributeAliasingMapper.class.getName() + + " available"); + } + systemAttributeAliasingMapper.addAliasFor(systemAttributeName, alias); + } + + /** + * Create an alias for an attribute. + * + * @param definedIn the type where the attribute is defined + * @param attributeName the name of the attribute + * @param alias the alias itself + * @throws InitializationException if no {@link AttributeAliasingMapper} is available + * @since 1.2.2 + */ + public void aliasAttribute(Class definedIn, String attributeName, String alias) { + aliasField(alias, definedIn, attributeName); + useAttributeFor(definedIn, attributeName); + } + + /** + * Use an attribute for a field or a specific type. + * + * @param fieldName the name of the field + * @param type the Class of the type to be rendered as XML attribute + * @throws InitializationException if no {@link AttributeMapper} is available + * @since 1.2 + */ + public void useAttributeFor(String fieldName, Class type) { + if (attributeMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + AttributeMapper.class.getName() + + " available"); + } + attributeMapper.addAttributeFor(fieldName, type); + } + + /** + * Use an attribute for a field declared in a specific type. + * + * @param fieldName the name of the field + * @param definedIn the Class containing such field + * @throws InitializationException if no {@link AttributeMapper} is available + * @since 1.2.2 + */ + public void useAttributeFor(Class definedIn, String fieldName) { + if (attributeMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + AttributeMapper.class.getName() + + " available"); + } + attributeMapper.addAttributeFor(definedIn, fieldName); + } + + /** + * Use an attribute for an arbitrary type. + * + * @param type the Class of the type to be rendered as XML attribute + * @throws InitializationException if no {@link AttributeMapper} is available + * @since 1.2 + */ + public void useAttributeFor(Class type) { + if (attributeMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + AttributeMapper.class.getName() + + " available"); + } + attributeMapper.addAttributeFor(type); + } + + /** + * Associate a default implementation of a class with an object. Whenever XStream encounters + * an instance of this type, it will use the default implementation instead. For example, + * java.util.ArrayList is the default implementation of java.util.List. + * + * @param defaultImplementation + * @param ofType + * @throws InitializationException if no {@link DefaultImplementationsMapper} is available + */ + public void addDefaultImplementation(Class defaultImplementation, Class ofType) { + if (defaultImplementationsMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + DefaultImplementationsMapper.class.getName() + + " available"); + } + defaultImplementationsMapper.addDefaultImplementation(defaultImplementation, ofType); + } + + /** + * Add immutable types. The value of the instances of these types will always be written + * into the stream even if they appear multiple times. + * + * @throws InitializationException if no {@link ImmutableTypesMapper} is available + */ + public void addImmutableType(Class type) { + if (immutableTypesMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + ImmutableTypesMapper.class.getName() + + " available"); + } + immutableTypesMapper.addImmutableType(type); + } + + public void registerConverter(Converter converter) { + registerConverter(converter, PRIORITY_NORMAL); + } + + public void registerConverter(Converter converter, int priority) { + if (converterRegistry != null) { + converterRegistry.registerConverter(converter, priority); + } + } + + public void registerConverter(SingleValueConverter converter) { + registerConverter(converter, PRIORITY_NORMAL); + } + + public void registerConverter(SingleValueConverter converter, int priority) { + if (converterRegistry != null) { + converterRegistry.registerConverter( + new SingleValueConverterWrapper(converter), priority); + } + } + + /** + * Register a local {@link Converter} for a field. + * + * @param definedIn the class type the field is defined in + * @param fieldName the field name + * @param converter the converter to use + * @since 1.3 + */ + public void registerLocalConverter(Class definedIn, String fieldName, Converter converter) { + if (localConversionMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + LocalConversionMapper.class.getName() + + " available"); + } + localConversionMapper.registerLocalConverter(definedIn, fieldName, converter); + } + + /** + * Register a local {@link SingleValueConverter} for a field. + * + * @param definedIn the class type the field is defined in + * @param fieldName the field name + * @param converter the converter to use + * @since 1.3 + */ + public void registerLocalConverter(Class definedIn, String fieldName, + SingleValueConverter converter) { + registerLocalConverter( + definedIn, fieldName, (Converter)new SingleValueConverterWrapper(converter)); + } + + /** + * Retrieve the {@link Mapper}. This is by default a chain of {@link MapperWrapper + * MapperWrappers}. + * + * @return the mapper + * @since 1.2 + */ + public Mapper getMapper() { + return mapper; + } + + /** + * Retrieve the {@link ReflectionProvider} in use. + * + * @return the mapper + * @since 1.2.1 + */ + public ReflectionProvider getReflectionProvider() { + return reflectionProvider; + } + + public ConverterLookup getConverterLookup() { + return converterLookup; + } + + /** + * Change mode for dealing with duplicate references. Valid values are + * XPATH_ABSOLUTE_REFERENCES, XPATH_RELATIVE_REFERENCES, + * XStream.ID_REFERENCES and XStream.NO_REFERENCES. + * + * @throws IllegalArgumentException if the mode is not one of the declared types + * @see #XPATH_ABSOLUTE_REFERENCES + * @see #XPATH_RELATIVE_REFERENCES + * @see #ID_REFERENCES + * @see #NO_REFERENCES + */ + public void setMode(int mode) { + switch (mode) { + case NO_REFERENCES: + setMarshallingStrategy(new TreeMarshallingStrategy()); + break; + case ID_REFERENCES: + setMarshallingStrategy(new ReferenceByIdMarshallingStrategy()); + break; + case XPATH_RELATIVE_REFERENCES: + setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy( + ReferenceByXPathMarshallingStrategy.RELATIVE)); + break; + case XPATH_ABSOLUTE_REFERENCES: + setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy( + ReferenceByXPathMarshallingStrategy.ABSOLUTE)); + break; + case SINGLE_NODE_XPATH_RELATIVE_REFERENCES: + setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy( + ReferenceByXPathMarshallingStrategy.RELATIVE + | ReferenceByXPathMarshallingStrategy.SINGLE_NODE)); + break; + case SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES: + setMarshallingStrategy(new ReferenceByXPathMarshallingStrategy( + ReferenceByXPathMarshallingStrategy.ABSOLUTE + | ReferenceByXPathMarshallingStrategy.SINGLE_NODE)); + break; + default: + throw new IllegalArgumentException("Unknown mode : " + mode); + } + } + + /** + * Adds a default implicit collection which is used for any unmapped XML tag. + * + * @param ownerType class owning the implicit collection + * @param fieldName name of the field in the ownerType. This field must be a concrete + * collection type or matching the default implementation type of the collection + * type. + */ + public void addImplicitCollection(Class ownerType, String fieldName) { + addImplicitCollection(ownerType, fieldName, null, null); + } + + /** + * Adds implicit collection which is used for all items of the given itemType. + * + * @param ownerType class owning the implicit collection + * @param fieldName name of the field in the ownerType. This field must be a concrete + * collection type or matching the default implementation type of the collection + * type. + * @param itemType type of the items to be part of this collection + * @throws InitializationException if no {@link ImplicitCollectionMapper} is available + */ + public void addImplicitCollection(Class ownerType, String fieldName, Class itemType) { + addImplicitCollection(ownerType, fieldName, null, itemType); + } + + /** + * Adds implicit collection which is used for all items of the given element name defined by + * itemFieldName. + * + * @param ownerType class owning the implicit collection + * @param fieldName name of the field in the ownerType. This field must be a concrete + * collection type or matching the default implementation type of the collection + * type. + * @param itemFieldName element name of the implicit collection + * @param itemType item type to be aliases be the itemFieldName + * @throws InitializationException if no {@link ImplicitCollectionMapper} is available + */ + public void addImplicitCollection(Class ownerType, String fieldName, String itemFieldName, + Class itemType) { + addImplicitMap(ownerType, fieldName, itemFieldName, itemType, null); + } + + /** + * Adds an implicit array. + * + * @param ownerType class owning the implicit array + * @param fieldName name of the array field + * @since 1.4 + */ + public void addImplicitArray(Class ownerType, String fieldName) { + addImplicitCollection(ownerType, fieldName); + } + + /** + * Adds an implicit array which is used for all items of the given itemType when the array + * type matches. + * + * @param ownerType class owning the implicit array + * @param fieldName name of the array field in the ownerType + * @param itemType type of the items to be part of this array + * @throws InitializationException if no {@link ImplicitCollectionMapper} is available or the + * array type does not match the itemType + * @since 1.4 + */ + public void addImplicitArray(Class ownerType, String fieldName, Class itemType) { + addImplicitCollection(ownerType, fieldName, itemType); + } + + /** + * Adds an implicit array which is used for all items of the given element name defined by + * itemName. + * + * @param ownerType class owning the implicit array + * @param fieldName name of the array field in the ownerType + * @param itemName alias name of the items + * @throws InitializationException if no {@link ImplicitCollectionMapper} is available + * @since 1.4 + */ + public void addImplicitArray(Class ownerType, String fieldName, String itemName) { + addImplicitCollection(ownerType, fieldName, itemName, null); + } + + /** + * Adds an implicit map. + * + * @param ownerType class owning the implicit map + * @param fieldName name of the field in the ownerType. This field must be a concrete + * map type or matching the default implementation type of the map + * type. + * @param itemType type of the items to be part of this map as value + * @param keyFieldName the name of the filed of the itemType that is used for the key in the map + * @since 1.4 + */ + public void addImplicitMap(Class ownerType, String fieldName, Class itemType, String keyFieldName) { + addImplicitMap(ownerType, fieldName, null, itemType, keyFieldName); + } + + /** + * Adds an implicit map. + * + * @param ownerType class owning the implicit map + * @param fieldName name of the field in the ownerType. This field must be a concrete + * map type or matching the default implementation type of the map + * type. + * @param itemType type of the items to be part of this map as value + * @param keyFieldName the name of the filed of the itemType that is used for the key in the map + * @since 1.4 + */ + public void addImplicitMap(Class ownerType, String fieldName, String itemFieldName, + Class itemType, String keyFieldName) { + if (implicitCollectionMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + ImplicitCollectionMapper.class.getName() + + " available"); + } + implicitCollectionMapper.add(ownerType, fieldName, itemFieldName, itemType, keyFieldName); + } + + /** + * Create a DataHolder that can be used to pass data to the converters. The DataHolder is + * provided with a call to {@link #marshal(Object, HierarchicalStreamWriter, DataHolder)} or + * {@link #unmarshal(HierarchicalStreamReader, Object, DataHolder)}. + * + * @return a new {@link DataHolder} + */ + public DataHolder newDataHolder() { + return new MapBackedDataHolder(); + } + + /** + * Creates an ObjectOutputStream that serializes a stream of objects to the writer using + * XStream. + *

+ * To change the name of the root element (from <object-stream>), use + * {@link #createObjectOutputStream(java.io.Writer, String)}. + *

+ * + * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, + * String) + * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) + * @since 1.0.3 + */ + public ObjectOutputStream createObjectOutputStream(Writer writer) throws IOException { + return createObjectOutputStream( + hierarchicalStreamDriver.createWriter(writer), "object-stream"); + } + + /** + * Creates an ObjectOutputStream that serializes a stream of objects to the writer using + * XStream. + *

+ * To change the name of the root element (from <object-stream>), use + * {@link #createObjectOutputStream(java.io.Writer, String)}. + *

+ * + * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, + * String) + * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) + * @since 1.0.3 + */ + public ObjectOutputStream createObjectOutputStream(HierarchicalStreamWriter writer) + throws IOException { + return createObjectOutputStream(writer, "object-stream"); + } + + /** + * Creates an ObjectOutputStream that serializes a stream of objects to the writer using + * XStream. + * + * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, + * String) + * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) + * @since 1.0.3 + */ + public ObjectOutputStream createObjectOutputStream(Writer writer, String rootNodeName) + throws IOException { + return createObjectOutputStream( + hierarchicalStreamDriver.createWriter(writer), rootNodeName); + } + + /** + * Creates an ObjectOutputStream that serializes a stream of objects to the OutputStream + * using XStream. + *

+ * To change the name of the root element (from <object-stream>), use + * {@link #createObjectOutputStream(java.io.Writer, String)}. + *

+ * + * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, + * String) + * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) + * @since 1.3 + */ + public ObjectOutputStream createObjectOutputStream(OutputStream out) throws IOException { + return createObjectOutputStream( + hierarchicalStreamDriver.createWriter(out), "object-stream"); + } + + /** + * Creates an ObjectOutputStream that serializes a stream of objects to the OutputStream + * using XStream. + * + * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, + * String) + * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) + * @since 1.3 + */ + public ObjectOutputStream createObjectOutputStream(OutputStream out, String rootNodeName) + throws IOException { + return createObjectOutputStream( + hierarchicalStreamDriver.createWriter(out), rootNodeName); + } + + /** + * Creates an ObjectOutputStream that serializes a stream of objects to the writer using + * XStream. + *

+ * Because an ObjectOutputStream can contain multiple items and XML only allows a single + * root node, the stream must be written inside an enclosing node. + *

+ *

+ * It is necessary to call ObjectOutputStream.close() when done, otherwise the stream will + * be incomplete. + *

+ *

Example

+ * + *
+     *  ObjectOutputStream out = xstream.createObjectOutputStream(aWriter, "things");
+     *   out.writeInt(123);
+     *   out.writeObject("Hello");
+     *   out.writeObject(someObject)
+     *   out.close();
+     * 
+ * + * @param writer The writer to serialize the objects to. + * @param rootNodeName The name of the root node enclosing the stream of objects. + * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) + * @since 1.0.3 + */ + public ObjectOutputStream createObjectOutputStream(final HierarchicalStreamWriter writer, + String rootNodeName) throws IOException { + final StatefulWriter statefulWriter = new StatefulWriter(writer); + statefulWriter.startNode(rootNodeName, null); + return new CustomObjectOutputStream(new CustomObjectOutputStream.StreamCallback() { + public void writeToStream(Object object) { + marshal(object, statefulWriter); + } + + public void writeFieldsToStream(Map fields) throws NotActiveException { + throw new NotActiveException("not in call to writeObject"); + } + + public void defaultWriteObject() throws NotActiveException { + throw new NotActiveException("not in call to writeObject"); + } + + public void flush() { + statefulWriter.flush(); + } + + public void close() { + if (statefulWriter.state() != StatefulWriter.STATE_CLOSED) { + statefulWriter.endNode(); + statefulWriter.close(); + } + } + }); + } + + /** + * Creates an ObjectInputStream that deserializes a stream of objects from a reader using + * XStream. + * + * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) + * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, + * String) + * @since 1.0.3 + */ + public ObjectInputStream createObjectInputStream(Reader xmlReader) throws IOException { + return createObjectInputStream(hierarchicalStreamDriver.createReader(xmlReader)); + } + + /** + * Creates an ObjectInputStream that deserializes a stream of objects from an InputStream + * using XStream. + * + * @see #createObjectInputStream(com.thoughtworks.xstream.io.HierarchicalStreamReader) + * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, + * String) + * @since 1.3 + */ + public ObjectInputStream createObjectInputStream(InputStream in) throws IOException { + return createObjectInputStream(hierarchicalStreamDriver.createReader(in)); + } + + /** + * Creates an ObjectInputStream that deserializes a stream of objects from a reader using + * XStream.

Example

+ * + *
+     * ObjectInputStream in = xstream.createObjectOutputStream(aReader);
+     * int a = out.readInt();
+     * Object b = out.readObject();
+     * Object c = out.readObject();
+     * 
+ * + * @see #createObjectOutputStream(com.thoughtworks.xstream.io.HierarchicalStreamWriter, + * String) + * @since 1.0.3 + */ + public ObjectInputStream createObjectInputStream(final HierarchicalStreamReader reader) + throws IOException { + return new CustomObjectInputStream(new CustomObjectInputStream.StreamCallback() { + public Object readFromStream() throws EOFException { + if (!reader.hasMoreChildren()) { + throw new EOFException(); + } + reader.moveDown(); + Object result = unmarshal(reader); + reader.moveUp(); + return result; + } + + public Map readFieldsFromStream() throws IOException { + throw new NotActiveException("not in call to readObject"); + } + + public void defaultReadObject() throws NotActiveException { + throw new NotActiveException("not in call to readObject"); + } + + public void registerValidation(ObjectInputValidation validation, int priority) + throws NotActiveException { + throw new NotActiveException("stream inactive"); + } + + public void close() { + reader.close(); + } + }, classLoaderReference); + } + + /** + * Change the ClassLoader XStream uses to load classes. Creating an XStream instance it will + * register for all kind of classes and types of the current JDK, but not for any 3rd party + * type. To ensure that all other types are loaded with your class loader, you should call + * this method as early as possible - or consider to provide the class loader directly in + * the constructor. + * + * @since 1.1.1 + */ + public void setClassLoader(ClassLoader classLoader) { + classLoaderReference.setReference(classLoader); + } + + /** + * Retrieve the ClassLoader XStream uses to load classes. + * + * @since 1.1.1 + */ + public ClassLoader getClassLoader() { + return classLoaderReference.getReference(); + } + + /** + * Add pattern for unknown element names to ignore. + * + * @param pattern the name pattern as regular expression + * @since 1.4.5 + */ + private void ignoreUnknownElements(Pattern pattern) { + if (fieldAliasingMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + FieldAliasingMapper.class.getName() + + " available"); + } + fieldAliasingMapper.addFieldsToIgnore(pattern); + } + + /** + * Process the annotations of the given types and configure the XStream. + * + * @param types the types with XStream annotations + * @since 1.3 + */ + public void processAnnotations(final Class[] types) { + if (annotationConfiguration == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + ANNOTATION_MAPPER_TYPE + + " available"); + } + annotationConfiguration.processAnnotations(types); + } + + /** + * Process the annotations of the given type and configure the XStream. A call of this + * method will automatically turn the auto-detection mode for annotations off. + * + * @param type the type with XStream annotations + * @since 1.3 + */ + public void processAnnotations(final Class type) { + processAnnotations(new Class[]{type}); + } + + /** + * Set the auto-detection mode of the AnnotationMapper. Note that auto-detection implies + * that the XStream is configured while it is processing the XML steams. This is a potential + * concurrency problem. Also is it technically not possible to detect all class aliases at + * deserialization. You have been warned! + * + * @param mode true if annotations are auto-detected + * @since 1.3 + */ + public void autodetectAnnotations(boolean mode) { + if (annotationConfiguration != null) { + annotationConfiguration.autodetectAnnotations(mode); + } + } + + /** + * Add a new security permission. + * + *

+ * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or + * {@link AnyTypePermission} will implicitly wipe any existing permission. + *

+ * + * @param permission the permission to add + * @since 1.4.7 + */ + public void addPermission(TypePermission permission) { + if (securityMapper != null) { + securityMapper.addPermission(permission); + } + } + + public void allowTypesByWildcard(String[] patterns) { + addPermission(new WildcardTypePermission(patterns)); + } + + /** + * Add security permission for explicit types by name. + * + * @param names the type names to allow + * @since 1.4.7 + */ + public void allowTypes(String[] names) { + addPermission(new ExplicitTypePermission(names)); + } + + /** + * Add security permission for explicit types. + * + * @param types the types to allow + * @since 1.4.7 + */ + public void allowTypes(Class[] types) { + addPermission(new ExplicitTypePermission(types)); + } + /** + * Prevents a field from being serialized. To omit a field you must always provide the + * declaring type and not necessarily the type that is converted. + * + * @since 1.1.3 + * @throws InitializationException if no {@link FieldAliasingMapper} is available + */ + public void omitField(Class definedIn, String fieldName) { + if (fieldAliasingMapper == null) { + throw new com.thoughtworks.xstream.InitializationException("No " + + FieldAliasingMapper.class.getName() + + " available"); + } + fieldAliasingMapper.omitField(definedIn, fieldName); + } + + /** + * Add security permission for a type hierarchy. + * + * @param type the base type to allow + * @since 1.4.7 + */ + public void allowTypeHierarchy(Class type) { + addPermission(new TypeHierarchyPermission(type)); + } + /** + * Ignore all unknown elements. + * + * @since 1.4.5 + */ + public void ignoreUnknownElements() { + ignoreUnknownElements(IGNORE_ALL); + } + + /** + * @deprecated As of 1.3, use {@link InitializationException} instead + */ + public static class InitializationException extends XStreamException { + /** + * @deprecated As of 1.3, use {@link InitializationException} instead + */ + public InitializationException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @deprecated As of 1.3, use {@link InitializationException} instead + */ + public InitializationException(String message) { + super(message); + } + } + + private Object readResolve() { + jvm = new JVM(); + return this; + } + +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/FieldAliasingMapper.java b/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/FieldAliasingMapper.java new file mode 100644 index 0000000..7e627c2 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/FieldAliasingMapper.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2005 Joe Walnes. + * Copyright (C) 2006, 2007, 2008, 2009, 2013, 2014 XStream Committers. + * All rights reserved. + * + * The software in this package is published under the terms of the BSD + * style license a copy of which has been included with this distribution in + * the LICENSE.txt file. + * + * Created on 09. April 2005 by Joe Walnes + */ +package com.thoughtworks.xstream.mapper; + +import com.thoughtworks.xstream.core.util.FastField; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * Mapper that allows a field of a specific class to be replaced with a shorter alias, or omitted + * entirely. + * + * @author Joe Walnes + */ +public class FieldAliasingMapper extends MapperWrapper { + + protected final Map fieldToAliasMap = new HashMap(); + protected final Map aliasToFieldMap = new HashMap(); + protected final Set fieldsToOmit = new HashSet(); + protected final Set unknownFieldsToIgnore = new LinkedHashSet(); + + public FieldAliasingMapper(Mapper wrapped) { + super(wrapped); + } + + public void addFieldAlias(String alias, Class type, String fieldName) { + fieldToAliasMap.put(key(type, fieldName), alias); + aliasToFieldMap.put(key(type, alias), fieldName); + } + + public void addFieldsToIgnore(final Pattern pattern) { + unknownFieldsToIgnore.add(pattern); + } + + private Object key(Class type, String name) { + return new FastField(type, name); + } + + public String serializedMember(Class type, String memberName) { + String alias = getMember(type, memberName, fieldToAliasMap); + if (alias == null) { + return super.serializedMember(type, memberName); + } else { + return alias; + } + } + + public String realMember(Class type, String serialized) { + String real = getMember(type, serialized, aliasToFieldMap); + if (real == null) { + return super.realMember(type, serialized); + } else { + return real; + } + } + + private String getMember(Class type, String name, Map map) { + String member = null; + for (Class declaringType = type; + member == null && declaringType != Object.class && declaringType != null; + declaringType = declaringType.getSuperclass()) { + member = (String) map.get(key(declaringType, name)); + } + return member; + } + + public boolean shouldSerializeMember(Class definedIn, String fieldName) { + if (fieldsToOmit.contains(key(definedIn, fieldName))) { + return false; + } else if (definedIn == Object.class && !unknownFieldsToIgnore.isEmpty()) { + for(Iterator iter = unknownFieldsToIgnore.iterator(); iter.hasNext();) { + Pattern pattern = (Pattern)iter.next(); + if (pattern.matcher(fieldName).matches()) { + return false; + } + } + } + return true; + } + + public void omitField(Class definedIn, String fieldName) { + fieldsToOmit.add(key(definedIn, fieldName)); + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/SecurityMapper.java b/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/SecurityMapper.java new file mode 100644 index 0000000..d650c92 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/mapper/SecurityMapper.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 08. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.mapper; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.thoughtworks.xstream.security.AnyTypePermission; +import com.thoughtworks.xstream.security.ForbiddenClassException; +import com.thoughtworks.xstream.security.NoTypePermission; +import com.thoughtworks.xstream.security.TypePermission; + + +/** + * A Mapper implementation injecting a security layer based on permission rules for any type required in the + * unmarshalling process. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class SecurityMapper extends MapperWrapper { + + private final List permissions; + + /** + * Construct a SecurityMapper. + * + * @param wrapped the mapper chain + * @since 1.4.7 + */ + public SecurityMapper(final Mapper wrapped) { + this(wrapped, (TypePermission[])null); + } + + /** + * Construct a SecurityMapper. + * + * @param wrapped the mapper chain + * @param permissions the predefined permissions + * @since 1.4.7 + */ + public SecurityMapper(final Mapper wrapped, final TypePermission[] permissions) { + super(wrapped); + this.permissions = permissions == null // + ? new ArrayList() + : new ArrayList(Arrays.asList(permissions)); + } + + /** + * Add a new permission. + *

+ * Permissions are evaluated in the added sequence. An instance of {@link NoTypePermission} or + * {@link AnyTypePermission} will implicitly wipe any existing permission. + *

+ * + * @param permission the permission to add. + * @since 1.4.7 + */ + public void addPermission(final TypePermission permission) { + if (permission.equals(NoTypePermission.NONE) || permission.equals(AnyTypePermission.ANY)) + permissions.clear(); + permissions.add(0, permission); + } + + public Class realClass(final String elementName) { + final Class type = super.realClass(elementName); + for (int i = 0; i < permissions.size(); ++i) { + final TypePermission permission = (TypePermission)permissions.get(i); + if (permission.allows(type)) + return type; + } + throw new ForbiddenClassException(type); + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/AnyTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/AnyTypePermission.java new file mode 100644 index 0000000..d1524a9 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/AnyTypePermission.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 08. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * Permission for any type and null. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class AnyTypePermission implements TypePermission { + /** + * @since 1.4.7 + */ + public static final TypePermission ANY = new AnyTypePermission(); + + public boolean allows(Class type) { + return true; + } + + public int hashCode() { + return 3; + } + + public boolean equals(Object obj) { + return obj != null && obj.getClass() == AnyTypePermission.class; + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/ArrayTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ArrayTypePermission.java new file mode 100644 index 0000000..1e856ec --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ArrayTypePermission.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 09. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * Permission for any array type. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class ArrayTypePermission implements TypePermission { + /** + * @since 1.4.7 + */ + public static final TypePermission ARRAYS = new ArrayTypePermission(); + + public boolean allows(Class type) { + return type != null && type.isArray(); + } + + public int hashCode() { + return 13; + } + + public boolean equals(Object obj) { + return obj != null && obj.getClass() == ArrayTypePermission.class; + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java new file mode 100644 index 0000000..196380b --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ExplicitTypePermission.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 09. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + + +/** + * Explicit permission for a type with a name matching one in the provided list. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class ExplicitTypePermission implements TypePermission { + + final Set names; + + /** + * @since 1.4.7 + */ + public ExplicitTypePermission(final Class[] types) { + this(new Object() { + public String[] getNames() { + if (types == null) + return null; + String[] names = new String[types.length]; + for (int i = 0; i < types.length; ++i) + names[i] = types[i].getName(); + return names; + } + }.getNames()); + } + + /** + * @since 1.4.7 + */ + public ExplicitTypePermission(String[] names) { + this.names = names == null ? Collections.EMPTY_SET : new HashSet(Arrays.asList(names)); + } + + public boolean allows(Class type) { + if (type == null) + return false; + return names.contains(type.getName()); + } + +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/ForbiddenClassException.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ForbiddenClassException.java new file mode 100644 index 0000000..017fc30 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ForbiddenClassException.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 08. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +import com.thoughtworks.xstream.XStreamException; + +/** + * Exception thrown for a forbidden class. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class ForbiddenClassException extends XStreamException { + + /** + * Construct a ForbiddenClassException. + * @param type the forbidden class + * @since 1.4.7 + */ + public ForbiddenClassException(Class type) { + super(type == null ? "null" : type.getName()); + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/InterfaceTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/InterfaceTypePermission.java new file mode 100644 index 0000000..c5b8002 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/InterfaceTypePermission.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 27. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * Permission for any interface type. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class InterfaceTypePermission implements TypePermission { + /** + * @since 1.4.7 + */ + public static final TypePermission INTERFACES = new InterfaceTypePermission(); + + public boolean allows(Class type) { + return type != null && type.isInterface(); + } + + public int hashCode() { + return 31; + } + + public boolean equals(Object obj) { + return obj != null && obj.getClass() == InterfaceTypePermission.class; + } + +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoPermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoPermission.java new file mode 100644 index 0000000..17115b0 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoPermission.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 09. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * Wrapper to negate another type permission. + *

+ * If the wrapped {@link TypePermission} allows the type, this instance will throw a {@link ForbiddenClassException} + * instead. An instance of this permission cannot be used to allow a type. + *

+ * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class NoPermission implements TypePermission { + + private final TypePermission permission; + + /** + * Construct a NoPermission. + * + * @param permission the permission to negate or null to forbid any type + * @since 1.4.7 + */ + public NoPermission(final TypePermission permission) { + this.permission = permission; + } + + public boolean allows(final Class type) { + if (permission == null || permission.allows(type)) { + throw new ForbiddenClassException(type); + } + return false; + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoTypePermission.java new file mode 100644 index 0000000..802537b --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NoTypePermission.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 08. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * No permission for any type. + *

+ * Can be used to skip any existing default permission. + *

+ * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class NoTypePermission implements TypePermission { + + /** + * @since 1.4.7 + */ + public static final TypePermission NONE = new NoTypePermission(); + + public boolean allows(Class type) { + throw new ForbiddenClassException(type); + } + + public int hashCode() { + return 1; + } + + public boolean equals(Object obj) { + return obj != null && obj.getClass() == NoTypePermission.class; + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/NullPermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NullPermission.java new file mode 100644 index 0000000..d241641 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/NullPermission.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 09. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +import com.thoughtworks.xstream.mapper.Mapper; + +/** + * Permission for null or XStream's null replacement type. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class NullPermission implements TypePermission { + /** + * @since 1.4.7 + */ + public static final TypePermission NULL = new NullPermission(); + + public boolean allows(Class type) { + return type == null || type == Mapper.Null.class; + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java new file mode 100644 index 0000000..fb69b95 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/PrimitiveTypePermission.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 09. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +import com.thoughtworks.xstream.core.util.Primitives; + +/** + * Permission for any primitive type and its boxed counterpart (incl. void). + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class PrimitiveTypePermission implements TypePermission { + /** + * @since 1.4.7 + */ + public static final TypePermission PRIMITIVES = new PrimitiveTypePermission(); + + public boolean allows(Class type) { + return type != null && type.isPrimitive() || Primitives.isBoxed(type); + } + + public int hashCode() { + return 7; + } + + public boolean equals(Object obj) { + return obj != null && obj.getClass() == PrimitiveTypePermission.class; + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/ProxyTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ProxyTypePermission.java new file mode 100644 index 0000000..1f3d3be --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/ProxyTypePermission.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 19. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +import java.lang.reflect.Proxy; + +import com.thoughtworks.xstream.mapper.DynamicProxyMapper; + + +/** + * Permission for any array type. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class ProxyTypePermission implements TypePermission { + /** + * @since 1.4.7 + */ + public static final TypePermission PROXIES = new ProxyTypePermission(); + + public boolean allows(final Class type) { + return type != null && (Proxy.isProxyClass(type) || type == DynamicProxyMapper.DynamicProxy.class); + } + + public int hashCode() { + return 17; + } + + public boolean equals(final Object obj) { + return obj != null && obj.getClass() == ProxyTypePermission.class; + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/RegExpTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/RegExpTypePermission.java new file mode 100644 index 0000000..31ddbd6 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/RegExpTypePermission.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 09. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +import java.util.regex.Pattern; + + +/** + * Permission for any type with a name matching one of the provided regular expressions. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class RegExpTypePermission implements TypePermission { + + private final Pattern[] patterns; + + public RegExpTypePermission(final String[] patterns) { + this(getPatterns(patterns)); + } + + public RegExpTypePermission(final Pattern[] patterns) { + this.patterns = patterns == null ? new Pattern[0] : patterns; + } + + public boolean allows(final Class type) { + if (type != null) { + final String name = type.getName(); + for (int i = 0; i < patterns.length; ++i) + if (patterns[i].matcher(name).matches()) + return true; + } + return false; + } + + private static Pattern[] getPatterns(final String[] patterns) { + if (patterns == null) + return null; + final Pattern[] array = new Pattern[patterns.length]; + for (int i = 0; i < array.length; ++i) + array[i] = Pattern.compile(patterns[i]); + return array; + } +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java new file mode 100644 index 0000000..d476ddf --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypeHierarchyPermission.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 23. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * Permission for a type hierarchy with a name matching one in the provided list. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class TypeHierarchyPermission implements TypePermission { + + private Class type; + + /** + * @since 1.4.7 + */ + public TypeHierarchyPermission(Class type) { + this.type = type; + } + + public boolean allows(Class type) { + if (type == null) + return false; + return this.type.isAssignableFrom(type); + } + +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypePermission.java new file mode 100644 index 0000000..03f02ec --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/TypePermission.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 08. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * Definition of a type permission. + * + * @author Jörg Schaible + * @since 1.4.7 + */ +public interface TypePermission { + /** + * Check permission for a provided type. + * + * @param type the type to check + * @return true if provided type is allowed, false if permission does not handle the type + * @throws ForbiddenClassException if provided type is explicitly forbidden + * @since 1.4.7 + */ + boolean allows(Class type); +} diff --git a/activemq-core/src/main/java/com/thoughtworks/xstream/security/WildcardTypePermission.java b/activemq-core/src/main/java/com/thoughtworks/xstream/security/WildcardTypePermission.java new file mode 100644 index 0000000..9da8249 --- /dev/null +++ b/activemq-core/src/main/java/com/thoughtworks/xstream/security/WildcardTypePermission.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2014 XStream Committers. + * All rights reserved. + * + * Created on 09. January 2014 by Joerg Schaible + */ +package com.thoughtworks.xstream.security; + +/** + * Permission for any type with a name matching one of the provided wildcard expressions. + * + *

+ * Supported are patterns with path expressions using dot as separator: + *

+ *
    + *
  • ?: one non-control character except separator, e.g. for 'java.net.Inet?Address'
  • + *
  • *: arbitrary number of non-control characters except separator, e.g. for types in a package like 'java.lang.*'
  • + *
  • **: arbitrary number of non-control characters including separator, e.g. for types in a package and subpackages like 'java.lang.**'
  • + *
+ *

+ * The complete range of UTF-8 characters is supported except control characters. + *

+ * + * @author Jörg Schaible + * @since 1.4.7 + */ +public class WildcardTypePermission extends RegExpTypePermission { + + /** + * @since 1.4.7 + */ + public WildcardTypePermission(final String[] patterns) { + super(getRegExpPatterns(patterns)); + } + + private static String[] getRegExpPatterns(final String[] wildcards) { + if (wildcards == null) + return null; + final String[] regexps = new String[wildcards.length]; + for (int i = 0; i < wildcards.length; ++i) { + final String wildcardExpression = wildcards[i]; + final StringBuffer result = new StringBuffer(wildcardExpression.length() * 2); + result.append("(?u)"); + final int length = wildcardExpression.length(); + for (int j = 0; j < length; j++) { + final char ch = wildcardExpression.charAt(j); + switch (ch) { + case '\\': + case '.': + case '+': + case '|': + case '[': + case ']': + case '(': + case ')': + case '^': + case '$': + result.append('\\').append(ch); + break; + + case '?': + result.append('.'); + break; + + case '*': + // see "General Category Property" in http://www.unicode.org/reports/tr18/ + if (j + 1 < length && wildcardExpression.charAt(j + 1) == '*') { + result.append("[\\P{C}]*"); + j++; + } else { + result.append("[\\P{C}&&[^").append('.').append("]]*"); + } + break; + + default: + result.append(ch); + break; + } + } + regexps[i] = result.toString(); + } + return regexps; + } +} diff --git a/activemq-core/src/main/java/org/apache/activemq/transport/stomp/JmsFrameTranslator.java b/activemq-core/src/main/java/org/apache/activemq/transport/stomp/JmsFrameTranslator.java index 5274b34..4fd18b0 100644 --- a/activemq-core/src/main/java/org/apache/activemq/transport/stomp/JmsFrameTranslator.java +++ b/activemq-core/src/main/java/org/apache/activemq/transport/stomp/JmsFrameTranslator.java @@ -84,7 +84,7 @@ public class JmsFrameTranslator extends LegacyFrameTranslator implements msg = createMapMessage(in); break; default: - throw new Exception("Unkown transformation: " + transformation); + throw new Exception("Unknown transformation: " + transformation); } } catch (Throwable e) { command.getHeaders().put(Stomp.Headers.TRANSFORMATION_ERROR, e.getMessage()); @@ -243,7 +243,8 @@ public class JmsFrameTranslator extends LegacyFrameTranslator implements } if (xstream == null) { - xstream = new XStream(); + xstream = XStreamSupport.createXStream(); + xstream.ignoreUnknownElements(); } return xstream; diff --git a/activemq-core/src/main/java/org/apache/activemq/transport/stomp/XStreamSupport.java b/activemq-core/src/main/java/org/apache/activemq/transport/stomp/XStreamSupport.java new file mode 100644 index 0000000..abcca72 --- /dev/null +++ b/activemq-core/src/main/java/org/apache/activemq/transport/stomp/XStreamSupport.java @@ -0,0 +1,47 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.activemq.transport.stomp; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.security.AnyTypePermission; +import com.thoughtworks.xstream.security.NoTypePermission; +import com.thoughtworks.xstream.security.PrimitiveTypePermission; +import org.apache.activemq.util.ClassLoadingAwareObjectInputStream; + +import java.util.Collection; +import java.util.Map; + +public class XStreamSupport { + + public static XStream createXStream() { + XStream stream = new XStream(); + stream.addPermission(NoTypePermission.NONE); + stream.addPermission(PrimitiveTypePermission.PRIMITIVES); + stream.allowTypeHierarchy(Collection.class); + stream.allowTypeHierarchy(Map.class); + stream.allowTypes(new Class[]{String.class}); + if (ClassLoadingAwareObjectInputStream.isAllAllowed()) { + stream.addPermission(AnyTypePermission.ANY); + } else { + for (String packageName : ClassLoadingAwareObjectInputStream.serializablePackages) { + stream.allowTypesByWildcard(new String[]{packageName + ".**"}); + } + } + return stream; + } + +} diff --git a/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java b/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java index 82da30c..6a2864f 100644 --- a/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java +++ b/activemq-core/src/main/java/org/apache/activemq/util/ClassLoadingAwareObjectInputStream.java @@ -21,7 +21,10 @@ import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; +import java.util.Map; @SuppressWarnings("rawtypes") public class ClassLoadingAwareObjectInputStream extends ObjectInputStream { @@ -29,6 +32,12 @@ public class ClassLoadingAwareObjectInputStream extends ObjectInputStream { private static final ClassLoader FALLBACK_CLASS_LOADER = ClassLoadingAwareObjectInputStream.class.getClassLoader(); + public static final String[] serializablePackages; + + static { + serializablePackages = System.getProperty("org.apache.activemq.SERIALIZABLE_PACKAGES", "java.lang,java.util,org.apache.activemq,org.fusesource.hawtbuf,com.thoughtworks.xstream.mapper").split(","); + } + /** * Maps primitive type names to corresponding class objects. */ @@ -40,7 +49,9 @@ public class ClassLoadingAwareObjectInputStream extends ObjectInputStream { protected Class resolveClass(ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { ClassLoader cl = Thread.currentThread().getContextClassLoader(); - return load(classDesc.getName(), cl); + Class clazz = load(classDesc.getName(), cl); + checkSecurity(clazz); + return clazz; } protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { @@ -50,18 +61,47 @@ public class ClassLoadingAwareObjectInputStream extends ObjectInputStream { cinterfaces[i] = load(interfaces[i], cl); } + Class clazz = null; try { - return Proxy.getProxyClass(cl, cinterfaces); + clazz = Proxy.getProxyClass(cl, cinterfaces); } catch (IllegalArgumentException e) { try { - return Proxy.getProxyClass(FALLBACK_CLASS_LOADER, cinterfaces); + clazz = Proxy.getProxyClass(FALLBACK_CLASS_LOADER, cinterfaces); } catch (IllegalArgumentException e1) { } - throw new ClassNotFoundException(null, e); + } + + if (clazz != null) { + checkSecurity(clazz); + return clazz; + } else { + throw new ClassNotFoundException(null); } } + public static boolean isAllAllowed() { + return serializablePackages.length == 1 && serializablePackages[0].equals("*"); + } + + private void checkSecurity(Class clazz) throws ClassNotFoundException { + if (!clazz.isPrimitive()) { + if (clazz.getPackage() != null && !isAllAllowed()) { + boolean found = false; + for (String packageName : serializablePackages) { + if (clazz.getPackage().getName().equals(packageName) || clazz.getPackage().getName().startsWith(packageName + ".")) { + found = true; + break; + } + } + + if (!found) { + throw new ClassNotFoundException("Forbidden " + clazz + "! This class is not allowed to be serialized. Add package with 'org.apache.activemq.SERIALIZABLE_PACKAGES' system property."); + } + } + } + } + private Class load(String className, ClassLoader cl) throws ClassNotFoundException { try { return Class.forName(className, false, cl); diff --git a/activemq-optional/src/main/java/org/apache/activemq/transport/xstream/XStreamWireFormat.java b/activemq-optional/src/main/java/org/apache/activemq/transport/xstream/XStreamWireFormat.java index 91ae036..1b83e2e 100755 --- a/activemq-optional/src/main/java/org/apache/activemq/transport/xstream/XStreamWireFormat.java +++ b/activemq-optional/src/main/java/org/apache/activemq/transport/xstream/XStreamWireFormat.java @@ -17,9 +17,15 @@ package org.apache.activemq.transport.xstream; import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import org.apache.activemq.command.Command; import org.apache.activemq.command.MarshallAware; import org.apache.activemq.command.MessageDispatch; +import org.apache.activemq.transport.stomp.XStreamSupport; import org.apache.activemq.transport.util.TextWireFormat; import org.apache.activemq.wireformat.WireFormat; @@ -105,7 +111,28 @@ public class XStreamWireFormat extends TextWireFormat { // Implementation methods // ------------------------------------------------------------------------- protected XStream createXStream() { - return new XStream(); + final XStream xstream = XStreamSupport.createXStream(); + xstream.ignoreUnknownElements(); + xstream.registerConverter(new Converter() { + final Converter delegate = xstream.getConverterLookup().lookupConverterForType(ByteSequence.class); + @Override + public void marshal(Object o, HierarchicalStreamWriter hierarchicalStreamWriter, MarshallingContext marshallingContext) { + ByteSequence byteSequence = (ByteSequence)o; + byteSequence.compact(); + delegate.marshal(byteSequence, hierarchicalStreamWriter, marshallingContext); + } + + @Override + public Object unmarshal(HierarchicalStreamReader hierarchicalStreamReader, UnmarshallingContext unmarshallingContext) { + return delegate.unmarshal(hierarchicalStreamReader, unmarshallingContext); + } + + @Override + public boolean canConvert(Class aClass) { + return aClass == ByteSequence.class; + } + }); + return xstream; } } diff --git a/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java index 1d0ec06..a6cbd51 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java @@ -80,9 +80,9 @@ public class MessageQuery extends QueueBrowseQuery { if (message instanceof ObjectMessage) { try { return ((ObjectMessage) message).getObject(); - } catch (JMSException e) { + } catch (Exception e) { //message could not be parsed, make the reason available - return e; + return new String("Cannot display ObjectMessage body. Reason: " + e.getMessage()); } } if (message instanceof MapMessage) { debian/patches/exclude_mqtt.diff0000664000000000000000000000203613077354155014162 0ustar Description: Disable MQTT transport (new feature of 5.6 release) because it depends on non-existing library in Debian. Author: Damien Raude-Morvan Last-Update: 2012-05-28 Forwarded: not-needed --- a/activemq-core/pom.xml +++ b/activemq-core/pom.xml @@ -54,8 +54,6 @@ org.w3c.dom.traversal*;resolution:=optional, org.fusesource.hawtbuf*;resolution:=optional, org.fusesource.mq.leveldb*;resolution:=optional, - org.fusesource.mqtt.client*;resolution:=optional, - org.fusesource.mqtt.codec*;resolution:=optional, * @@ -407,6 +405,15 @@ + + maven-compiler-plugin + + + **/mqtt/* + + + + maven-surefire-plugin debian/patches/disable_some_modules.diff0000664000000000000000000000220613077354155015641 0ustar Description: Only enable some modules for now Author: Damien Raude-Morvan Last-Update: 2011-05-08 Forwarded: not-needed --- a/pom.xml +++ b/pom.xml @@ -171,27 +171,35 @@ + activemq-console activemq-core activemq-fileserver activemq-jaas + activemq-pool activemq-ra + activemq-run activemq-spring + activemq-jmdns_1.0 kahadb debian/patches/init_debian_default_values.diff0000664000000000000000000000737313077354155017025 0ustar Description: Init script for ActiveMQ : Use default values compliant with Debian installation. ACTIVEMQ_HOME=/usr/share/activemq ACTIVEMQ_BASE="/var/lib/activemq" ACTIVEMQ_CONFIG_DIR="/etc/activemq" ACTIVEMQ_PIDFILE="/var/run/activemq.pid" JAVA_HOME="/usr/lib/jvm/java-6-openjdk/" Create data directory and chown to $ACTIVEMQ_USER Author: Damien Raude-Morvan Last-Update: 2011-07-22 Forwarded: not-needed --- a/assembly/src/release/bin/activemq +++ b/assembly/src/release/bin/activemq @@ -29,18 +29,16 @@ # ------------------------------------------------------------------------ # CONFIGURATION -ACTIVEMQ_CONFIGS="/etc/default/activemq $HOME/.activemqrc" +ACTIVEMQ_CONFIGS="/usr/share/activemq/activemq-options" + +if [ -r "/etc/activemq/instances-enabled/$INSTANCE/options" ]; then + ACTIVEMQ_CONFIGS="/etc/activemq/instances-enabled/$INSTANCE/options" + fi + # Backup invocation parameters COMMANDLINE_ARGS="$@" -# For using instances -if ( basename $0 | grep "activemq-instance-" > /dev/null);then - INST="`basename $0|sed 's/^activemq-instance-//;s/\.sh$//'`" - ACTIVEMQ_CONFIGS="/etc/default/activemq-instance-${INST} $HOME/.activemqrc-instance-${INST}" - echo "INFO: Using alternative activemq configuration files: $ACTIVEMQ_CONFIGS" -fi - ## START:DEFAULTCONFIG # ------------------------------------------------------------------------ # Configuration file for running Apache Active MQ as standalone provider @@ -50,43 +48,13 @@ # Active MQ installation dir if [ -z "$ACTIVEMQ_HOME" ] ; then # try to find ACTIVEMQ - if [ -d /opt/activemq ] ; then - ACTIVEMQ_HOME=/opt/activemq - fi - - if [ -d "${HOME}/opt/activemq" ] ; then - ACTIVEMQ_HOME="${HOME}/opt/activemq" + if [ -d /usr/share/activemq ] ; then + ACTIVEMQ_HOME=/usr/share/activemq fi - - ## resolve links - $0 may be a link to activemq's home - PRG="$0" - progname=`basename "$0"` - saveddir=`pwd` - - # need this for relative symlinks - dirname_prg=`dirname "$PRG"` - cd "$dirname_prg" - - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '.*/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi - done - - ACTIVEMQ_HOME=`dirname "$PRG"`/.. - - cd "$saveddir" - - # make it fully qualified - ACTIVEMQ_HOME=`cd "$ACTIVEMQ_HOME" && pwd` fi if [ -z "$ACTIVEMQ_BASE" ] ; then - ACTIVEMQ_BASE="$ACTIVEMQ_HOME" + ACTIVEMQ_BASE="/var/lib/activemq" fi # Active MQ configuration directory @@ -102,7 +70,7 @@ # Configure a user with non root priviledges, if no user is specified do not change user if [ -z "$ACTIVEMQ_USER" ] ; then - ACTIVEMQ_USER="" + ACTIVEMQ_USER="activemq" fi # Active MQ data directory @@ -140,14 +108,14 @@ # Location of the pidfile if [ -z "$ACTIVEMQ_PIDFILE" ]; then - ACTIVEMQ_PIDFILE="$ACTIVEMQ_DATA/activemq-`hostname`.pid" + ACTIVEMQ_PIDFILE="/var/run/activemq.pid" fi # Location of the java installation # Specify the location of your java installation using JAVA_HOME, or specify the # path to the "java" binary using JAVACMD # (set JAVACMD to "auto" for automatic detection) -#JAVA_HOME="" +JAVA_HOME="/usr/lib/jvm/java-6-openjdk/" JAVACMD="auto" # Set jvm memory configuration @@ -391,6 +359,15 @@ DOIT_POSTFIX=" - $ACTIVEMQ_USER" echo "INFO: changing to user '$ACTIVEMQ_USER' to invoke java" fi + + # Create data directory and chown to $ACTIVEMQ_USER + if [ ! -d "$ACTIVEMQ_DATA_DIR" ]; then + mkdir -p $ACTIVEMQ_DATA_DIR + if [ -z "$ACTIVEMQ_USER" ]; then + chown -R $ACTIVEMQ_USER $ACTIVEMQ_DATA_DIR + fi + fi + # Execute java binary if [ -n "$PIDFILE" ] && [ "$PIDFILE" != "stop" ];then $DOIT_PREFIX "$JAVACMD $ACTIVEMQ_OPTS $ACTIVEMQ_DEBUG_OPTS \ debian/patches/CVE-2015-7559.patch0000664000000000000000000000365413077354155013273 0ustar From: Markus Koschany Date: Sun, 23 Apr 2017 22:13:33 +0200 Subject: CVE-2015-7559 Bug-Debian: https://bugs.debian.org/860866 Bug-Upstream: https://issues.apache.org/jira/browse/AMQ-6470 Origin: https://git-wip-us.apache.org/repos/asf?p=activemq.git;h=b8fc78e --- .../java/org/apache/activemq/ActiveMQConnection.java | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/activemq-core/src/main/java/org/apache/activemq/ActiveMQConnection.java b/activemq-core/src/main/java/org/apache/activemq/ActiveMQConnection.java index 57ca8f1..d5797d6 100755 --- a/activemq-core/src/main/java/org/apache/activemq/ActiveMQConnection.java +++ b/activemq-core/src/main/java/org/apache/activemq/ActiveMQConnection.java @@ -1860,7 +1860,6 @@ public class ActiveMQConnection implements Connection, TopicConnection, QueueCon @Override public Response processControlCommand(ControlCommand command) throws Exception { - onControlCommand(command); return null; } @@ -2296,23 +2295,6 @@ public class ActiveMQConnection implements Connection, TopicConnection, QueueCon inputStreams.remove(stream); } - protected void onControlCommand(ControlCommand command) { - String text = command.getCommand(); - if (text != null) { - if ("shutdown".equals(text)) { - LOG.info("JVM told to shutdown"); - System.exit(0); - } - if (false && "close".equals(text)){ - LOG.error("Broker " + getBrokerInfo() + "shutdown connection"); - try { - close(); - } catch (JMSException e) { - } - } - } - } - protected void onConnectionControl(ConnectionControl command) { if (command.isFaultTolerant()) { this.optimizeAcknowledge = false; debian/patches/exclude_leveldb.diff0000664000000000000000000000144013077354155014610 0ustar Description: Disable LevelDB Store (new feature of 5.6 release) because it depends on non-existing library in Debian. Author: Damien Raude-Morvan Last-Update: 2012-05-28 Forwarded: not-needed --- a/activemq-core/pom.xml +++ b/activemq-core/pom.xml @@ -53,7 +53,6 @@ org.springframework.beans.factory.xml;resolution:=optional, org.w3c.dom.traversal*;resolution:=optional, org.fusesource.hawtbuf*;resolution:=optional, - org.fusesource.mq.leveldb*;resolution:=optional, * @@ -410,6 +409,7 @@ **/mqtt/* + **/leveldb/* debian/activemq.README.Debian0000664000000000000000000000424013077354155013053 0ustar ActiveMQ Server for Debian ========================== Disabled features ----------------- This package doesn't contains (yet) all features provided by upstream as some dependencies are missing from Debian. For a list of disabled modules, you can look at /usr/share/doc/libactivemq-java/README.Debian Main ActiveMQ instance ---------------------- Current package provide a default ("main") instance for ActiveMQ. As of now, this instance only listen on loopback interface (127.0.0.1) on port 61616, with OpenWire protocol enabled. Messages storage is handled by kahadb in /var/lib/activemq/main/data/kahadb You can customize its environnement here : cp /usr/share/activemq/activemq-options /etc/activemq/instances-available/main/options Edit the file /etc/activemq/instances-available/main/options and restart it. And it's XML configuration can be edited here : /etc/activemq/instances-available/main/activemq.xml Enable it: ln -s /etc/activemq/instances-available/main \ /etc/activemq/instances-enabled/main Start it : invoke-rc.d activemq start Debug an ActiveMQ instance -------------------------- You can start any ActiveMQ instance in foreground for debugging. Start instance `foo` in forground: # /etc/init.d/activemq console foo Setup a new ActiveMQ instance ----------------------------- To create a new instance, you have to : mkdir /etc/activemq/instances-available/ Create your own configuration into /etc/activemq/instances-available//activemq.xml For example, you can copy a sample configuration : cp /etc/activemq/instances-available/main/* \ /etc/activemq/instances-available// If you need some other Xms / Xmx settings or want to use another JDK: cp /usr/share/activemq/activemq-options \ /etc/activemq/instances-available//options In this file, you can modify ACTIVEMQ_BASE if you want to store your data elsewhere than /var/lib/activemq// or JAVA_HOME if you want to use another JDK. Register this instance into enabled: ln -s /etc/activemq/instances-available/ \ /etc/activemq/instances-enabled/ Start it : invoke-rc.d activemq start debian/libactivemq-java.poms0000664000000000000000000000507213077354155013325 0ustar # List of POM files for the package # Format of this file is: # [option]* # where option can be: # --ignore: ignore this POM or # --no-parent: remove the tag from the POM # --package=: an alternative package to use when installing this POM # and its artifact # --has-package-version: to indicate that the original version of the POM is the same as the upstream part # of the version for the package. # --keep-elements=: a list of XML elements to keep in the POM # during a clean operation with mh_cleanpom or mh_installpom # --artifact=: path to the build artifact associated with this POM, # it will be installed when using the command mh_install # --java-lib: install the jar into /usr/share/java to comply with Debian # packaging guidelines # --usj-name=: name to use when installing the library in /usr/share/java # --usj-version=: version to use when installing the library in /usr/share/java # --no-usj-versionless: don't install the versionless link in /usr/share/java # --dest-jar=: the destination for the real jar # it will be installed with mh_install. # --classifier=: Optional, the classifier for the jar. Empty by default. # --ignore-pom: don't install the POM with mh_install or mh_installpoms. To use with POM files that are created # temporarily for certain artifacts such as Javadoc jars. # pom.xml --no-parent --has-package-version activemq-core/pom.xml --has-package-version --java-lib kahadb/pom.xml --has-package-version --java-lib activemq-jmdns_1.0/pom.xml --has-package-version activemq-jaas/pom.xml --has-package-version activemq-ra/pom.xml --has-package-version activemq-pool/pom.xml --has-package-version activemq-spring/pom.xml --has-package-version activemq-fileserver/pom.xml --has-package-version activemq-console/pom.xml --has-package-version --java-lib activemq-run/pom.xml --has-package-version --java-lib activemq-optional/pom.xml --ignore-pom activemq-karaf/pom.xml --ignore-pom activemq-camel/pom.xml --ignore-pom activemq-all/pom.xml --ignore-pom activemq-rar/pom.xml --ignore-pom activemq-tooling/pom.xml --ignore-pom activemq-tooling/maven-activemq-plugin/pom.xml --ignore-pom activemq-tooling/maven-activemq-perf-plugin/pom.xml --ignore-pom activemq-tooling/maven-activemq-memtest-plugin/pom.xml --ignore-pom activemq-web/pom.xml --ignore-pom activemq-web-demo/pom.xml --ignore-pom activemq-web-console/pom.xml --ignore-pom activemq-blueprint/pom.xml --ignore-pom activemq-xmpp/pom.xml --ignore-pom assembly/pom.xml --ignore-pom debian/activemq.xml0000664000000000000000000000454513077354155011545 0ustar debian/libactivemq-java-doc.doc-base0000664000000000000000000000035413077354155014565 0ustar Document: activemq Title: Apache ActiveMQ libraries Author: The Apache Software Foundation Section: Programming/Java Format: HTML Index: /usr/share/doc/libactivemq-java/api/index.html Files: /usr/share/doc/libactivemq-java/api/*.html debian/maven.rules0000664000000000000000000000442513077354155011371 0ustar # Maven rules - transform Maven dependencies and plugins # Format of this file is: # [group] [artifact] [type] [version] [classifier] [scope] # where each element can be either # - the exact string, for example org.apache for the group, or 3.1 # for the version. In this case, the element is simply matched # and left as it is # - * (the star character, alone). In this case, anything will # match and be left as it is. For example, using * on the # position of the artifact field will match any artifact id # - a regular expression of the form s/match/replace/ # in this case, elements that match are transformed using # the regex rule. # All elements much match before a rule can be applied # Example rule: match jar with groupid= junit, artifactid= junit # and version starting with 3., replacing the version with 3.x # junit junit jar s/3\\..*/3.x/ org.apache.activemq activemq-core jar s/.*/5.6.0/ * * org.apache.activemq activemq-jaas jar s/.*/5.6.0/ * * org.apache.activemq activemq-ra jar s/.*/5.6.0/ * * org.apache.activemq kahadb jar s/.*/5.6.0/ * * org.apache.activemq activemq-pool jar s/.*/5.6.0/ * * org.apache.activemq activemq-console jar s/.*/5.6.0/ * * # Dependencies org.apache.activemq.protobuf activemq-protobuf * s/.*/1.1/ * * commons-collections commons-collections jar s/3\..*/3.x/ * * commons-httpclient commons-httpclient jar s/3\..*/3.x/ * * commons-net commons-net jar s/2\..+/2.x/ * * s/jdom/org.jdom/ jdom jar s/1\..*/debian/ * * log4j log4j jar s/1\.2\..*/1.2.x/ * * junit junit jar s/.*/4.x/ * * s/regexp/jakarta-regexp/ s/regexp/jakarta-regexp/ jar s/.*/debian/ * * commons-logging commons-logging * s/.*/debian/ * * commons-logging commons-logging-api * s/.*/debian/ * * s/ant/org.apache.ant/ * * s/.*/debian/ * * org.springframework * * s/.*/3.x/ * * s/velocity/org.apache.velocity/ * * s/.*/debian/ * * # JEE s/org.apache.geronimo.specs/javax/ s/geronimo-jms_1.1_spec/javaee-api/ jar s/.*/5.0/ * * s/org.apache.geronimo.specs/javax/ s/geronimo-jta_1.0.1B_spec/javaee-api/ jar s/.*/5.0/ * * s/org.apache.geronimo.specs/javax/ s/geronimo-jacc_1.1_spec/javaee-api/ jar s/.*/5.0/ * * s/org.apache.geronimo.specs/javax/ s/geronimo-j2ee-connector_1.5_spec/javaee-api/ jar s/.*/5.0/ * * s/org.apache.geronimo.specs/javax/ s/geronimo-servlet_2.5_spec/javaee-api/ jar s/.*/5.0/ * * debian/maven.ignoreRules0000664000000000000000000000452413077354155012535 0ustar # Maven ignore rules - ignore some Maven dependencies and plugins # Format of this file is: # [group] [artifact] [type] [version] [classifier] [scope] # where each element can be either # - the exact string, for example org.apache for the group, or 3.1 # for the version. In this case, the element is simply matched # and left as it is # - * (the star character, alone). In this case, anything will # match and be left as it is. For example, using * on the # position of the artifact field will match any artifact id # All elements much match before a rule can be applied # Example rule: match jar with groupid= junit, artifactid= junit # and version starting with 3., this dependency is then removed # from the POM # junit junit jar s/3\\..*/3.x/ axion axion * * * * commons-primitives commons-primitives * * * * org.apache.activemq activemq-openwire-generator * * * * org.springframework.osgi spring-osgi-core * * * * org.apache.camel camel-core * * * * org.apache.camel camel-spring * * * * org.apache.derby derby * * * * org.apache.directory.server apacheds-core * * * * org.apache.directory.server apacheds-core-integ * * * * org.apache.directory.server apacheds-server-integ * * * * org.apache.ftpserver ftpserver-core * * * * org.jencks jencks * * * * org.eclipse.jetty.aggregate jetty-all-server * * * * org.fusesource.mqtt-client mqtt-client * * * * org.fusesource.fuse-extra fusemq-leveldb * * * * # Replaced by glassfish-j2ee org.apache.geronimo.specs geronimo-jta_1.0.1B_spec * * * * org.apache.geronimo.specs geronimo-j2ee-management_1.1_spec * * * * org.apache.geronimo.specs geronimo-annotation_1.0_spec * * * * org.apache.geronimo.specs geronimo-jacc_1.1_spec * * * * org.apache.geronimo.components geronimo-transaction * * * * # Maven plugins org.apache.maven.plugins maven-eclipse-plugin * * * * org.apache.rat apache-rat-plugin * * * * org.codehaus.mojo cobertura-maven-plugin * * * * org.codehaus.mojo findbugs-maven-plugin * * * * org.codehaus.mojo ianal-maven-plugin * * * * org.codehaus.mojo taglist-maven-plugin * * * * xsddoc maven-xsddoc-plugin * * * * org.mortbay.jetty jetty-maven-plugin * * * * # Test ? org.apache.activemq activeio-core test-jar * * * org.apache.activemq activemq-core jar * tests * org.apache.activemq activemq-core test-jar * * * org.jmock jmock-junit4 * * * * org.jmock jmock-legacy * * * * org.hamcrest hamcrest-all * * * * debian/maven.properties0000664000000000000000000000017113077354155012425 0ustar # Include here properties to pass to Maven during the build. # For example: # maven.test.skip=true maven.test.skip=true debian/activemq.links0000664000000000000000000000720613077354155012062 0ustar /usr/share/java/activemq-run.jar /usr/share/activemq/bin/run.jar /usr/share/java/activemq-console.jar /usr/share/activemq/lib/activemq-console.jar /usr/share/java/activemq-core.jar /usr/share/activemq/lib/activemq-core.jar /usr/share/java/activemq-jaas.jar /usr/share/activemq/lib/activemq-jaas.jar /usr/share/java/activemq-protobuf.jar /usr/share/activemq/lib/activemq-protobuf.jar /usr/share/java/glassfish-javaee.jar /usr/share/activemq/lib/glassfish-javaee.jar /usr/share/java/jcl-over-slf4j.jar /usr/share/activemq/lib/jcl-over-slf4j.jar /usr/share/java/kahadb.jar /usr/share/activemq/lib/kahadb.jar /usr/share/java/slf4j-api.jar /usr/share/activemq/lib/slf4j-api.jar /usr/share/java/activeio-core.jar /usr/share/activemq/lib/optional/activeio-core.jar /usr/share/java/activemq-jmdns_1.0.jar /usr/share/activemq/lib/optional/activemq-jmdns_1.0.jar /usr/share/java/activemq-pool.jar /usr/share/activemq/lib/optional/activemq-pool.jar /usr/share/java/activemq-spring.jar /usr/share/activemq/lib/optional/activemq-spring.jar /usr/share/java/asm3.jar /usr/share/activemq/lib/optional/asm3.jar /usr/share/java/asm3-commons.jar /usr/share/activemq/lib/optional/asm3-commons.jar /usr/share/java/commons-beanutils.jar /usr/share/activemq/lib/optional/commons-beanutils.jar /usr/share/java/commons-codec.jar /usr/share/activemq/lib/optional/commons-codec.jar /usr/share/java/commons-collections3.jar /usr/share/activemq/lib/optional/commons-collections3.jar /usr/share/java/commons-dbcp.jar /usr/share/activemq/lib/optional/commons-dbcp.jar /usr/share/java/commons-httpclient.jar /usr/share/activemq/lib/optional/commons-httpclient.jar /usr/share/java/commons-lang.jar /usr/share/activemq/lib/optional/commons-lang.jar /usr/share/java/commons-net2.jar /usr/share/activemq/lib/optional/commons-net2.jar /usr/share/java/commons-pool.jar /usr/share/activemq/lib/optional/commons-pool.jar /usr/share/java/jasypt.jar /usr/share/activemq/lib/optional/jasypt.jar /usr/share/java/jettison.jar /usr/share/activemq/lib/optional/jettison.jar /usr/share/java/josql.jar /usr/share/activemq/lib/optional/josql.jar /usr/share/java/log4j-1.2.jar /usr/share/activemq/lib/optional/log4j-1.2.jar /usr/share/java/slf4j-log4j12.jar /usr/share/activemq/lib/optional/slf4j-log4j12.jar /usr/share/java/spring3-aop.jar /usr/share/activemq/lib/optional/spring3-aop.jar /usr/share/java/spring3-beans.jar /usr/share/activemq/lib/optional/spring3-beans.jar /usr/share/java/spring3-context.jar /usr/share/activemq/lib/optional/spring3-context.jar /usr/share/java/spring3-core.jar /usr/share/activemq/lib/optional/spring3-core.jar /usr/share/java/spring3-expression.jar /usr/share/activemq/lib/optional/spring3-expression.jar /usr/share/java/spring3-jms.jar /usr/share/activemq/lib/optional/spring3-jms.jar /usr/share/java/spring3-orm.jar /usr/share/activemq/lib/optional/spring3-orm.jar /usr/share/java/spring3-transaction.jar /usr/share/activemq/lib/optional/spring3-transaction.jar /usr/share/java/stax-api.jar /usr/share/activemq/lib/optional/stax-api.jar /usr/share/java/velocity.jar /usr/share/activemq/lib/optional/velocity.jar /usr/share/java/wstx-lgpl.jar /usr/share/activemq/lib/optional/wstx-lgpl.jar /usr/share/java/xbean-spring.jar /usr/share/activemq/lib/optional/xbean-spring.jar /usr/share/java/xpp3.jar /usr/share/activemq/lib/optional/xpp3.jar /usr/share/java/xstream.jar /usr/share/activemq/lib/optional/xstream.jar debian/compat0000664000000000000000000000000213077354155010400 0ustar 7 debian/activemq-options0000664000000000000000000000067113077354155012433 0ustar # Time to wait for the server to start, in seconds STARTTIME=5 # !!! Use a specific data directory for each instance ACTIVEMQ_BASE="/var/lib/activemq/$INSTANCE" # Use openjdk-6 as default Java runtime JAVA_HOME="/usr/lib/jvm/java-6-openjdk/" # Set some JVM memory options ACTIVEMQ_OPTS="-Xms512M -Xmx512M -Dorg.apache.activemq.UseDedicatedTaskRunner=true" # Arguments to launch /usr/bin/activemq ACTIVEMQ_ARGS="start xbean:activemq.xml" debian/activemq.dirs0000664000000000000000000000034013077354155011673 0ustar /etc/activemq /etc/activemq/instances-enabled /etc/activemq/instances-available /usr/share/activemq /usr/share/activemq/bin /usr/share/activemq/lib /usr/share/activemq/lib/optional /var/lib/activemq /var/lib/activemq/data debian/changelog0000664000000000000000000001132513110575750011050 0ustar activemq (5.6.0+dfsg-1+deb7u3build0.14.04.1) trusty-security; urgency=medium * fake sync from Debian -- Tyler Hicks Mon, 22 May 2017 14:55:36 +0000 activemq (5.6.0+dfsg-1+deb7u3) wheezy-security; urgency=high * Team upload. * Fix CVE-2015-7559. DoS in activemq-core via shutdown command. -- Markus Koschany Mon, 24 Apr 2017 12:50:21 +0200 activemq (5.6.0+dfsg-1+deb7u2) wheezy-security; urgency=high * Team upload. * Fix CVE-2015-5254: Apache ActiveMQ 5.x before 5.13.0 does not restrict the classes that can be serialized in the broker, which allows remote attackers to execute arbitrary code via a crafted serialized Java Message Service (JMS) ObjectMessage object. -- Markus Koschany Fri, 18 Mar 2016 22:47:35 +0100 activemq (5.6.0+dfsg-1+deb7u1) wheezy-security; urgency=high * Team upload. * Fixed security issues (Closes: #777196, #792857) - CVE-2014-3612: JAAS LDAPLoginModule allows empty password authentication - CVE-2014-3600: XML External Entity expansion when evaluating XPath expressions - CVE-2014-3576: DoS via unauthenticated remote shutdown command - Disable JMX by default (Closes: #769887) -- Emmanuel Bourg Fri, 07 Aug 2015 22:16:39 +0200 activemq (5.6.0+dfsg-1) unstable; urgency=low * New upstream release: - Refresh all patches. - Drop d/patches/CVE-2011-4605.diff: merged upstream. - d/patches/exclude_mqtt.diff: Disable MQTT transport. - d/patches/exclude_leveldb.diff: Disable LevelDB Store. * d/maven.rules: Upgrade internal components version. * Build-Depends on libxstream-java (>= 1.4). -- Damien Raude-Morvan Fri, 25 May 2012 00:47:55 +0200 activemq (5.5.0+dfsg-7) unstable; urgency=low [ Ulrich Dangel ] * Install the activemq-{core,console,run} and kahadb jar files to /usr/share/java. (Closes: #668943) - Add the necessary --java-lib flag to d/libactivemq-java.poms [ Damien Raude-Morvan ] * Thanks to Ulrich Dangel for RC bugfix, upload to unstable. -- Damien Raude-Morvan Tue, 01 May 2012 14:38:27 +0200 activemq (5.5.0+dfsg-6) unstable; urgency=low * d/patches/activemq-admin.patch: Fix activemq-admin "unexpected operator" (Closes: #662698). Thanks to Mathieu Mitchell. * Bump Standards-Version to 3.9.3: no changes needed. -- Damien Raude-Morvan Sun, 01 Apr 2012 20:26:10 +0200 activemq (5.5.0+dfsg-5) unstable; urgency=high * Fix CVE-2011-4905 (potential Denial of Service) by backporting upstream patch on failover feature. (Closes: #655495). * Set urgency=high for security fix. -- Damien Raude-Morvan Sun, 15 Jan 2012 19:38:21 +0100 activemq (5.5.0+dfsg-4) unstable; urgency=low * d/activemq.init: Merge change proposed by Jonas Genannt to allow console startup, useful for debugging purposes. (Closes: #645241). -- Damien Raude-Morvan Wed, 26 Oct 2011 21:13:20 +0200 activemq (5.5.0+dfsg-3) unstable; urgency=low * d/control: Wrap-and-sort Build-Depends. * d/activemq.links: Since libasm3-java package now provide splited JAR also link all ASM3 jars (Closes: #644834). * d/maven.rules: - Don't replace osgi artifacts since they are now provided by official osgi-core package. - Force 2.1.1 version of maven-war-plugin. -- Damien Raude-Morvan Tue, 11 Oct 2011 23:11:16 +0200 activemq (5.5.0+dfsg-2) unstable; urgency=low * Drop d/patches/exclude_xsd_install.diff and install XSD files into JAR. * Build-Depends on libxbean-java 3.7 for maven-xbean-plugin. * Add new "activemq" package to start ActiveMQ server: - d/activemq.{postinst,prerm}: Create a activemq system user - d/activemq.{install,links}: Install activemq and activemq-admin commands to /usr/bin/, set /usr/share/activemq/ as ACTIVEMQ_HOME and install many examples into /usr/share/doc/activemq/examples/. - d/activemq.README.Debian: Describe how to setup an alternative instance (Closes: #634868). - Provide a way to handle multi-instances of activemq. Each directory inside /etc/activemq/instances-enabled/ will be started as an instance with its own configuration. Thanks to Jonas Genannt for patch. * d/patches/javadoc_links.diff: Update links to system-wide Javadoc. * d/libactivemq-java.README.Debian: Describe disabled features regarding upstream package. * d/control: Don't use package name in synospis. -- Damien Raude-Morvan Sun, 04 Sep 2011 18:50:59 +0200 activemq (5.5.0+dfsg-1) unstable; urgency=low * Initial release (Closes: #627778). -- Damien Raude-Morvan Tue, 21 Jun 2011 00:32:12 +0200 debian/activemq.install0000664000000000000000000000174013077354155012405 0ustar # File list from assembly/src/main/descriptors/common-bin.xml # and assembly/src/main/descriptors/unix-bin.xml assembly/src/release/README.txt /usr/share/activemq/ assembly/src/release/bin/activemq /usr/bin/ assembly/src/release/bin/activemq-admin /usr/bin/ assembly/src/release/conf/*.properties /usr/share/doc/activemq/examples/conf/ assembly/src/release/conf/*.xml /usr/share/doc/activemq/examples/conf/ assembly/src/release/conf/log4j.properties /etc/activemq/instances-available/main/ assembly/src/release/example/ruby/* /usr/share/doc/activemq/examples/ruby/ assembly/src/release/example/transactions/* /usr/share/doc/activemq/examples/transactions/ assembly/src/release/lib/activemq-rar.txt /usr/share/activemq/lib/ assembly/src/sample-conf/activemq-*.xml /usr/share/doc/activemq/examples/conf/ debian/activemq-options /usr/share/activemq/ debian/activemq.xml /etc/activemq/instances-available/main/ debian/activemq.init0000664000000000000000000001635113077354155011706 0ustar #! /bin/sh ### BEGIN INIT INFO # Provides: activemq # Required-Start: $remote_fs # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: ActiveMQ instance # Description: Start ActiveMQ instance ### END INIT INFO # Author: Damien Raude-Morvan # Author: Jonas Genannt PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC="ActiveMQ instance" NAME=activemq DAEMON=/usr/bin/$NAME SCRIPTNAME=/etc/init.d/`basename $0` DEFAULT=/etc/default/$NAME ACTIVEMQ_JAR=/usr/share/activemq/bin/run.jar ACTIVEMQ_INSTANCES_ENABLED=/etc/activemq/instances-enabled # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.2-14) to ensure that this file is present # and status_of_proc is working. . /lib/lsb/init-functions # Whether to start ActiveMQ (as a daemon or not) NO_START=0 ACTIVEMQ_USER=activemq DIETIME=2 # Read configuration variable file if it is present [ -r $DEFAULT ] && . $DEFAULT # Exit now if daemon binary is not installed test -x $DAEMON || exit 0 # Check that the user exists (if we set a user) # Does the user exist? if [ -n "$ACTIVEMQ_USER" ] ; then if getent passwd | grep -q "^$ACTIVEMQ_USER:"; then # Obtain the uid and gid DAEMONUID=`getent passwd |grep "^$ACTIVEMQ_USER:" | awk -F : '{print $3}'` DAEMONGID=`getent passwd |grep "^$ACTIVEMQ_USER:" | awk -F : '{print $4}'` else log_failure_msg "The user $ACTIVEMQ_USER, required to run $NAME does not exist." exit 1 fi fi # Check whether startup has been disabled if [ "$NO_START" != "0" -a "$1" != "stop" ]; then [ "$VERBOSE" != "no" ] && log_failure_msg "Not starting $NAME - edit /etc/default/$NAME and change NO_START to be 0 (or comment it out)." exit 0 fi # Check if any instances exists in instances-enabled directory check_instances_enabled() { if [ -d "$ACTIVEMQ_INSTANCES_ENABLED" ] && [ `/bin/ls $ACTIVEMQ_INSTANCES_ENABLED | wc -l` -gt 0 ]; then return 1 else return 0 fi } # Check if a given process pid's cmdline matches a given name running_pid() { pid=$1 [ -z "$pid" ] && return 1 [ ! -d /proc/$pid ] && return 1 cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|grep "activemq\.base" |cut -d= -f2` getinst=`basename $cmd` # Is this the expected server [ "x$getinst" != "x$INSTANCE" ] && return 1 return 0 } # Check if the process is running looking at /proc # (works for all users) running() { # No pidfile, probably no daemon present [ ! -f "$ACTIVEMQ_PIDFILE" ] && return 1 pid=`cat $ACTIVEMQ_PIDFILE` running_pid $pid || return 1 return 0 } # Start the process using the wrapper start_servers() { mkdir -p /var/run/activemq/ chown $ACTIVEMQ_USER /var/run/activemq/ if check_instances_enabled; then echo "No instances found at ${ACTIVEMQ_INSTANCES_ENABLED}." exit 0 fi for INSTANCE in `ls $ACTIVEMQ_INSTANCES_ENABLED`; do if [ -d "${ACTIVEMQ_INSTANCES_ENABLED}/${INSTANCE}" ]; then ACTIVEMQ_PIDFILE="/var/run/activemq/$INSTANCE.pid" ACTIVEMQ_CONFIG_DIR="$ACTIVEMQ_INSTANCES_ENABLED/$INSTANCE" export INSTANCE export ACTIVEMQ_USER export ACTIVEMQ_PIDFILE export ACTIVEMQ_HOME=/usr/share/activemq export ACTIVEMQ_CONFIG_DIR # Import global configuration . /usr/share/activemq/activemq-options # Import per instance configuration [ -r "${ACTIVEMQ_CONFIG_DIR}/options" ] && . ${ACTIVEMQ_CONFIG_DIR}/options log_progress_msg "$INSTANCE" start-stop-daemon --start --quiet --pidfile $ACTIVEMQ_PIDFILE \ --chuid $ACTIVEMQ_USER --background \ --name java --startas $DAEMON -- $ACTIVEMQ_ARGS errcode=$? if [ ! $errcode ]; then log_progress_msg "(failed)" else [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time if running; then log_progress_msg "(running)" else log_progress_msg "(failed?)" fi fi else echo -n "${INSTANCE} (not an directory)" fi done } # Stops an running Instance stop_server() { INSTANCE=$1 ACTIVEMQ_PIDFILE="/var/run/activemq/$INSTANCE.pid" start-stop-daemon --stop --quiet --pidfile $ACTIVEMQ_PIDFILE \ --user $ACTIVEMQ_USER \ --name java --startas $DAEMON -- stop if running; then force_stop fi if running; then log_progress_msg "(failed)" else log_progress_msg "(stopped)" fi } # Stop the process using the wrapper stop_servers() { for INSTANCE in `ls /var/run/activemq/`; do INSTANCE=$(echo $INSTANCE | sed 's@.pid@@') log_progress_msg "$INSTANCE" stop_server "$INSTANCE" done } # Force the process to die killing it manually force_stop() { [ ! -e "$ACTIVEMQ_PIDFILE" ] && return if running ; then kill -15 $pid # Is it really dead? sleep "$DIETIME"s if running ; then kill -9 $pid sleep "$DIETIME"s if running ; then echo "Cannot kill $NAME (pid=$pid)!" exit 1 fi fi fi rm -f $ACTIVEMQ_PIDFILE } case "$1" in console) INSTANCE=$2 if [ ! -z $INSTANCE ]; then log_daemon_msg "Starting with Console $DESC " "$INSTANCE" if [ -r "${ACTIVEMQ_INSTANCES_ENABLED}/${INSTANCE}/activemq.xml" ]; then ACTIVEMQ_PIDFILE="/var/run/activemq/$INSTANCE.pid" ACTIVEMQ_CONFIG_DIR="$ACTIVEMQ_INSTANCES_ENABLED/$INSTANCE" if [ -f $ACTIVEMQ_PIDFILE ]; then stop_server "$INSTANCE" fi export INSTANCE export ACTIVEMQ_USER export ACTIVEMQ_PIDFILE export ACTIVEMQ_HOME=/usr/share/activemq export ACTIVEMQ_CONFIG_DIR # Import global configuration . /usr/share/activemq/activemq-options # Import per instance configuration [ -r "${ACTIVEMQ_CONFIG_DIR}/options" ] && . ${ACTIVEMQ_CONFIG_DIR}/options ACTIVEMQ_ARGS=$(echo $ACTIVEMQ_ARGS | sed 's/start/console/') start-stop-daemon --start --pidfile $ACTIVEMQ_PIDFILE \ --chuid $ACTIVEMQ_USER \ --name java --startas $DAEMON -- $ACTIVEMQ_ARGS else echo "File ${ACTIVEMQ_INSTANCES_ENABLED}/${BROKER}/activemq.xml not found." exit 1 fi else echo "Usage: $0 console foo" echo "This will start instance foo in foreground useful for debugging purposes." exit 1 fi log_end_msg 0 ;; start) log_daemon_msg "Starting $DESC " "$NAME" start_servers log_end_msg 0 ;; stop) log_daemon_msg "Stopping $DESC" "$NAME" stop_servers log_end_msg 0 ;; restart|force-reload) log_daemon_msg "Restarting $DESC" "$NAME" stop_servers start_servers log_end_msg 0 ;; status) log_daemon_msg "Checking status of $DESC" "$NAME" for INSTANCE in `ls $ACTIVEMQ_INSTANCES_ENABLED`; do if [ -d "${ACTIVEMQ_INSTANCES_ENABLED}/${INSTANCE}" ]; then ACTIVEMQ_PIDFILE="/var/run/activemq/${INSTANCE}.pid" log_progress_msg "$INSTANCE" if running; then log_progress_msg "(running)" else log_progress_msg "(stopped)" fi fi done log_end_msg 0 ;; reload) log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon" log_warning_msg "cannot re-read the config file (use restart)." ;; *) echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status|console}" >&2 exit 1 ;; esac exit 0 debian/maven.cleanIgnoreRules0000664000000000000000000000224413077354155013475 0ustar # Maven ignore rules - ignore some Maven dependencies and plugins # Format of this file is: # [group] [artifact] [type] [version] [classifier] [scope] # where each element can be either # - the exact string, for example org.apache for the group, or 3.1 # for the version. In this case, the element is simply matched # and left as it is # - * (the star character, alone). In this case, anything will # match and be left as it is. For example, using * on the # position of the artifact field will match any artifact id # All elements much match before a rule can be applied # Example rule: match jar with groupid= junit, artifactid= junit # and version starting with 3., this dependency is then removed # from the POM # junit junit jar s/3\\..*/3.x/ # Maven plugins org.apache.maven.plugins maven-eclipse-plugin * * * * org.apache.rat apache-rat-plugin * * * * org.codehaus.mojo cobertura-maven-plugin * * * * org.codehaus.mojo findbugs-maven-plugin * * * * org.codehaus.mojo ianal-maven-plugin * * * * org.codehaus.mojo taglist-maven-plugin * * * * xsddoc maven-xsddoc-plugin * * * * org.mortbay.jetty jetty-maven-plugin * * * * org.jvnet.jaxb2.maven2 maven-jaxb2-plugin * * * * debian/activemq.postrm0000664000000000000000000000231713077354155012264 0ustar #!/bin/sh set -e AMQ_HOME=/var/lib/activemq AMQ_GROUP=activemq AMQ_USER=activemq del_group() { if getent group $AMQ_GROUP > /dev/null 2>&1; then if [ -x "`which delgroup 2>/dev/null`" ]; then delgroup --system --only-if-empty $AMQ_GROUP else echo >&2 "Not removing \`$AMQ_GROUP' system group" \ "because delgroup command was not found." fi fi } del_user() { if getent passwd $AMQ_USER > /dev/null 2>&1; then if [ -x "`which deluser 2>/dev/null`" ]; then deluser --system $AMQ_USER else echo >&2 "Not removing \`$AMQ_USER' system account" \ "because deluser command was not found." fi fi } disable_user() { if getent passwd $AMQ_USER > /dev/null 2>&1; then usermod --shell /bin/false $AMQ_USER fi } if [ "$1" = "purge" ]; then # purge stats overrides # stats overrides could already be removed by root dpkg-statoverride --remove $AMQ_HOME || true # Unsure about this: # http://wiki.debian.org/AccountHandlingInMaintainerScripts del_user del_group # or just disable account ? # disable_user rm -rf $AMQ_HOME fi #DEBHELPER# debian/orig-tar.sh0000775000000000000000000000070513077354155011267 0ustar #!/bin/sh -e VERSION=$2 TAR=../activemq_$VERSION.orig.tar.gz DIR=activemq-$VERSION TAG=$(echo "activemq-$VERSION" | sed -re's/~(alpha|beta)/-\1-/') svn export https://svn.apache.org/repos/asf/activemq/tags/${TAG}/ $DIR GZIP=--best tar -c -z -f $TAR --exclude '*.jar' --exclude '*.class' $DIR rm -rf $DIR ../$TAG # move to directory 'tarballs' if [ -r .svn/deb-layout ]; then . .svn/deb-layout mv $TAR $origDir && echo "moved $TAR to $origDir" fi debian/activemq.postinst0000664000000000000000000000152313077354155012621 0ustar #!/bin/sh set -e AMQ_HOME=/var/lib/activemq AMQ_GROUP=activemq AMQ_USER=activemq create_group() { if ! getent group $AMQ_GROUP > /dev/null 2>&1; then addgroup --system $AMQ_GROUP fi } create_user() { if ! getent passwd $AMQ_USER > /dev/null 2>&1; then adduser --system --no-create-home --ingroup $AMQ_GROUP \ --home $AMQ_HOME --shell /bin/bash $AMQ_USER else AMQ_HOME=`getent passwd $AMQ_USER | cut -f6 -d:` # Renable user (give him a shell) usermod --shell /bin/bash $AMQ_USER fi } if [ "$1" = "configure" ]; then create_group create_user # Use dpkg-statoverride instead of direct chmod/chown if ! dpkg-statoverride --list $AMQ_HOME >/dev/null 2>&1; then dpkg-statoverride --update --add $AMQ_USER root 755 $AMQ_HOME fi fi #DEBHELPER# debian/copyright0000664000000000000000000000116113077354155011134 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Apache ActiveMQ Upstream-Contact: http://activemq.apache.org/developer-forum.html Source: https://svn.apache.org/repos/asf/activemq/trunk/ Files: * Copyright: 2005-2011, Apache Software Foundation License: Apache-2.0 Files: debian/* Copyright: Copyright 2011, Damien Raude-Morvan Copyright 2011, Jonas Genannt License: Apache-2.0 License: Apache-2.0 On Debian GNU/Linux system you can find the complete text of the Apache-2.0 license in '/usr/share/common-licenses/Apache-2.0' debian/TODO0000664000000000000000000000012413077354155007667 0ustar - Enable all module - Provide some startup script (in an activemq-server package ?) debian/watch0000664000000000000000000000026413077354155010235 0ustar version=3 opts="uversionmangle=s/-(alpha|beta)-/~$1/,dversionmangle=s/\+dfsg$//" \ https://svn.apache.org/repos/asf/activemq/tags/ \ activemq-(\d.*)/ debian debian/orig-tar.sh debian/source/0000775000000000000000000000000013077354155010502 5ustar debian/source/format0000664000000000000000000000001413077354155011710 0ustar 3.0 (quilt) debian/libactivemq-java-doc.install0000664000000000000000000000007313077354155014554 0ustar target/site/apidocs/* /usr/share/doc/libactivemq-java/api/ debian/rules0000775000000000000000000000101513077354155010257 0ustar #!/usr/bin/make -f include /usr/share/cdbs/1/rules/debhelper.mk include /usr/share/cdbs/1/class/maven.mk JAVA_HOME := /usr/lib/jvm/default-java DEB_MAVEN_DOC_TARGET := javadoc:aggregate DEB_MAVEN_BUILD_TARGET := install binary-post-install/activemq:: chmod 644 debian/activemq/etc/activemq/instances-available/main/log4j.properties chmod 644 debian/activemq/usr/share/doc/activemq/examples/conf/log4j.properties chmod 644 debian/activemq/usr/share/activemq/README.txt get-orig-source: uscan --force-download --rename debian/README.source0000664000000000000000000000226613077354155011367 0ustar Information about activemq ------------------------------ This package was debianized using the mh_make command from the maven-debian-helper package. The build system uses Maven but prevents it from downloading anything from the Internet, making the build compliant with the Debian policy. Cleanup for DFSG ---------------- Build upstream tarball from SVN tag : debian/rules get-orig-source Import upstream tarball without merging to debian (master) branch : git-import-orig --no-merge activemq_5.5.0.orig.tar.gz git tag upstream/5.5.0 Switch to dfsg_clean branch to do the real cleanup : git checkout dfsg_clean git pull . upstream git rm -r assembly/src/release/bin/linux-x86-32 git rm -r assembly/src/release/bin/linux-x86-64/ git rm -r assembly/src/release/bin/macosx/ git rm -r assembly/src/release/bin/solaris/ git rm -r assembly/src/release/bin/win32/ git commit -a -m "Make source dfsg clean" git tag upstream/5.5.0+dfsg git tar-tree upstream/5.5.0+dfsg activemq-5.5.0+dfsg | gzip > activemq_5.5.0+dfsg.orig.tar.gz pristine-tar commit activemq_5.5.0+dfsg.orig.tar.gz Merge back changes into debian (master) branch : git checkout master git pull . dfsg_clean debian/main.xml0000664000000000000000000000454513077354155010660 0ustar debian/libactivemq-java.README.Debian0000664000000000000000000000157113077354155014465 0ustar ActiveMQ for Debian =================== Disabled features ----------------- For now, libactivemq-java doesn't provide the same featureset as upstream "activemq" tarball, as some modules have been disabled in Debian package build. Here is a complete list of disabled modules : - activemq-camel: need Apache Camel library - activemq-blueprint: need XBean OSGi Blueprint library - activemq-karaf: need Apache Karaf Shell Console library - activemq-openwire-generator: need Groovy Gram and Annogen modules - activemq-optional: need Eclipse Jetty 7 - activemq-rar: need many Apache Geronimo JEE Server libs - activemq-tooling: need Apache Derby - activemq-web: need Eclipse Jetty 7 - activemq-web-demo: need activemq-web - activemq-web-console: need activemq-web - activemq-xmpp: need Smack XMPP library and maven-jaxb2-plugin - activemq-all: need everything else...