Repository: servicemix-bundles Updated Branches: refs/heads/master f693c9f95 -> a67ba0b1e
SM-2876 - Create OSGi bundles for avro 1.8.0 Project: http://git-wip-us.apache.org/repos/asf/servicemix-bundles/repo Commit: http://git-wip-us.apache.org/repos/asf/servicemix-bundles/commit/a67ba0b1 Tree: http://git-wip-us.apache.org/repos/asf/servicemix-bundles/tree/a67ba0b1 Diff: http://git-wip-us.apache.org/repos/asf/servicemix-bundles/diff/a67ba0b1 Branch: refs/heads/master Commit: a67ba0b1ec0b386e8b709af14ba88e348f70ce1f Parents: f693c9f Author: Jean-Baptiste Onofré <[email protected]> Authored: Mon Feb 15 15:20:31 2016 +0100 Committer: Jean-Baptiste Onofré <[email protected]> Committed: Mon Feb 15 15:20:31 2016 +0100 ---------------------------------------------------------------------- avro-1.8.0/pom.xml | 120 +++++ .../org/apache/avro/reflect/ReflectData.java | 475 +++++++++++++++++++ .../org/apache/avro/specific/SpecificData.java | 272 +++++++++++ .../org/apache/avro/util/ClassLoadingUtils.java | 105 ++++ .../src/main/resources/OSGI-INF/bundle.info | 11 + avro-ipc-1.8.0/pom.xml | 115 +++++ .../src/main/resources/OSGI-INF/bundle.info | 11 + pom.xml | 2 + 8 files changed, 1111 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/servicemix-bundles/blob/a67ba0b1/avro-1.8.0/pom.xml ---------------------------------------------------------------------- diff --git a/avro-1.8.0/pom.xml b/avro-1.8.0/pom.xml new file mode 100644 index 0000000..10689fa --- /dev/null +++ b/avro-1.8.0/pom.xml @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <!-- + + 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. + --> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.servicemix.bundles</groupId> + <artifactId>bundles-pom</artifactId> + <version>12</version> + <relativePath>../bundles-pom/pom.xml</relativePath> + </parent> + + <groupId>org.apache.servicemix.bundles</groupId> + <artifactId>org.apache.servicemix.bundles.avro</artifactId> + <version>1.8.0_1-SNAPSHOT</version> + <packaging>bundle</packaging> + <name>Apache ServiceMix :: Bundles :: ${pkgArtifactId}</name> + <description>This OSGi bundle wraps ${pkgArtifactId} ${pkgVersion} jar file.</description> + + <scm> + <connection>scm:git:https://git-wip-us.apache.org/repos/asf/servicemix-bundles.git</connection> + <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/servicemix-bundles.git</developerConnection> + <url>https://git-wip-us.apache.org/repos/asf?p=servicemix-bundles.git</url> + <tag>HEAD</tag> + </scm> + + <properties> + <pkgGroupId>org.apache.avro</pkgGroupId> + <pkgArtifactId>avro</pkgArtifactId> + <pkgVersion>1.8.0</pkgVersion> + <servicemix.osgi.export> + !org.apache.avro.ipc;version="${project.version}", + org.apache.avro*;version="${project.version}";-noimport:=true;-split-package:=merge-first + </servicemix.osgi.export> + <servicemix.osgi.import.pkg> + javax.annotation, + com.thoughtworks.paranamer;version="[2.3,3)", + org.apache.commons.compress*, + org.codehaus.jackson*;version="[1.8,2)", + org.slf4j;resolution:=optional, + org.joda.time;resolution:=optional, + org.xerial.snappy;version="[1.0,2)";resolution:=optional, + sun.misc;resolution:=optional + </servicemix.osgi.import.pkg> + <servicemix.osgi.private.pkg> + avro.shaded* + </servicemix.osgi.private.pkg> + </properties> + + <dependencies> + <dependency> + <groupId>${pkgGroupId}</groupId> + <artifactId>${pkgArtifactId}</artifactId> + <version>${pkgVersion}</version> + <optional>false</optional> + </dependency> + + <!-- sources --> + <dependency> + <groupId>${pkgGroupId}</groupId> + <artifactId>${pkgArtifactId}</artifactId> + <version>${pkgVersion}</version> + <classifier>sources</classifier> + <optional>false</optional> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>1.4</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <artifactSet> + <includes> + <include>${pkgGroupId}:${pkgArtifactId}</include> + </includes> + </artifactSet> + <filters> + <filter> + <artifact>${pkgGroupId}:${pkgArtifactId}</artifact> + <excludes> + <exclude>**</exclude> + </excludes> + </filter> + </filters> + <promoteTransitiveDependencies>true</promoteTransitiveDependencies> + <createDependencyReducedPom>true</createDependencyReducedPom> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/servicemix-bundles/blob/a67ba0b1/avro-1.8.0/src/main/java/org/apache/avro/reflect/ReflectData.java ---------------------------------------------------------------------- diff --git a/avro-1.8.0/src/main/java/org/apache/avro/reflect/ReflectData.java b/avro-1.8.0/src/main/java/org/apache/avro/reflect/ReflectData.java new file mode 100644 index 0000000..e182064 --- /dev/null +++ b/avro-1.8.0/src/main/java/org/apache/avro/reflect/ReflectData.java @@ -0,0 +1,475 @@ +/** + * 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.avro.reflect; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.GenericArrayType; +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.ConcurrentHashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.avro.AvroRemoteException; +import org.apache.avro.AvroRuntimeException; +import org.apache.avro.AvroTypeException; +import org.apache.avro.Protocol; +import org.apache.avro.Schema; +import org.apache.avro.Protocol.Message; +import org.apache.avro.generic.IndexedRecord; +import org.apache.avro.generic.GenericFixed; +import org.apache.avro.generic.GenericContainer; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.specific.FixedSize; +import org.apache.avro.io.BinaryData; +import org.apache.avro.util.ClassLoadingUtils; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.NullNode; + +import com.thoughtworks.paranamer.CachingParanamer; +import com.thoughtworks.paranamer.Paranamer; + +/** Utilities to use existing Java classes and interfaces via reflection. */ +public class ReflectData extends SpecificData { + + /** {@link org.apache.avro.reflect.ReflectData} implementation that permits null field values. The + * schema generated for each field is a union of its declared type and + * null. */ + public static class AllowNull extends ReflectData { + + private static final AllowNull INSTANCE = new AllowNull(); + + /** Return the singleton instance. */ + public static AllowNull get() { return INSTANCE; } + + protected Schema createFieldSchema(Field field, Map<String, Schema> names) { + Schema schema = super.createFieldSchema(field, names); + return makeNullable(schema); + } + } + + private static final ReflectData INSTANCE = new ReflectData(); + + protected ReflectData() {} + + /** Return the singleton instance. */ + public static ReflectData get() { return INSTANCE; } + + @Override + public void setField(Object record, String name, int position, Object o) { + if (record instanceof IndexedRecord) { + super.setField(record, name, position, o); + return; + } + try { + getField(record.getClass(), name).set(record, o); + } catch (IllegalAccessException e) { + throw new AvroRuntimeException(e); + } + } + + @Override + public Object getField(Object record, String name, int position) { + if (record instanceof IndexedRecord) + return super.getField(record, name, position); + try { + return getField(record.getClass(), name).get(record); + } catch (IllegalAccessException e) { + throw new AvroRuntimeException(e); + } + } + + @Override + protected boolean isRecord(Object datum) { + if (datum == null) return false; + if (super.isRecord(datum)) return true; + return getSchema(datum.getClass()).getType() == Schema.Type.RECORD; + } + + @Override + protected boolean isArray(Object datum) { + if (datum == null) return false; + return (datum instanceof Collection) || datum.getClass().isArray(); + } + + @Override + protected boolean isBytes(Object datum) { + if (datum == null) return false; + if (super.isBytes(datum)) return true; + Class c = datum.getClass(); + return c.isArray() && c.getComponentType() == Byte.TYPE; + } + + @Override + protected Schema getRecordSchema(Object record) { + if (record instanceof GenericContainer) + return super.getRecordSchema(record); + return getSchema(record.getClass()); + } + + @Override + public boolean validate(Schema schema, Object datum) { + switch (schema.getType()) { + case ARRAY: + if (!datum.getClass().isArray()) + return super.validate(schema, datum); + int length = java.lang.reflect.Array.getLength(datum); + for (int i = 0; i < length; i++) + if (!validate(schema.getElementType(), + java.lang.reflect.Array.get(datum, i))) + return false; + return true; + default: + return super.validate(schema, datum); + } + } + + private static final Map<Class,Map<String,Field>> FIELD_CACHE = + new ConcurrentHashMap<Class,Map<String,Field>>(); + + /** Return the named field of the provided class. Implementation caches + * values, since this is used at runtime to get and set fields. */ + private static Field getField(Class c, String name) { + Map<String,Field> fields = FIELD_CACHE.get(c); + if (fields == null) { + fields = new ConcurrentHashMap<String,Field>(); + FIELD_CACHE.put(c, fields); + } + Field f = fields.get(name); + if (f == null) { + f = findField(c, name); + fields.put(name, f); + } + return f; + } + + private static Field findField(Class original, String name) { + Class c = original; + do { + try { + Field f = c.getDeclaredField(name); + f.setAccessible(true); + return f; + } catch (NoSuchFieldException e) {} + c = c.getSuperclass(); + } while (c != null); + throw new AvroRuntimeException("No field named "+name+" in: "+original); + } + + static final String CLASS_PROP = "java-class"; + static final String ELEMENT_PROP = "java-element-class"; + + static Class getClassProp(Schema schema, String prop) { + String name = schema.getProp(prop); + if (name == null) return null; + try { + return ClassLoadingUtils.loadClass(name); + } catch (ClassNotFoundException e) { + throw new AvroRuntimeException(e); + } + } + + private static final Class BYTES_CLASS = new byte[0].getClass(); + + @Override + public Class getClass(Schema schema) { + switch (schema.getType()) { + case ARRAY: + Class collectionClass = getClassProp(schema, CLASS_PROP); + if (collectionClass != null) + return collectionClass; + return java.lang.reflect.Array.newInstance(getClass(schema.getElementType()),0).getClass(); + case STRING: return String.class; + case BYTES: return BYTES_CLASS; + case INT: + if (Short.class.getName().equals(schema.getProp(CLASS_PROP))) + return Short.TYPE; + default: + return super.getClass(schema); + } + } + + @Override + @SuppressWarnings(value="unchecked") + protected Schema createSchema(Type type, Map<String,Schema> names) { + if (type instanceof GenericArrayType) { // generic array + Type component = ((GenericArrayType)type).getGenericComponentType(); + if (component == Byte.TYPE) // byte array + return Schema.create(Schema.Type.BYTES); + Schema result = Schema.createArray(createSchema(component, names)); + setElement(result, component); + return result; + } else if (type instanceof ParameterizedType) { + ParameterizedType ptype = (ParameterizedType)type; + Class raw = (Class)ptype.getRawType(); + Type[] params = ptype.getActualTypeArguments(); + if (Map.class.isAssignableFrom(raw)) { // Map + Type key = params[0]; + Type value = params[1]; + if (!(key == String.class)) + throw new AvroTypeException("Map key class not String: "+key); + return Schema.createMap(createSchema(value, names)); + } else if (Collection.class.isAssignableFrom(raw)) { // Collection + if (params.length != 1) + throw new AvroTypeException("No array type specified."); + Schema schema = Schema.createArray(createSchema(params[0], names)); + schema.addProp(CLASS_PROP, raw.getName()); + return schema; + } + } else if ((type == Short.class) || (type == Short.TYPE)) { + Schema result = Schema.create(Schema.Type.INT); + result.addProp(CLASS_PROP, Short.class.getName()); + return result; + } else if (type instanceof Class) { // Class + Class<?> c = (Class<?>)type; + if (c.isPrimitive() || Number.class.isAssignableFrom(c) + || c == Void.class || c == Boolean.class) // primitive + return super.createSchema(type, names); + if (c.isArray()) { // array + Class component = c.getComponentType(); + if (component == Byte.TYPE) // byte array + return Schema.create(Schema.Type.BYTES); + Schema result = Schema.createArray(createSchema(component, names)); + setElement(result, component); + return result; + } + if (CharSequence.class.isAssignableFrom(c)) // String + return Schema.create(Schema.Type.STRING); + String fullName = c.getName(); + Schema schema = names.get(fullName); + if (schema == null) { + String name = c.getSimpleName(); + String space = c.getPackage() == null ? "" : c.getPackage().getName(); + if (c.getEnclosingClass() != null) // nested class + space = c.getEnclosingClass().getName() + "$"; + Union union = c.getAnnotation(Union.class); + if (union != null) { // union annotated + return getAnnotatedUnion(union, names); + } else if (c.isAnnotationPresent(Stringable.class)){ // Stringable + Schema result = Schema.create(Schema.Type.STRING); + result.addProp(CLASS_PROP, c.getName()); + return result; + } else if (c.isEnum()) { // Enum + List<String> symbols = new ArrayList<String>(); + Enum[] constants = (Enum[])c.getEnumConstants(); + for (int i = 0; i < constants.length; i++) + symbols.add(constants[i].name()); + schema = Schema.createEnum(name, null /* doc */, space, symbols); + } else if (GenericFixed.class.isAssignableFrom(c)) { // fixed + int size = c.getAnnotation(FixedSize.class).value(); + schema = Schema.createFixed(name, null /* doc */, space, size); + } else if (IndexedRecord.class.isAssignableFrom(c)) { // specific + return super.createSchema(type, names); + } else { // record + List<Schema.Field> fields = new ArrayList<Schema.Field>(); + boolean error = Throwable.class.isAssignableFrom(c); + schema = Schema.createRecord(name, null /* doc */, space, error); + names.put(c.getName(), schema); + for (Field field : getFields(c)) + if ((field.getModifiers()&(Modifier.TRANSIENT|Modifier.STATIC))==0){ + Schema fieldSchema = createFieldSchema(field, names); + JsonNode defaultValue = null; + if (fieldSchema.getType() == Schema.Type.UNION) { + Schema defaultType = fieldSchema.getTypes().get(0); + if (defaultType.getType() == Schema.Type.NULL) { + defaultValue = NullNode.getInstance(); + } + } + fields.add(new Schema.Field(field.getName(), + fieldSchema, null /* doc */, defaultValue)); + } + if (error) // add Throwable message + fields.add(new Schema.Field("detailMessage", THROWABLE_MESSAGE, + null, null)); + schema.setFields(fields); + } + names.put(fullName, schema); + } + return schema; + } + return super.createSchema(type, names); + } + + private static final Schema THROWABLE_MESSAGE = + makeNullable(Schema.create(Schema.Type.STRING)); + + // if array element type is a class with a union annotation, note it + // this is required because we cannot set a property on the union itself + @SuppressWarnings(value="unchecked") + private void setElement(Schema schema, Type element) { + if (!(element instanceof Class)) return; + Class<?> c = (Class<?>)element; + Union union = c.getAnnotation(Union.class); + if (union != null) // element is annotated union + schema.addProp(ELEMENT_PROP, c.getName()); + } + + // construct a schema from a union annotation + private Schema getAnnotatedUnion(Union union, Map<String,Schema> names) { + List<Schema> branches = new ArrayList<Schema>(); + for (Class branch : union.value()) + branches.add(createSchema(branch, names)); + return Schema.createUnion(branches); + } + + /** Create and return a union of the null schema and the provided schema. */ + public static Schema makeNullable(Schema schema) { + return Schema.createUnion(Arrays.asList(Schema.create(Schema.Type.NULL), + schema)); + } + + // Return of this class and its superclasses to serialize. + // Not cached, since this is only used to create schemas, which are cached. + private Collection<Field> getFields(Class recordClass) { + Map<String,Field> fields = new LinkedHashMap<String,Field>(); + Class c = recordClass; + do { + if (c.getPackage() != null + && c.getPackage().getName().startsWith("java.")) + break; // skip java built-in classes + for (Field field : c.getDeclaredFields()) + if ((field.getModifiers() & (Modifier.TRANSIENT|Modifier.STATIC)) == 0) + if (fields.put(field.getName(), field) != null) + throw new AvroTypeException(c+" contains two fields named: "+field); + c = c.getSuperclass(); + } while (c != null); + return fields.values(); + } + + /** Create a schema for a field. */ + protected Schema createFieldSchema(Field field, Map<String, Schema> names) { + Schema schema = createSchema(field.getGenericType(), names); + if (field.isAnnotationPresent(Nullable.class)) // nullable + schema = makeNullable(schema); + return schema; + } + + /** Return the protocol for a Java interface. + * <p>Note that this requires that <a + * href="http://paranamer.codehaus.org/">Paranamer</a> is run over compiled + * interface declarations, since Java 6 reflection does not provide access to + * method parameter names. See Avro's build.xml for an example. */ + @Override + public Protocol getProtocol(Class iface) { + Protocol protocol = + new Protocol(iface.getSimpleName(), + iface.getPackage()==null?"":iface.getPackage().getName()); + Map<String,Schema> names = new LinkedHashMap<String,Schema>(); + Map<String,Message> messages = protocol.getMessages(); + for (Method method : iface.getMethods()) + if ((method.getModifiers() & Modifier.STATIC) == 0) { + String name = method.getName(); + if (messages.containsKey(name)) + throw new AvroTypeException("Two methods with same name: "+name); + messages.put(name, getMessage(method, protocol, names)); + } + + // reverse types, since they were defined in reference order + List<Schema> types = new ArrayList<Schema>(); + types.addAll(names.values()); + Collections.reverse(types); + protocol.setTypes(types); + + return protocol; + } + + private final Paranamer paranamer = new CachingParanamer(); + + private Message getMessage(Method method, Protocol protocol, + Map<String,Schema> names) { + List<Schema.Field> fields = new ArrayList<Schema.Field>(); + String[] paramNames = paranamer.lookupParameterNames(method); + Type[] paramTypes = method.getGenericParameterTypes(); + Annotation[][] annotations = method.getParameterAnnotations(); + for (int i = 0; i < paramTypes.length; i++) { + Schema paramSchema = getSchema(paramTypes[i], names); + for (int j = 0; j < annotations[i].length; j++) + if (annotations[i][j] instanceof Union) + paramSchema = getAnnotatedUnion(((Union)annotations[i][j]), names); + else if (annotations[i][j] instanceof Nullable) + paramSchema = makeNullable(paramSchema); + String paramName = paramNames.length == paramTypes.length + ? paramNames[i] + : paramSchema.getName()+i; + fields.add(new Schema.Field(paramName, paramSchema, + null /* doc */, null)); + } + Schema request = Schema.createRecord(fields); + + Union union = method.getAnnotation(Union.class); + Schema response = union == null + ? getSchema(method.getGenericReturnType(), names) + : getAnnotatedUnion(union, names); + if (method.isAnnotationPresent(Nullable.class)) // nullable + response = makeNullable(response); + + List<Schema> errs = new ArrayList<Schema>(); + errs.add(Protocol.SYSTEM_ERROR); // every method can throw + for (Type err : method.getGenericExceptionTypes()) + if (err != AvroRemoteException.class) + errs.add(getSchema(err, names)); + Schema errors = Schema.createUnion(errs); + + return protocol.createMessage(method.getName(), null /* doc */, request, response, errors); + } + + private Schema getSchema(Type type, Map<String,Schema> names) { + try { + return createSchema(type, names); + } catch (AvroTypeException e) { // friendly exception + throw new AvroTypeException("Error getting schema for "+type+": " + +e.getMessage(), e); + } + } + + @Override + protected int compare(Object o1, Object o2, Schema s, boolean equals) { + switch (s.getType()) { + case ARRAY: + if (!o1.getClass().isArray()) + break; + Schema elementType = s.getElementType(); + int l1 = java.lang.reflect.Array.getLength(o1); + int l2 = java.lang.reflect.Array.getLength(o2); + int l = Math.min(l1, l2); + for (int i = 0; i < l; i++) { + int compare = compare(java.lang.reflect.Array.get(o1, i), + java.lang.reflect.Array.get(o2, i), + elementType, equals); + if (compare != 0) return compare; + } + return l1 - l2; + case BYTES: + if (!o1.getClass().isArray()) + break; + byte[] b1 = (byte[])o1; + byte[] b2 = (byte[])o2; + return BinaryData.compareBytes(b1, 0, b1.length, b2, 0, b2.length); + } + return super.compare(o1, o2, s, equals); + } + +} http://git-wip-us.apache.org/repos/asf/servicemix-bundles/blob/a67ba0b1/avro-1.8.0/src/main/java/org/apache/avro/specific/SpecificData.java ---------------------------------------------------------------------- diff --git a/avro-1.8.0/src/main/java/org/apache/avro/specific/SpecificData.java b/avro-1.8.0/src/main/java/org/apache/avro/specific/SpecificData.java new file mode 100644 index 0000000..5714ab6 --- /dev/null +++ b/avro-1.8.0/src/main/java/org/apache/avro/specific/SpecificData.java @@ -0,0 +1,272 @@ +/** + * 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.avro.specific; + +import java.util.Map; +import java.util.Collection; +import java.util.List; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.LinkedHashMap; +import java.nio.ByteBuffer; +import java.lang.reflect.Constructor; +import java.lang.reflect.ParameterizedType; + +import org.apache.avro.Schema; +import org.apache.avro.Protocol; +import org.apache.avro.AvroRuntimeException; +import org.apache.avro.AvroTypeException; +import org.apache.avro.Schema.Type; +import org.apache.avro.generic.GenericData; +import org.apache.avro.util.ClassLoadingUtils; + +/** Utilities for generated Java classes and interfaces. */ +public class SpecificData extends GenericData { + + private static final SpecificData INSTANCE = new SpecificData(); + + private final ClassLoader classLoader; + + private static final Class<?>[] NO_ARG = new Class[]{}; + private static final Class<?>[] SCHEMA_ARG = new Class[]{Schema.class}; + private static final Map<Class,Constructor> CTOR_CACHE = + new ConcurrentHashMap<Class,Constructor>(); + + /** For subclasses. Applications normally use {@link org.apache.avro.specific.SpecificData#get()}. */ + protected SpecificData() { this(SpecificData.class.getClassLoader()); } + + /** Construct with a specific classloader. */ + public SpecificData(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + /** Return the singleton instance. */ + public static SpecificData get() { return INSTANCE; } + + @Override + protected boolean isEnum(Object datum) { + return datum instanceof Enum || super.isEnum(datum); + } + + @Override + protected Schema getEnumSchema(Object datum) { + return (datum instanceof Enum) + ? getSchema(datum.getClass()) + : super.getEnumSchema(datum); + } + + private Map<String,Class> classCache = new ConcurrentHashMap<String,Class>(); + + private static final Class NO_CLASS = new Object(){}.getClass(); + private static final Schema NULL_SCHEMA = Schema.create(Schema.Type.NULL); + + /** Return the class that implements a schema, or null if none exists. */ + public Class getClass(Schema schema) { + switch (schema.getType()) { + case FIXED: + case RECORD: + case ENUM: + String name = schema.getFullName(); + if (name == null) return null; + Class c = classCache.get(name); + if (c == null) { + try { + c = ClassLoadingUtils.loadClass(classLoader,getClassName(schema)); + } catch (ClassNotFoundException e) { + c = NO_CLASS; + } + classCache.put(name, c); + } + return c == NO_CLASS ? null : c; + case ARRAY: return List.class; + case MAP: return Map.class; + case UNION: + List<Schema> types = schema.getTypes(); // elide unions with null + if ((types.size() == 2) && types.contains(NULL_SCHEMA)) + return getClass(types.get(types.get(0).equals(NULL_SCHEMA) ? 1 : 0)); + return Object.class; + case STRING: + if (STRING_TYPE_STRING.equals(schema.getProp(STRING_PROP))) + return String.class; + return CharSequence.class; + case BYTES: return ByteBuffer.class; + case INT: return Integer.TYPE; + case LONG: return Long.TYPE; + case FLOAT: return Float.TYPE; + case DOUBLE: return Double.TYPE; + case BOOLEAN: return Boolean.TYPE; + case NULL: return Void.TYPE; + default: throw new AvroRuntimeException("Unknown type: "+schema); + } + } + + /** Returns the Java class name indicated by a schema's name and namespace. */ + public static String getClassName(Schema schema) { + String namespace = schema.getNamespace(); + String name = schema.getName(); + if (namespace == null || "".equals(namespace)) + return name; + String dot = namespace.endsWith("$") ? "" : "."; + return namespace + dot + name; + } + + private final WeakHashMap<java.lang.reflect.Type,Schema> schemaCache = + new WeakHashMap<java.lang.reflect.Type,Schema>(); + + /** Find the schema for a Java type. */ + public Schema getSchema(java.lang.reflect.Type type) { + Schema schema = schemaCache.get(type); + if (schema == null) { + schema = createSchema(type, new LinkedHashMap<String,Schema>()); + schemaCache.put(type, schema); + } + return schema; + } + + /** Create the schema for a Java type. */ + @SuppressWarnings(value="unchecked") + protected Schema createSchema(java.lang.reflect.Type type, + Map<String,Schema> names) { + if (type instanceof Class + && CharSequence.class.isAssignableFrom((Class)type)) + return Schema.create(Type.STRING); + else if (type == ByteBuffer.class) + return Schema.create(Type.BYTES); + else if ((type == Integer.class) || (type == Integer.TYPE)) + return Schema.create(Type.INT); + else if ((type == Long.class) || (type == Long.TYPE)) + return Schema.create(Type.LONG); + else if ((type == Float.class) || (type == Float.TYPE)) + return Schema.create(Type.FLOAT); + else if ((type == Double.class) || (type == Double.TYPE)) + return Schema.create(Type.DOUBLE); + else if ((type == Boolean.class) || (type == Boolean.TYPE)) + return Schema.create(Type.BOOLEAN); + else if ((type == Void.class) || (type == Void.TYPE)) + return Schema.create(Type.NULL); + else if (type instanceof ParameterizedType) { + ParameterizedType ptype = (ParameterizedType)type; + Class raw = (Class)ptype.getRawType(); + java.lang.reflect.Type[] params = ptype.getActualTypeArguments(); + if (Collection.class.isAssignableFrom(raw)) { // array + if (params.length != 1) + throw new AvroTypeException("No array type specified."); + return Schema.createArray(createSchema(params[0], names)); + } else if (Map.class.isAssignableFrom(raw)) { // map + java.lang.reflect.Type key = params[0]; + java.lang.reflect.Type value = params[1]; + if (!(type instanceof Class + && CharSequence.class.isAssignableFrom((Class)type))) + throw new AvroTypeException("Map key class not CharSequence: "+key); + return Schema.createMap(createSchema(value, names)); + } else { + return createSchema(raw, names); + } + } else if (type instanceof Class) { // class + Class c = (Class)type; + String fullName = c.getName(); + Schema schema = names.get(fullName); + if (schema == null) + try { + schema = (Schema)(c.getDeclaredField("SCHEMA$").get(null)); + + if (!fullName.equals(getClassName(schema))) + // HACK: schema mismatches class. maven shade plugin? try replacing. + schema = Schema.parse + (schema.toString().replace(schema.getNamespace(), + c.getPackage().getName())); + } catch (NoSuchFieldException e) { + throw new AvroRuntimeException(e); + } catch (IllegalAccessException e) { + throw new AvroRuntimeException(e); + } + names.put(fullName, schema); + return schema; + } + throw new AvroTypeException("Unknown type: "+type); + } + + /** Return the protocol for a Java interface. */ + public Protocol getProtocol(Class iface) { + try { + Protocol p = (Protocol)(iface.getDeclaredField("PROTOCOL").get(null)); + if (!p.getNamespace().equals(iface.getPackage().getName())) + // HACK: protocol mismatches iface. maven shade plugin? try replacing. + p = Protocol.parse(p.toString().replace(p.getNamespace(), + iface.getPackage().getName())); + return p; + } catch (NoSuchFieldException e) { + throw new AvroRuntimeException(e); + } catch (IllegalAccessException e) { + throw new AvroRuntimeException(e); + } + } + + @Override + protected int compare(Object o1, Object o2, Schema s, boolean eq) { + switch (s.getType()) { + case ENUM: + if (o1 instanceof Enum) + return ((Enum)o1).ordinal() - ((Enum)o2).ordinal(); + default: + return super.compare(o1, o2, s, eq); + } + } + + /** Create an instance of a class. If the class implements {@link + * org.apache.avro.specific.SpecificData.SchemaConstructable}, call a constructor with a {@link + * org.apache.avro.Schema} parameter, otherwise use a no-arg constructor. */ + @SuppressWarnings("unchecked") + public static Object newInstance(Class c, Schema s) { + boolean useSchema = SchemaConstructable.class.isAssignableFrom(c); + Object result; + try { + Constructor meth = (Constructor)CTOR_CACHE.get(c); + if (meth == null) { + meth = c.getDeclaredConstructor(useSchema ? SCHEMA_ARG : NO_ARG); + meth.setAccessible(true); + CTOR_CACHE.put(c, meth); + } + result = meth.newInstance(useSchema ? new Object[]{s} : (Object[])null); + } catch (Exception e) { + throw new RuntimeException(e); + } + return result; + } + + @Override + public Object createFixed(Object old, Schema schema) { + Class c = SpecificData.get().getClass(schema); + if (c == null) return super.createFixed(old, schema); // punt to generic + return c.isInstance(old) ? old : newInstance(c, schema); + } + + @Override + public Object newRecord(Object old, Schema schema) { + Class c = SpecificData.get().getClass(schema); + if (c == null) return super.newRecord(old, schema); // punt to generic + return (c.isInstance(old) ? old : newInstance(c, schema)); + } + + /** Tag interface that indicates that a class has a one-argument constructor + * that accepts a Schema. + * @see SpecificDatumReader#newInstance + */ + public interface SchemaConstructable {} + +} http://git-wip-us.apache.org/repos/asf/servicemix-bundles/blob/a67ba0b1/avro-1.8.0/src/main/java/org/apache/avro/util/ClassLoadingUtils.java ---------------------------------------------------------------------- diff --git a/avro-1.8.0/src/main/java/org/apache/avro/util/ClassLoadingUtils.java b/avro-1.8.0/src/main/java/org/apache/avro/util/ClassLoadingUtils.java new file mode 100644 index 0000000..cc669b2 --- /dev/null +++ b/avro-1.8.0/src/main/java/org/apache/avro/util/ClassLoadingUtils.java @@ -0,0 +1,105 @@ +/** + * 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.avro.util; + +public class ClassLoadingUtils { + + private ClassLoadingUtils() { + //Utility Class + } + + /** + * Loads a class using the class loader. + * 1. The class loader of the current class is being used. + * 2. The thread context class loader is being used. + * If both approaches fail, returns null. + * + * @param className The name of the class to load. + * @return The class or null if no class loader could load the class. + */ + public static Class<?> loadClass(String className) throws ClassNotFoundException { + return ClassLoadingUtils.loadClass(ClassLoadingUtils.class, className); + } + + /** + * Loads a class using the class loader. + * 1. The class loader of the context class is being used. + * 2. The thread context class loader is being used. + * If both approaches fail, returns null. + * + * @param contextClass The name of a context class to use. + * @param className The name of the class to load + * @return The class or null if no class loader could load the class. + */ + public static Class<?> loadClass(Class<?> contextClass, String className) throws ClassNotFoundException { + Class<?> clazz = null; + if (contextClass.getClassLoader() != null) { + clazz = loadClassFromClassLoader(contextClass.getClassLoader(), className); + } + if (clazz == null && Thread.currentThread().getContextClassLoader() != null) { + clazz = loadClassFromClassLoader(Thread.currentThread().getContextClassLoader(), className); + } + if (clazz == null) { + throw new ClassNotFoundException("Failed to load class" + className); + } + return clazz; + } + + /** + * Loads a class using the class loader. + * 1. The class loader of the context class is being used. + * 2. The thread context class loader is being used. + * If both approaches fail, returns null. + * + * @param classLoader The classloader to use. + * @param className The name of the class to load + * @return The class or null if no class loader could load the class. + */ + public static Class<?> loadClass(ClassLoader classLoader, String className) throws ClassNotFoundException { + Class<?> clazz = null; + if (classLoader != null) { + clazz = loadClassFromClassLoader(classLoader, className); + } + if (clazz == null && Thread.currentThread().getContextClassLoader() != null) { + clazz = loadClassFromClassLoader(Thread.currentThread().getContextClassLoader(),className); + } + if (clazz == null) { + throw new ClassNotFoundException("Failed to load class" + className); + } + return clazz; + } + + /** + * Loads a {@link Class} from the specified {@link ClassLoader} without throwing {@ClassNotFoundException}. + * + * @param className + * @param classLoader + * @return + */ + private static Class<?> loadClassFromClassLoader(ClassLoader classLoader, String className) { + Class<?> clazz = null; + if (classLoader != null && className != null) { + try { + clazz = classLoader.loadClass(className); + } catch (ClassNotFoundException e) { + //Ignore and return null + } + } + return clazz; + } +} http://git-wip-us.apache.org/repos/asf/servicemix-bundles/blob/a67ba0b1/avro-1.8.0/src/main/resources/OSGI-INF/bundle.info ---------------------------------------------------------------------- diff --git a/avro-1.8.0/src/main/resources/OSGI-INF/bundle.info b/avro-1.8.0/src/main/resources/OSGI-INF/bundle.info new file mode 100644 index 0000000..e68ffdb --- /dev/null +++ b/avro-1.8.0/src/main/resources/OSGI-INF/bundle.info @@ -0,0 +1,11 @@ +\u001B[1mSYNOPSIS\u001B[0m + ${project.description} + + Original Maven URL: + \u001B[33mmvn:${pkgGroupId}/${pkgArtifactId}-core/${pkgVersion}\u001B[0m + +\u001B[1mDESCRIPTION\u001B[0m + Apache Avro⢠is a data serialization system. + +\u001B[1mSEE ALSO\u001B[0m + \u001B[36mhttp://avro.apache.org\u001B[0m http://git-wip-us.apache.org/repos/asf/servicemix-bundles/blob/a67ba0b1/avro-ipc-1.8.0/pom.xml ---------------------------------------------------------------------- diff --git a/avro-ipc-1.8.0/pom.xml b/avro-ipc-1.8.0/pom.xml new file mode 100644 index 0000000..dbd2f6a --- /dev/null +++ b/avro-ipc-1.8.0/pom.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <!-- + + 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. + --> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.servicemix.bundles</groupId> + <artifactId>bundles-pom</artifactId> + <version>12</version> + <relativePath>../bundles-pom/pom.xml</relativePath> + </parent> + + <groupId>org.apache.servicemix.bundles</groupId> + <artifactId>org.apache.servicemix.bundles.avro-ipc</artifactId> + <version>1.8.0_1-SNAPSHOT</version> + <packaging>bundle</packaging> + <name>Apache ServiceMix :: Bundles :: ${pkgArtifactId}</name> + <description>This OSGi bundle wraps ${pkgArtifactId} ${pkgVersion} jar file.</description> + + <scm> + <connection>scm:git:https://git-wip-us.apache.org/repos/asf/servicemix-bundles.git</connection> + <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/servicemix-bundles.git</developerConnection> + <url>https://git-wip-us.apache.org/repos/asf?p=servicemix-bundles.git</url> + <tag>HEAD</tag> + </scm> + + <properties> + <pkgGroupId>org.apache.avro</pkgGroupId> + <pkgArtifactId>avro-ipc</pkgArtifactId> + <pkgVersion>1.8.0</pkgVersion> + <servicemix.osgi.export> + org.apache.avro.ipc*;version="${project.version}";-noimport:=true;-split-package:=merge-first + </servicemix.osgi.export> + <servicemix.osgi.import.pkg> + javax.security*, + org.apache.avro*;version="[1.7,2)", + javax.servlet*;resolution:=optional, + org.apache.velocity*;resolution:=optional, + org.jboss.netty*;resolution:=optional, + org.mortbay*;resolution:=optional, + org.slf4j;resolution:=optional + </servicemix.osgi.import.pkg> + </properties> + + <dependencies> + <dependency> + <groupId>${pkgGroupId}</groupId> + <artifactId>${pkgArtifactId}</artifactId> + <version>${pkgVersion}</version> + <optional>false</optional> + </dependency> + + <!-- sources --> + <dependency> + <groupId>${pkgGroupId}</groupId> + <artifactId>${pkgArtifactId}</artifactId> + <version>${pkgVersion}</version> + <classifier>sources</classifier> + <optional>false</optional> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>1.4</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <artifactSet> + <includes> + <include>${pkgGroupId}:${pkgArtifactId}</include> + </includes> + </artifactSet> + <filters> + <filter> + <artifact>${pkgGroupId}:${pkgArtifactId}</artifact> + <excludes> + <exclude>**</exclude> + </excludes> + </filter> + </filters> + <promoteTransitiveDependencies>true</promoteTransitiveDependencies> + <createDependencyReducedPom>true</createDependencyReducedPom> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/servicemix-bundles/blob/a67ba0b1/avro-ipc-1.8.0/src/main/resources/OSGI-INF/bundle.info ---------------------------------------------------------------------- diff --git a/avro-ipc-1.8.0/src/main/resources/OSGI-INF/bundle.info b/avro-ipc-1.8.0/src/main/resources/OSGI-INF/bundle.info new file mode 100644 index 0000000..e68ffdb --- /dev/null +++ b/avro-ipc-1.8.0/src/main/resources/OSGI-INF/bundle.info @@ -0,0 +1,11 @@ +\u001B[1mSYNOPSIS\u001B[0m + ${project.description} + + Original Maven URL: + \u001B[33mmvn:${pkgGroupId}/${pkgArtifactId}-core/${pkgVersion}\u001B[0m + +\u001B[1mDESCRIPTION\u001B[0m + Apache Avro⢠is a data serialization system. + +\u001B[1mSEE ALSO\u001B[0m + \u001B[36mhttp://avro.apache.org\u001B[0m http://git-wip-us.apache.org/repos/asf/servicemix-bundles/blob/a67ba0b1/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 78e27a2..2add63c 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,8 @@ <module>aws-java-sdk-1.10.52</module> <module>braintree-java-2.55.0</module> <module>esapi-2.1.0.1</module> + <module>avro-1.8.0</module> + <module>avro-ipc-1.8.0</module> </modules> </project>
