Author: cziegeler Date: Fri Sep 25 15:58:10 2009 New Revision: 818893 URL: http://svn.apache.org/viewvc?rev=818893&view=rev Log: SLING-1125 : Deprecate internal methods
Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventUtil.java sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/TimedJobHandler.java Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventUtil.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventUtil.java?rev=818893&r1=818892&r2=818893&view=diff ============================================================================== --- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventUtil.java (original) +++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/EventUtil.java Fri Sep 25 15:58:10 2009 @@ -336,7 +336,9 @@ * @param ignoreProps optional list of property which should be ignored * @param binPropertyName The name of the binary property. * @throws RepositoryException + * @deprecated */ + @Deprecated public static void addProperties(final Node node, final Map<String, Object> properties, final String[] ignoreProps, @@ -356,7 +358,9 @@ * @param ignoreProps optional list of property which should be ignored * @param binPropertyName The name of the binary property. * @throws RepositoryException + * @deprecated */ + @Deprecated public static void addProperties(final Node node, final EventPropertiesMap properties, final String[] ignoreProps, @@ -410,34 +414,20 @@ * loader is used to load these objects. * @throws RepositoryException * @throws ClassNotFoundException + * @deprecated */ + @Deprecated public static EventPropertiesMap readProperties(final Node node, final String binPropertyName, final String[] ignorePrefixes) throws RepositoryException, ClassNotFoundException { - return readProperties(node, binPropertyName, ignorePrefixes, Thread.currentThread().getContextClassLoader()); - } - - /** - * Read properties from a repository node and create a property map. - * As the properties might contain serialized java objects, a class loader can be specified - * for loading classes of the serialized java objects. - * @throws RepositoryException - * @throws ClassNotFoundException - * @since 2.0.6 - */ - public static EventPropertiesMap readProperties(final Node node, - final String binPropertyName, - final String[] ignorePrefixes, - final ClassLoader objectClassLoader) - throws RepositoryException, ClassNotFoundException { final Map<String, Object> properties = new HashMap<String, Object>(); // check the properties blob if ( node.hasProperty(binPropertyName) ) { try { final ObjectInputStream ois = new ObjectInputStream(node.getProperty(binPropertyName).getStream(), - objectClassLoader); + Thread.currentThread().getContextClassLoader()); int length = ois.readInt(); for(int i=0;i<length;i++) { final String key = (String)ois.readObject(); @@ -503,7 +493,9 @@ * Return the converted repository property name * @param name The java object property name * @return The converted name or null if not possible. + * @deprecated */ + @Deprecated public static String getNodePropertyName(final String name) { // if name contains a colon, we can't set it as a property if ( name.indexOf(':') != -1 ) { @@ -517,7 +509,9 @@ * @param valueFactory The value factory * @param eventValue The event value * @return The converted value or null if not possible + * @deprecated */ + @Deprecated public static Value getNodePropertyValue(final ValueFactory valueFactory, final Object eventValue) { final Value val; if (eventValue instanceof Calendar) { @@ -541,7 +535,9 @@ * @param value * @return * @throws RepositoryException + * @deprecated */ + @Deprecated private static Object getPropertyValue(final Value value) throws RepositoryException { final Object o; @@ -569,7 +565,9 @@ * @param node * @return * @throws RepositoryException + * @deprecated */ + @Deprecated private static boolean setProperty(String name, Object value, Node node) throws RepositoryException { final String propName = getNodePropertyName(name); Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java?rev=818893&r1=818892&r2=818893&view=diff ============================================================================== --- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java (original) +++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java Fri Sep 25 15:58:10 2009 @@ -32,8 +32,6 @@ import org.apache.sling.commons.classloader.DynamicClassLoaderManager; import org.apache.sling.commons.osgi.OsgiUtil; import org.apache.sling.engine.SlingSettingsService; -import org.apache.sling.event.EventPropertiesMap; -import org.apache.sling.event.EventUtil; import org.apache.sling.event.JobStatusProvider; import org.apache.sling.event.ThreadPool; import org.apache.sling.jcr.api.SlingRepository; @@ -101,19 +99,6 @@ public static String APPLICATION_ID; - /** List of ignored properties to write to the repository. */ - private static final String[] IGNORE_PROPERTIES = new String[] { - EventUtil.PROPERTY_DISTRIBUTE, - EventUtil.PROPERTY_APPLICATION, - JobStatusProvider.PROPERTY_EVENT_ID, - EventUtil.JobStatusNotifier.CONTEXT_PROPERTY_NAME - }; - - /** List of ignored prefixes to read from the repository. */ - private static final String[] IGNORE_PREFIXES = new String[] { - EventHelper.EVENT_PREFIX - }; - /** * Activate this component. * @param context @@ -273,10 +258,7 @@ eventNode.setProperty(EventHelper.NODE_PROPERTY_TOPIC, e.getTopic()); eventNode.setProperty(EventHelper.NODE_PROPERTY_APPLICATION, this.applicationId); - EventUtil.addProperties(eventNode, - new EventPropertiesMap(e), - IGNORE_PROPERTIES, - EventHelper.NODE_PROPERTY_PROPERTIES); + EventHelper.writeEventProperties(eventNode, e); this.addNodeProperties(eventNode, e); rootNode.save(); @@ -292,26 +274,19 @@ */ protected Event readEvent(Node eventNode) throws RepositoryException, ClassNotFoundException { - final ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(this.classLoaderManager.getDynamicClassLoader()); - final String topic = eventNode.getProperty(EventHelper.NODE_PROPERTY_TOPIC).getString(); - final EventPropertiesMap eventProps = EventUtil.readProperties(eventNode, - EventHelper.NODE_PROPERTY_PROPERTIES, - IGNORE_PREFIXES); + final String topic = eventNode.getProperty(EventHelper.NODE_PROPERTY_TOPIC).getString(); + final Dictionary<String, Object> eventProps = EventHelper.readEventProperties(eventNode, + this.classLoaderManager.getDynamicClassLoader()); - eventProps.put(JobStatusProvider.PROPERTY_EVENT_ID, eventNode.getPath()); - this.addEventProperties(eventNode, eventProps); - try { - final Event event = new Event(topic, (Dictionary)eventProps); - return event; - } catch (IllegalArgumentException iae) { - // this exception occurs if the topic is not correct (it should never happen, - // but you never know) - throw new RepositoryException("Unable to read event: " + iae.getMessage(), iae); - } - } finally { - Thread.currentThread().setContextClassLoader(oldCL); + eventProps.put(JobStatusProvider.PROPERTY_EVENT_ID, eventNode.getPath()); + this.addEventProperties(eventNode, eventProps); + try { + final Event event = new Event(topic, eventProps); + return event; + } catch (IllegalArgumentException iae) { + // this exception occurs if the topic is not correct (it should never happen, + // but you never know) + throw new RepositoryException("Unable to read event: " + iae.getMessage(), iae); } } Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java?rev=818893&r1=818892&r2=818893&view=diff ============================================================================== --- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java (original) +++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java Fri Sep 25 15:58:10 2009 @@ -18,9 +18,32 @@ */ package org.apache.sling.event.impl; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectOutputStream; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFactory; + +import org.apache.jackrabbit.util.ISO9075; +import org.apache.sling.event.EventUtil; +import org.apache.sling.event.JobStatusProvider; +import org.osgi.service.event.Event; /** @@ -60,6 +83,19 @@ /** Replacement characters for unallowed characters in a node name */ private static final char REPLACEMENT_CHAR = '_'; + /** List of ignored properties to write to the repository. */ + private static final String[] IGNORE_PROPERTIES = new String[] { + EventUtil.PROPERTY_DISTRIBUTE, + EventUtil.PROPERTY_APPLICATION, + JobStatusProvider.PROPERTY_EVENT_ID, + EventUtil.JobStatusNotifier.CONTEXT_PROPERTY_NAME + }; + + /** List of ignored prefixes to read from the repository. */ + private static final String[] IGNORE_PREFIXES = new String[] { + EventHelper.EVENT_PREFIX + }; + /** * Filter the node name for not allowed characters and replace them. * @param nodeName The suggested node name. @@ -138,4 +174,281 @@ } return res.toString(); } + + /** + * Check if this property should be ignored + */ + private static boolean ignoreProperty(final String name) { + for(final String prop : IGNORE_PROPERTIES) { + if ( prop.equals(name) ) { + return true; + } + } + return false; + } + + /** + * Add all java properties as properties to the node. + * If the name and the value of a map entry can easily converted into + * a repository property, it is directly added. All other java + * properties are stored in one binary property. + * + * @param node The node where all properties are added to + * @param event The event. + * @throws RepositoryException + */ + public static void writeEventProperties(final Node node, + final Event event) + throws RepositoryException { + if ( event != null ) { + final String[] propNames = event.getPropertyNames(); + if ( propNames != null && propNames.length > 0 ) { + // check which props we can write directly and + // which we need to write as a binary blob + final List<String> propsAsBlob = new ArrayList<String>(); + + for(final String name : propNames) { + + if ( !ignoreProperty(name) ) { + // sanity check + final Object value = event.getProperty(name); + if ( value != null ) { + if ( !setProperty(name, value, node) ) { + propsAsBlob.add(name); + } + } + } + } + // write the remaining properties as a blob + if ( propsAsBlob.size() > 0 ) { + try { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeInt(propsAsBlob.size()); + for(final String propName : propsAsBlob) { + oos.writeObject(propName); + try { + oos.writeObject(event.getProperty(propName)); + } catch (IOException ioe) { + throw new RepositoryException("Unable to serialize property " + propName, ioe); + } + } + oos.close(); + node.setProperty(EventHelper.NODE_PROPERTY_PROPERTIES, new ByteArrayInputStream(baos.toByteArray())); + } catch (IOException ioe) { + throw new RepositoryException("Unable to serialize event " + EventUtil.toString(event), ioe); + } + } + } + } + } + + /** + * Read event properties from a repository node and create a property map (dictionary). + * As the properties might contain serialized java objects, a class loader can be specified + * for loading classes of the serialized java objects. + * @throws RepositoryException + * @throws ClassNotFoundException + */ + public static Dictionary<String, Object> readEventProperties(final Node node, + final ClassLoader objectClassLoader) + throws RepositoryException, ClassNotFoundException { + final Dictionary<String, Object> properties = new Hashtable<String, Object>(); + + // check the properties blob + if ( node.hasProperty(EventHelper.NODE_PROPERTY_PROPERTIES) ) { + try { + final ObjectInputStream ois = new ObjectInputStream(node.getProperty(EventHelper.NODE_PROPERTY_PROPERTIES).getStream(), + objectClassLoader); + int length = ois.readInt(); + for(int i=0;i<length;i++) { + final String key = (String)ois.readObject(); + final Object value = ois.readObject(); + properties.put(key, value); + } + } catch (java.io.InvalidClassException ice) { + throw new ClassNotFoundException("Found invalid class.", ice); + } catch (IOException ioe) { + throw new RepositoryException("Unable to deserialize event properties.", ioe); + } + } + // now all properties that have been set directly + final PropertyIterator pI = node.getProperties(); + while ( pI.hasNext() ) { + final Property p = pI.nextProperty(); + boolean ignore = p.getName().startsWith("jcr:"); + if ( !ignore) { + int index = 0; + while ( !ignore && index < IGNORE_PREFIXES.length ) { + ignore = p.getName().startsWith(IGNORE_PREFIXES[index]); + index++; + } + } + if ( !ignore ) { + final String name = ISO9075.decode(p.getName()); + if ( p.getDefinition().isMultiple() ) { + final Value[] values = p.getValues(); + if ( values.length > 0 ) { + // get first value + final Object firstObject = getPropertyValue(values[0]); + final Object[] array; + if ( firstObject instanceof Boolean ) { + array = new Boolean[values.length]; + } else if ( firstObject instanceof Calendar ) { + array = new Calendar[values.length]; + } else if ( firstObject instanceof Double ) { + array = new Double[values.length]; + } else if ( firstObject instanceof Long ) { + array = new Long[values.length]; + } else { + array = new String[values.length]; + } + array[0] = firstObject; + int index = 1; + while ( index < values.length ) { + array[index] = getPropertyValue(values[index]); + index++; + } + properties.put(name, array); + } + } else { + final Value value = p.getValue(); + final Object o = getPropertyValue(value); + properties.put(name, o); + } + } + } + return properties; + } + + /** + * Return the converted repository property name + * @param name The java object property name + * @return The converted name or null if not possible. + */ + public static String getNodePropertyName(final String name) { + // if name contains a colon, we can't set it as a property + if ( name.indexOf(':') != -1 ) { + return null; + } + return ISO9075.encode(name); + } + + /** + * Return the converted repository property value + * @param valueFactory The value factory + * @param eventValue The event value + * @return The converted value or null if not possible + */ + public static Value getNodePropertyValue(final ValueFactory valueFactory, final Object eventValue) { + final Value val; + if (eventValue instanceof Calendar) { + val = valueFactory.createValue((Calendar)eventValue); + } else if (eventValue instanceof Long) { + val = valueFactory.createValue((Long)eventValue); + } else if (eventValue instanceof Double) { + val = valueFactory.createValue(((Double)eventValue).doubleValue()); + } else if (eventValue instanceof Boolean) { + val = valueFactory.createValue((Boolean) eventValue); + } else if (eventValue instanceof String) { + val = valueFactory.createValue((String)eventValue); + } else { + val = null; + } + return val; + } + + /** + * Convert the value back to an object. + * @param value + * @return + * @throws RepositoryException + */ + private static Object getPropertyValue(final Value value) + throws RepositoryException { + final Object o; + switch (value.getType()) { + case PropertyType.BOOLEAN: + o = value.getBoolean(); break; + case PropertyType.DATE: + o = value.getDate(); break; + case PropertyType.DOUBLE: + o = value.getDouble(); break; + case PropertyType.LONG: + o = value.getLong(); break; + case PropertyType.STRING: + o = value.getString(); break; + default: // this should never happen - we convert to a string... + o = value.getString(); + } + return o; + } + + /** + * Try to set the java property as a property of the node. + * @param name + * @param value + * @param node + * @return + * @throws RepositoryException + */ + private static boolean setProperty(String name, Object value, Node node) + throws RepositoryException { + final String propName = getNodePropertyName(name); + if ( propName == null ) { + return false; + } + final ValueFactory fac = node.getSession().getValueFactory(); + // check for multi value + if ( value.getClass().isArray() ) { + final Object[] array = (Object[])value; + // now we try to convert each value + // and check if all converted values have the same type + final Value[] values = new Value[array.length]; + int index = 0; + for(final Object v : array ) { + values[index] = getNodePropertyValue(fac, v); + if ( values[index] == null ) { + return false; + } + if ( index > 0 && !values[index-1].getClass().equals(values[index].getClass()) ) { + return false; + } + index++; + } + node.setProperty(propName, values); + return true; + } + final Value val = getNodePropertyValue(fac, value); + if ( val != null ) { + node.setProperty(propName, val); + return true; + } + return false; + } + + /** + * This is an extended version of the object input stream which uses the + * thread context class loader. + */ + private static class ObjectInputStream extends java.io.ObjectInputStream { + + private ClassLoader classloader; + + public ObjectInputStream(final InputStream in, final ClassLoader classLoader) throws IOException { + super(in); + this.classloader = classLoader; + } + + /** + * @see java.io.ObjectInputStream#resolveClass(java.io.ObjectStreamClass) + */ + @Override + protected Class<?> resolveClass(java.io.ObjectStreamClass classDesc) throws IOException, ClassNotFoundException { + if ( this.classloader != null ) { + return Class.forName(classDesc.getName(), true, this.classloader); + } + return super.resolveClass(classDesc); + } + } } Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java?rev=818893&r1=818892&r2=818893&view=diff ============================================================================== --- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java (original) +++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java Fri Sep 25 15:58:10 2009 @@ -1365,10 +1365,10 @@ while ( i.hasNext() ) { final Map.Entry<String, Object> current = i.next(); // check prop name first - final String propName = EventUtil.getNodePropertyName(current.getKey()); + final String propName = EventHelper.getNodePropertyName(current.getKey()); if ( propName != null ) { // check value - final Value value = EventUtil.getNodePropertyValue(s.getValueFactory(), current.getValue()); + final Value value = EventHelper.getNodePropertyValue(s.getValueFactory(), current.getValue()); if ( value != null ) { if ( first ) { first = false; Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/TimedJobHandler.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/TimedJobHandler.java?rev=818893&r1=818892&r2=818893&view=diff ============================================================================== --- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/TimedJobHandler.java (original) +++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/TimedJobHandler.java Fri Sep 25 15:58:10 2009 @@ -693,10 +693,10 @@ while ( i.hasNext() ) { final Map.Entry<String, Object> current = i.next(); // check prop name first - final String propName = EventUtil.getNodePropertyName(current.getKey()); + final String propName = EventHelper.getNodePropertyName(current.getKey()); if ( propName != null ) { // check value - final Value value = EventUtil.getNodePropertyValue(s.getValueFactory(), current.getValue()); + final Value value = EventHelper.getNodePropertyValue(s.getValueFactory(), current.getValue()); if ( value != null ) { if ( first ) { first = false;