bug5032: using the JoinedClassloader in the DataMiningService for function de-serialization

This commit is contained in:
Axel Uhl
2019-12-12 16:04:07 +01:00
parent 21e249cef5
commit 53a4c77dc6
8 changed files with 50 additions and 56 deletions
@@ -21,7 +21,6 @@ import org.osgi.util.tracker.ServiceTracker;
import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sailing.server.interfaces.RacingEventService;
import com.sap.sse.common.settings.SerializableSettings; import com.sap.sse.common.settings.SerializableSettings;
import com.sap.sse.datamining.DataMiningServer; import com.sap.sse.datamining.DataMiningServer;
import com.sap.sse.datamining.ModifiableDataMiningServer;
import com.sap.sse.datamining.Query; import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.StatisticQueryDefinition; import com.sap.sse.datamining.StatisticQueryDefinition;
import com.sap.sse.datamining.components.AggregationProcessorDefinition; import com.sap.sse.datamining.components.AggregationProcessorDefinition;
@@ -33,7 +32,6 @@ import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.impl.components.DataRetrieverLevel; import com.sap.sse.datamining.impl.components.DataRetrieverLevel;
import com.sap.sse.datamining.impl.components.management.ReducedDimensions; import com.sap.sse.datamining.impl.components.management.ReducedDimensions;
import com.sap.sse.datamining.impl.data.QueryResultImpl; import com.sap.sse.datamining.impl.data.QueryResultImpl;
import com.sap.sse.datamining.shared.DataMiningQuerySerializer;
import com.sap.sse.datamining.shared.DataMiningSession; import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.GroupKey; import com.sap.sse.datamining.shared.GroupKey;
import com.sap.sse.datamining.shared.SerializationDummy; import com.sap.sse.datamining.shared.SerializationDummy;
@@ -59,19 +57,15 @@ public class DataMiningServiceImpl extends ProxiedRemoteServiceServlet implement
private static final long serialVersionUID = -7951930891674894528L; private static final long serialVersionUID = -7951930891674894528L;
private final BundleContext context; private final BundleContext context;
private final ServiceTracker<DataMiningServer, DataMiningServer> dataMiningServerTracker; private final ServiceTracker<DataMiningServer, DataMiningServer> dataMiningServerTracker;
private final ServiceTracker<SecurityService, SecurityService> securityServiceTracker; private final ServiceTracker<SecurityService, SecurityService> securityServiceTracker;
private final StoredDataMiningQueryPersister storedDataMiningQueryPersistor; private final StoredDataMiningQueryPersister storedDataMiningQueryPersistor;
private final DataMiningDTOFactory dtoFactory; private final DataMiningDTOFactory dtoFactory;
public DataMiningServiceImpl() { public DataMiningServiceImpl() {
context = Activator.getDefault(); context = Activator.getDefault();
dataMiningServerTracker = createAndOpenDataMiningServerTracker(context); dataMiningServerTracker = createAndOpenDataMiningServerTracker(context);
securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class); securityServiceTracker = ServiceTrackerFactory.createAndOpen(context, SecurityService.class);
storedDataMiningQueryPersistor = new StoredDataMiningQueryPersisterImpl(getSecurityService(), storedDataMiningQueryPersistor = new StoredDataMiningQueryPersisterImpl(getSecurityService(),
dataMiningServerTracker); dataMiningServerTracker);
dtoFactory = new DataMiningDTOFactory(); dtoFactory = new DataMiningDTOFactory();
@@ -439,7 +433,6 @@ public class DataMiningServiceImpl extends ProxiedRemoteServiceServlet implement
@Override @Override
public ModifiableStatisticQueryDefinitionDTO getDeserializedQuery(String serializedQuery) { public ModifiableStatisticQueryDefinitionDTO getDeserializedQuery(String serializedQuery) {
return (ModifiableStatisticQueryDefinitionDTO) DataMiningQuerySerializer.fromBase64String(serializedQuery, return (ModifiableStatisticQueryDefinitionDTO) dataMiningServerTracker.getService().fromBase64String(serializedQuery);
((ModifiableDataMiningServer) dataMiningServerTracker.getService()).getJoinedClassLoader());
} }
} }
@@ -13,7 +13,6 @@ import com.sap.sailing.server.impl.preferences.model.StoredDataMiningQueryPrefer
import com.sap.sailing.server.impl.preferences.model.StoredDataMiningQueryPreferences; import com.sap.sailing.server.impl.preferences.model.StoredDataMiningQueryPreferences;
import com.sap.sse.common.Util; import com.sap.sse.common.Util;
import com.sap.sse.datamining.DataMiningServer; import com.sap.sse.datamining.DataMiningServer;
import com.sap.sse.datamining.ModifiableDataMiningServer;
import com.sap.sse.datamining.shared.DataMiningQuerySerializer; import com.sap.sse.datamining.shared.DataMiningQuerySerializer;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO; import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.dto.StoredDataMiningQueryDTO; import com.sap.sse.datamining.shared.dto.StoredDataMiningQueryDTO;
@@ -114,8 +113,7 @@ public class StoredDataMiningQueryPersisterImpl implements StoredDataMiningQuery
/** Converts a {@link StoredDataMiningQueryPreference} to a {@link StoredDataMiningQueryDTO}. */ /** Converts a {@link StoredDataMiningQueryPreference} to a {@link StoredDataMiningQueryDTO}. */
private StoredDataMiningQueryDTO transform(StoredDataMiningQueryPreference pref) { private StoredDataMiningQueryDTO transform(StoredDataMiningQueryPreference pref) {
StatisticQueryDefinitionDTO query = DataMiningQuerySerializer.fromBase64String(pref.getSerializedQuery(), StatisticQueryDefinitionDTO query = dataMiningServerTracker.getService().fromBase64String(pref.getSerializedQuery());
((ModifiableDataMiningServer) dataMiningServerTracker.getService()).getJoinedClassLoader());
return new StoredDataMiningQueryDTOImpl(pref.getName(), pref.getId(), query); return new StoredDataMiningQueryDTOImpl(pref.getName(), pref.getId(), query);
} }
@@ -13,5 +13,6 @@ Export-Package: com.sap.sse.datamining.shared,
com.sap.sse.datamining.shared.util com.sap.sse.datamining.shared.util
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Require-Bundle: com.sap.sse.datamining.annotations, Require-Bundle: com.sap.sse.datamining.annotations,
com.sap.sse.common com.sap.sse.common,
com.sap.sse.shared.android
Automatic-Module-Name: com.sap.sse.datamining.shared Automatic-Module-Name: com.sap.sse.datamining.shared
@@ -1,11 +1,8 @@
package com.sap.sse.datamining.shared; package com.sap.sse.datamining.shared;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.sap.sse.common.Base64Utils; import com.sap.sse.common.Base64Utils;
@@ -30,37 +27,4 @@ public final class DataMiningQuerySerializer {
} }
return ""; return "";
} }
/** @return the {@link StatisticQueryDefinitionDTO} from a base 64 string deserialized with java serialization */
public static StatisticQueryDefinitionDTO fromBase64String(final String string, ClassLoader joinedClassLoader) {
byte[] bytes;
try {
bytes = Base64Utils.fromBase64(string);
} catch (IllegalArgumentException e) {
return null;
}
try (ByteArrayInputStream stream = new ByteArrayInputStream(bytes)) {
ObjectInputStream in = new ObjectInputStream(stream) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (joinedClassLoader != null) {
try {
return joinedClassLoader.loadClass(desc.getName());
} catch (ClassNotFoundException e) {
return super.resolveClass(desc);
}
}
return super.resolveClass(desc);
}
};
Object o = in.readObject();
if (o instanceof StatisticQueryDefinitionDTO) {
return (StatisticQueryDefinitionDTO) o;
}
} catch (IOException | ClassNotFoundException e) {
LOG.severe("Could not load query: " + e.getMessage());
}
return null;
}
} }
@@ -4,17 +4,15 @@ import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import com.sap.sailing.datamining.SailingPredefinedQueries; import com.sap.sailing.datamining.SailingPredefinedQueries;
import com.sap.sse.datamining.impl.DataMiningServerImpl;
import com.sap.sse.datamining.shared.DataMiningQuerySerializer; import com.sap.sse.datamining.shared.DataMiningQuerySerializer;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO; import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
public class DataMiningQuerySerializerTest { public class DataMiningQuerySerializerTest {
@Test @Test
public void testSerializationAndDeserialization() { public void testSerializationAndDeserialization() {
// test null // test null
testSerializationAndDeserialization(null); testSerializationAndDeserialization(null);
// test all predefined queries // test all predefined queries
for (StatisticQueryDefinitionDTO query : new SailingPredefinedQueries().getQueries().values()) { for (StatisticQueryDefinitionDTO query : new SailingPredefinedQueries().getQueries().values()) {
testSerializationAndDeserialization(query); testSerializationAndDeserialization(query);
@@ -23,7 +21,10 @@ public class DataMiningQuerySerializerTest {
private void testSerializationAndDeserialization(final StatisticQueryDefinitionDTO dto) { private void testSerializationAndDeserialization(final StatisticQueryDefinitionDTO dto) {
String base64 = DataMiningQuerySerializer.toBase64String(dto); String base64 = DataMiningQuerySerializer.toBase64String(dto);
StatisticQueryDefinitionDTO deserialized = DataMiningQuerySerializer.fromBase64String(base64, null); StatisticQueryDefinitionDTO deserialized = new DataMiningServerImpl(
/* executorService */ null, /* functionRegistry */ null, /* dataSourceProviderRegistry */ null,
/* dataRetrieverChainDefinitionRegistry */ null, /* aggregationProcessorDefinitionRegistry */ null,
/* queryDefinitionRegistry */ null).fromBase64String(base64);
Assert.assertEquals(dto, deserialized); Assert.assertEquals(dto, deserialized);
} }
} }
@@ -26,6 +26,7 @@ import com.sap.sse.datamining.shared.impl.dto.DataRetrieverChainDefinitionDTO;
import com.sap.sse.datamining.shared.impl.dto.FunctionDTO; import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.datamining.shared.impl.dto.ModifiableStatisticQueryDefinitionDTO; import com.sap.sse.datamining.shared.impl.dto.ModifiableStatisticQueryDefinitionDTO;
import com.sap.sse.i18n.ResourceBundleStringMessages; import com.sap.sse.i18n.ResourceBundleStringMessages;
import com.sap.sse.util.JoinedClassLoader;
public interface DataMiningServer { public interface DataMiningServer {
@@ -52,6 +53,8 @@ public interface DataMiningServer {
<DataSourceType, ResultType> Query<ResultType> createQuery(StatisticQueryDefinition<DataSourceType, ?, ?, ResultType> queryDefinition); <DataSourceType, ResultType> Query<ResultType> createQuery(StatisticQueryDefinition<DataSourceType, ?, ?, ResultType> queryDefinition);
<ResultType> QueryResult<ResultType> runNewQueryAndAbortPreviousQueries(DataMiningSession session, Query<ResultType> query); <ResultType> QueryResult<ResultType> runNewQueryAndAbortPreviousQueries(DataMiningSession session, Query<ResultType> query);
int getNumberOfRunningQueries(); int getNumberOfRunningQueries();
JoinedClassLoader getJoinedClassLoader();
StatisticQueryDefinitionDTO fromBase64String(String string);
//----------------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------------
// Component Accessors as default methods // Component Accessors as default methods
@@ -128,5 +131,4 @@ public interface DataMiningServer {
default ModifiableStatisticQueryDefinitionDTO getPredefinedQueryDefinitionDTO(PredefinedQueryIdentifier identifier) { default ModifiableStatisticQueryDefinitionDTO getPredefinedQueryDefinitionDTO(PredefinedQueryIdentifier identifier) {
return getQueryDefinitionDTOProvider().get(identifier); return getQueryDefinitionDTOProvider().get(identifier);
} }
} }
@@ -9,13 +9,11 @@ import com.sap.sse.datamining.components.management.QueryDefinitionDTORegistry;
import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO; import com.sap.sse.datamining.shared.dto.StatisticQueryDefinitionDTO;
import com.sap.sse.datamining.shared.impl.PredefinedQueryIdentifier; import com.sap.sse.datamining.shared.impl.PredefinedQueryIdentifier;
import com.sap.sse.i18n.ResourceBundleStringMessages; import com.sap.sse.i18n.ResourceBundleStringMessages;
import com.sap.sse.util.JoinedClassLoader;
public interface ModifiableDataMiningServer extends DataMiningServer { public interface ModifiableDataMiningServer extends DataMiningServer {
void addDataMiningBundleClassLoader(ClassLoader classLoader); void addDataMiningBundleClassLoader(ClassLoader classLoader);
void removeDataMiningBundleClassLoader(ClassLoader classLoader); void removeDataMiningBundleClassLoader(ClassLoader classLoader);
JoinedClassLoader getJoinedClassLoader();
void addStringMessages(ResourceBundleStringMessages stringMessages); void addStringMessages(ResourceBundleStringMessages stringMessages);
void removeStringMessages(ResourceBundleStringMessages stringMessages); void removeStringMessages(ResourceBundleStringMessages stringMessages);
@@ -1,5 +1,8 @@
package com.sap.sse.datamining.impl; package com.sap.sse.datamining.impl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -12,7 +15,10 @@ import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sap.sse.common.Base64Utils;
import com.sap.sse.common.settings.SerializableSettings; import com.sap.sse.common.settings.SerializableSettings;
import com.sap.sse.datamining.DataSourceProvider; import com.sap.sse.datamining.DataSourceProvider;
import com.sap.sse.datamining.ModifiableDataMiningServer; import com.sap.sse.datamining.ModifiableDataMiningServer;
@@ -50,8 +56,10 @@ import com.sap.sse.datamining.shared.impl.dto.FunctionDTO;
import com.sap.sse.i18n.ResourceBundleStringMessages; import com.sap.sse.i18n.ResourceBundleStringMessages;
import com.sap.sse.i18n.impl.CompoundResourceBundleStringMessages; import com.sap.sse.i18n.impl.CompoundResourceBundleStringMessages;
import com.sap.sse.util.JoinedClassLoader; import com.sap.sse.util.JoinedClassLoader;
import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache;
public class DataMiningServerImpl implements ModifiableDataMiningServer { public class DataMiningServerImpl implements ModifiableDataMiningServer {
private static final Logger logger = Logger.getLogger(DataMiningServerImpl.class.getName());
private static final long MEMORY_CHECK_PERIOD = 5; private static final long MEMORY_CHECK_PERIOD = 5;
private static final TimeUnit MEMORY_CHECK_PERIOD_UNIT = TimeUnit.SECONDS; private static final TimeUnit MEMORY_CHECK_PERIOD_UNIT = TimeUnit.SECONDS;
@@ -90,7 +98,6 @@ public class DataMiningServerImpl implements ModifiableDataMiningServer {
this.dataSourceProviderRegistry = dataSourceProviderRegistry; this.dataSourceProviderRegistry = dataSourceProviderRegistry;
this.dataRetrieverChainDefinitionRegistry = dataRetrieverChainDefinitionRegistry; this.dataRetrieverChainDefinitionRegistry = dataRetrieverChainDefinitionRegistry;
this.aggregationProcessorDefinitionRegistry = aggregationProcessorDefinitionRegistry; this.aggregationProcessorDefinitionRegistry = aggregationProcessorDefinitionRegistry;
this.queryDefinitionRegistry = queryDefinitionRegistry; this.queryDefinitionRegistry = queryDefinitionRegistry;
} }
@@ -143,6 +150,36 @@ public class DataMiningServerImpl implements ModifiableDataMiningServer {
return new JoinedClassLoader(dataMiningClassLoaders); return new JoinedClassLoader(dataMiningClassLoaders);
} }
/**
* @return the {@link StatisticQueryDefinitionDTO} from a base 64 string deserialized with java serialization,
* considering the {@link #getJoinedClassLoader() joined class loader} that offers all classes of all
* bundles that currently provide data mining components to this server
*/
@Override
public StatisticQueryDefinitionDTO fromBase64String(final String string) {
byte[] bytes;
try {
bytes = Base64Utils.fromBase64(string);
} catch (IllegalArgumentException e) {
return null;
}
final ClassLoader oldThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getJoinedClassLoader());
try (final ObjectInputStream in = new ObjectInputStreamResolvingAgainstCache<Object>(
new ByteArrayInputStream(bytes), /* dummy "cache" */ new Object(), /* resolve listener */ null) {}) {
Object o = in.readObject();
if (o instanceof StatisticQueryDefinitionDTO) {
return (StatisticQueryDefinitionDTO) o;
}
} catch (IOException | ClassNotFoundException e) {
logger.log(Level.SEVERE, "Could not load query", e);
} finally {
Thread.currentThread().setContextClassLoader(oldThreadContextClassLoader);
}
return null;
}
@Override @Override
public void addDataMiningBundleClassLoader(ClassLoader classLoader) { public void addDataMiningBundleClassLoader(ClassLoader classLoader) {
dataMiningClassLoaders.add(classLoader); dataMiningClassLoaders.add(classLoader);